Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "RadioButton.hxx"
30 : : #include "GroupManager.hxx"
31 : : #include "property.hxx"
32 : : #include "property.hrc"
33 : : #include "services.hxx"
34 : : #include <tools/debug.hxx>
35 : : #include <comphelper/extract.hxx>
36 : : #include <comphelper/basicio.hxx>
37 : : #include <com/sun/star/container/XIndexAccess.hpp>
38 : : #include <com/sun/star/awt/XVclWindowPeer.hpp>
39 : :
40 : : //.........................................................................
41 : : namespace frm
42 : : {
43 : : using namespace ::com::sun::star::uno;
44 : : using namespace ::com::sun::star::sdb;
45 : : using namespace ::com::sun::star::sdbc;
46 : : using namespace ::com::sun::star::sdbcx;
47 : : using namespace ::com::sun::star::beans;
48 : : using namespace ::com::sun::star::container;
49 : : using namespace ::com::sun::star::form;
50 : : using namespace ::com::sun::star::awt;
51 : : using namespace ::com::sun::star::io;
52 : : using namespace ::com::sun::star::lang;
53 : : using namespace ::com::sun::star::util;
54 : : using namespace ::com::sun::star::form::binding;
55 : :
56 : : //==================================================================
57 : : //------------------------------------------------------------------------------
58 : 12 : InterfaceRef SAL_CALL ORadioButtonControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException)
59 : : {
60 [ + - ]: 12 : return *(new ORadioButtonControl(_rxFactory));
61 : : }
62 : :
63 : : //------------------------------------------------------------------------------
64 : 0 : StringSequence SAL_CALL ORadioButtonControl::getSupportedServiceNames() throw(RuntimeException)
65 : : {
66 : 0 : StringSequence aSupported = OBoundControl::getSupportedServiceNames();
67 [ # # ]: 0 : aSupported.realloc(aSupported.getLength() + 1);
68 : :
69 [ # # ]: 0 : ::rtl::OUString* pArray = aSupported.getArray();
70 [ # # ]: 0 : pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_RADIOBUTTON;
71 : 0 : return aSupported;
72 : : }
73 : :
74 : :
75 : : //------------------------------------------------------------------
76 : 12 : ORadioButtonControl::ORadioButtonControl(const Reference<XMultiServiceFactory>& _rxFactory)
77 [ + - ]: 12 : :OBoundControl(_rxFactory, VCL_CONTROL_RADIOBUTTON)
78 : : {
79 : 12 : }
80 : :
81 : : //------------------------------------------------------------------
82 : 34 : void SAL_CALL ORadioButtonControl::createPeer(const Reference<starawt::XToolkit>& _rxToolkit, const Reference<starawt::XWindowPeer>& _rxParent) throw (RuntimeException)
83 : : {
84 : 34 : OBoundControl::createPeer(_rxToolkit, _rxParent);
85 : :
86 : : // switch off the auto-toggle, we do this ourself ....
87 : : // (formerly this switch-off was done in the toolkit - but the correct place is here ...)
88 : : // Reference< XVclWindowPeer > xVclWindowPeer( getPeer(), UNO_QUERY );
89 : : // if (xVclWindowPeer.is())
90 : : // xVclWindowPeer->setProperty(::rtl::OUString("AutoToggle"), ::cppu::bool2any(sal_False));
91 : : // new order: do _not_ switch off the auto toggle because:
92 : : // * today, it is not necessary anymore to handle the toggling ourself (everything works fine without it)
93 : : // * without auto toggle, the AccessibleEvents as fired by the radio buttons are
94 : : // a. newly checked button: "unchecked"->"checked"
95 : : // b. previously checked button: "checked"->"unchecked"
96 : : // This is deadly for AT-tools, which then get the "unchecked" event _immediately_ after the "checked" event,
97 : : // and only read the latter. This makes radio buttons pretty unusable in form documents.
98 : : // So we switched AutoToggle _on_, again, because then VCL can handle the notifications, and will send
99 : : // them in the proper order.
100 : 34 : }
101 : :
102 : : //==================================================================
103 : 34 : InterfaceRef SAL_CALL ORadioButtonModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException)
104 : : {
105 [ + - ]: 34 : return *(new ORadioButtonModel(_rxFactory));
106 : : }
107 : :
108 : : //------------------------------------------------------------------
109 : : DBG_NAME( ORadioButtonModel )
110 : : //------------------------------------------------------------------
111 : 34 : ORadioButtonModel::ORadioButtonModel(const Reference<XMultiServiceFactory>& _rxFactory)
112 [ + - ][ + - ]: 34 : :OReferenceValueComponent( _rxFactory, VCL_CONTROLMODEL_RADIOBUTTON, FRM_SUN_CONTROL_RADIOBUTTON,sal_True )
113 : : // use the old control name for compytibility reasons
114 : : {
115 : : DBG_CTOR( ORadioButtonModel, NULL );
116 : :
117 : 34 : m_nClassId = FormComponentType::RADIOBUTTON;
118 [ + - ]: 34 : m_aLabelServiceName = FRM_SUN_COMPONENT_GROUPBOX;
119 [ + - ][ + - ]: 34 : initValueProperty( PROPERTY_STATE, PROPERTY_ID_STATE );
120 [ + - ][ + - ]: 34 : startAggregatePropertyListening( PROPERTY_GROUP_NAME );
121 : 34 : }
122 : :
123 : : //------------------------------------------------------------------
124 : 2 : ORadioButtonModel::ORadioButtonModel( const ORadioButtonModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory )
125 : 2 : :OReferenceValueComponent( _pOriginal, _rxFactory )
126 : : {
127 : : DBG_CTOR( ORadioButtonModel, NULL );
128 : 2 : }
129 : :
130 : : //------------------------------------------------------------------------------
131 : 24 : ORadioButtonModel::~ORadioButtonModel()
132 : : {
133 : : DBG_DTOR( ORadioButtonModel, NULL );
134 [ - + ]: 48 : }
135 : :
136 : : // XCloneable
137 : : //------------------------------------------------------------------------------
138 [ + - ][ + - ]: 2 : IMPLEMENT_DEFAULT_CLONING( ORadioButtonModel )
139 : :
140 : : // XServiceInfo
141 : : //------------------------------------------------------------------------------
142 : 14 : StringSequence SAL_CALL ORadioButtonModel::getSupportedServiceNames() throw(RuntimeException)
143 : : {
144 : 14 : StringSequence aSupported = OReferenceValueComponent::getSupportedServiceNames();
145 : :
146 : 14 : sal_Int32 nOldLen = aSupported.getLength();
147 [ + - ]: 14 : aSupported.realloc( nOldLen + 8 );
148 [ + - ]: 14 : ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen;
149 : :
150 [ + - ]: 14 : *pStoreTo++ = BINDABLE_CONTROL_MODEL;
151 [ + - ]: 14 : *pStoreTo++ = DATA_AWARE_CONTROL_MODEL;
152 [ + - ]: 14 : *pStoreTo++ = VALIDATABLE_CONTROL_MODEL;
153 : :
154 [ + - ]: 14 : *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL;
155 [ + - ]: 14 : *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL;
156 : :
157 [ + - ]: 14 : *pStoreTo++ = FRM_SUN_COMPONENT_RADIOBUTTON;
158 [ + - ]: 14 : *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_RADIOBUTTON;
159 [ + - ]: 14 : *pStoreTo++ = BINDABLE_DATABASE_RADIO_BUTTON;
160 : :
161 : 14 : return aSupported;
162 : : }
163 : :
164 : : //------------------------------------------------------------------------------
165 : 54 : void ORadioButtonModel::SetSiblingPropsTo(const ::rtl::OUString& rPropName, const Any& rValue)
166 : : {
167 : : // my name
168 : 54 : ::rtl::OUString sMyGroup;
169 [ + - ][ + - ]: 54 : if (hasProperty(PROPERTY_GROUP_NAME, this))
[ + - ][ + - ]
170 [ + - ][ + - ]: 54 : this->getPropertyValue(PROPERTY_GROUP_NAME) >>= sMyGroup;
171 [ + + ]: 54 : if (sMyGroup.isEmpty())
172 : 28 : sMyGroup = m_aName;
173 : :
174 : : // Iterate over my siblings
175 [ + - ][ + - ]: 54 : Reference<XIndexAccess> xIndexAccess(getParent(), UNO_QUERY);
176 [ + - ]: 54 : if (xIndexAccess.is())
177 : : {
178 : 54 : Reference<XPropertySet> xMyProps;
179 [ + - ][ + - ]: 54 : query_interface(static_cast<XWeak*>(this), xMyProps);
180 : 54 : ::rtl::OUString sCurrentGroup;
181 [ + - ][ + - ]: 54 : sal_Int32 nNumSiblings = xIndexAccess->getCount();
182 [ + + ]: 162 : for (sal_Int32 i=0; i<nNumSiblings; ++i)
183 : : {
184 [ + - ][ + - ]: 108 : Reference<XPropertySet> xSiblingProperties(*(InterfaceRef*)xIndexAccess->getByIndex(i).getValue(), UNO_QUERY);
[ + - ]
185 [ - + ]: 108 : if (!xSiblingProperties.is())
186 : 0 : continue;
187 [ + - ][ + + ]: 108 : if (xMyProps == xSiblingProperties)
188 : 54 : continue; // do not set myself
189 : :
190 : : // Only if it's a RadioButton
191 [ + - ][ + - ]: 54 : if (!hasProperty(PROPERTY_CLASSID, xSiblingProperties))
[ - + ]
192 : 0 : continue;
193 : 54 : sal_Int16 nType = 0;
194 [ + - ][ + - ]: 54 : xSiblingProperties->getPropertyValue(PROPERTY_CLASSID) >>= nType;
[ + - ]
195 [ + - ]: 54 : if (nType != FormComponentType::RADIOBUTTON)
196 : 54 : continue;
197 : :
198 : : // The group association is attached to the name
199 [ # # ]: 0 : sCurrentGroup = OGroupManager::GetGroupName( xSiblingProperties );
200 [ # # ]: 0 : if (sCurrentGroup == sMyGroup)
201 [ # # ][ # # ]: 0 : xSiblingProperties->setPropertyValue(rPropName, rValue);
202 [ - + ]: 162 : }
203 : 54 : }
204 : 54 : }
205 : :
206 : : //------------------------------------------------------------------------------
207 : 272 : void ORadioButtonModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue) throw (Exception)
208 : : {
209 : 272 : OReferenceValueComponent::setFastPropertyValue_NoBroadcast( nHandle, rValue );
210 : :
211 : : // if the label control changed ...
212 [ - + ]: 272 : if (nHandle == PROPERTY_ID_CONTROLLABEL)
213 : : { // ... forward this to our siblings
214 [ # # ]: 0 : SetSiblingPropsTo(PROPERTY_CONTROLLABEL, rValue);
215 : : }
216 : :
217 : : // If the ControlSource property has changed ...
218 [ + + ]: 272 : if (nHandle == PROPERTY_ID_CONTROLSOURCE)
219 : : { // ... I have to pass the new ControlSource to my siblings, which are in the same RadioButton group as I am
220 [ + - ]: 32 : SetSiblingPropsTo(PROPERTY_CONTROLSOURCE, rValue);
221 : : }
222 : :
223 : : // The other way: if my name changes ...
224 [ + + ]: 272 : if (nHandle == PROPERTY_ID_NAME)
225 : : {
226 : 59 : setControlSource();
227 : : }
228 : :
229 [ + + ]: 272 : if (nHandle == PROPERTY_ID_DEFAULT_STATE)
230 : : {
231 : : sal_Int16 nValue;
232 : 25 : rValue >>= nValue;
233 [ + + ]: 25 : if (1 == nValue)
234 : : { // Reset the 'default checked' for all Radios of the same group.
235 : : // Because (as the Highlander already knew): "There can be only one"
236 : 9 : Any aZero;
237 : 9 : nValue = 0;
238 [ + - ]: 9 : aZero <<= nValue;
239 [ + - ][ + - ]: 25 : SetSiblingPropsTo(PROPERTY_DEFAULT_STATE, aZero);
240 : : }
241 : : }
242 : 272 : }
243 : :
244 : 91 : void ORadioButtonModel::setControlSource()
245 : : {
246 [ + - ][ + - ]: 91 : Reference<XIndexAccess> xIndexAccess(getParent(), UNO_QUERY);
247 [ + + ]: 91 : if (xIndexAccess.is())
248 : : {
249 : 72 : ::rtl::OUString sName, sGroupName;
250 : :
251 [ + - ][ + - ]: 72 : if (hasProperty(PROPERTY_GROUP_NAME, this))
[ + - ][ + - ]
252 [ + - ][ + - ]: 72 : this->getPropertyValue(PROPERTY_GROUP_NAME) >>= sGroupName;
253 [ + - ][ + - ]: 72 : this->getPropertyValue(PROPERTY_NAME) >>= sName;
254 : :
255 : 72 : Reference<XPropertySet> xMyProps;
256 [ + - ][ + - ]: 72 : query_interface(static_cast<XWeak*>(this), xMyProps);
257 [ + - ][ + - ]: 234 : for (sal_Int32 i=0; i<xIndexAccess->getCount(); ++i)
[ + + ]
258 : : {
259 [ + - ][ + - ]: 171 : Reference<XPropertySet> xSiblingProperties(*(InterfaceRef*)xIndexAccess->getByIndex(i).getValue(), UNO_QUERY);
[ + - ]
260 [ - + ]: 171 : if (!xSiblingProperties.is())
261 : 0 : continue;
262 : :
263 [ + - ][ + + ]: 171 : if (xMyProps == xSiblingProperties)
264 : : // Only if I didn't find myself
265 : 63 : continue;
266 : :
267 : 108 : sal_Int16 nType = 0;
268 [ + - ][ + - ]: 108 : xSiblingProperties->getPropertyValue(PROPERTY_CLASSID) >>= nType;
[ + - ]
269 [ + + ]: 108 : if (nType != FormComponentType::RADIOBUTTON)
270 : : // Only RadioButtons
271 : 72 : continue;
272 : :
273 : 36 : ::rtl::OUString sSiblingName, sSiblingGroupName;
274 [ + - ][ + - ]: 36 : if (hasProperty(PROPERTY_GROUP_NAME, xSiblingProperties))
[ + - ]
275 [ + - ][ + - ]: 36 : xSiblingProperties->getPropertyValue(PROPERTY_GROUP_NAME) >>= sSiblingGroupName;
[ + - ]
276 [ + - ][ + - ]: 36 : xSiblingProperties->getPropertyValue(PROPERTY_NAME) >>= sSiblingName;
[ + - ]
277 : :
278 [ + - + - : 117 : if ((sGroupName.isEmpty() && sSiblingGroupName.isEmpty() && // (no group name
+ + + + +
- ][ + + ]
[ + + ]
279 : 18 : sName == sSiblingName) || // names match) or
280 : 54 : (!sGroupName.isEmpty() && !sSiblingGroupName.isEmpty() && // (have group name
281 : 9 : sGroupName == sSiblingGroupName)) // they match)
282 : : {
283 [ + - ][ + - ]: 36 : setPropertyValue(PROPERTY_CONTROLSOURCE, xSiblingProperties->getPropertyValue(PROPERTY_CONTROLSOURCE));
[ + - ][ + - ]
[ + - ]
284 : : break;
285 : : }
286 [ + + ][ + + ]: 234 : }
[ + + + ]
287 : 91 : }
288 : 91 : }
289 : :
290 : : //------------------------------------------------------------------------------
291 : 38 : void ORadioButtonModel::describeFixedProperties( Sequence< Property >& _rProps ) const
292 : : {
293 : 38 : BEGIN_DESCRIBE_PROPERTIES( 1, OReferenceValueComponent )
294 [ + - ]: 38 : DECL_PROP1(TABINDEX, sal_Int16, BOUND);
295 : : END_DESCRIBE_PROPERTIES();
296 : 38 : }
297 : :
298 : : //------------------------------------------------------------------------------
299 : 2 : ::rtl::OUString SAL_CALL ORadioButtonModel::getServiceName() throw(RuntimeException)
300 : : {
301 : 2 : return FRM_COMPONENT_RADIOBUTTON; // old (non-sun) name for compatibility !
302 : : }
303 : :
304 : : //------------------------------------------------------------------------------
305 : 2 : void SAL_CALL ORadioButtonModel::write(const Reference<XObjectOutputStream>& _rxOutStream)
306 : : throw(IOException, RuntimeException)
307 : : {
308 : 2 : OReferenceValueComponent::write(_rxOutStream);
309 : :
310 : : // Version
311 : 2 : _rxOutStream->writeShort(0x0003);
312 : :
313 : : // Properties
314 : 2 : _rxOutStream << getReferenceValue();
315 : 2 : _rxOutStream << (sal_Int16)getDefaultChecked();
316 : 2 : writeHelpTextCompatibly(_rxOutStream);
317 : :
318 : : // from version 0x0003 : common properties
319 : 2 : writeCommonProperties(_rxOutStream);
320 : 2 : }
321 : :
322 : : //------------------------------------------------------------------------------
323 : 2 : void SAL_CALL ORadioButtonModel::read(const Reference<XObjectInputStream>& _rxInStream) throw(IOException, RuntimeException)
324 : : {
325 [ + - ]: 2 : OReferenceValueComponent::read(_rxInStream);
326 [ + - ]: 2 : ::osl::MutexGuard aGuard(m_aMutex);
327 : :
328 : : // Version
329 [ + - ][ + - ]: 2 : sal_uInt16 nVersion = _rxInStream->readShort();
330 : :
331 : 2 : ::rtl::OUString sReferenceValue;
332 : 2 : sal_Int16 nDefaultChecked( 0 );
333 [ - - + - ]: 2 : switch (nVersion)
334 : : {
335 : : case 0x0001 :
336 [ # # ]: 0 : _rxInStream >> sReferenceValue;
337 [ # # ]: 0 : _rxInStream >> nDefaultChecked;
338 : 0 : break;
339 : : case 0x0002 :
340 [ # # ]: 0 : _rxInStream >> sReferenceValue;
341 [ # # ]: 0 : _rxInStream >> nDefaultChecked;
342 [ # # ]: 0 : readHelpTextCompatibly(_rxInStream);
343 : 0 : break;
344 : : case 0x0003 :
345 [ + - ]: 2 : _rxInStream >> sReferenceValue;
346 [ + - ]: 2 : _rxInStream >> nDefaultChecked;
347 [ + - ]: 2 : readHelpTextCompatibly(_rxInStream);
348 [ + - ]: 2 : readCommonProperties(_rxInStream);
349 : 2 : break;
350 : : default :
351 : : OSL_FAIL("ORadioButtonModel::read : unknown version !");
352 [ # # ]: 0 : defaultCommonProperties();
353 : 0 : break;
354 : : }
355 : :
356 [ + - ]: 2 : setReferenceValue( sReferenceValue );
357 : 2 : setDefaultChecked( (ToggleState)nDefaultChecked );
358 : :
359 : : // Display default values after read
360 [ + - ]: 2 : if ( !getControlSource().isEmpty() )
361 : : // (not if we don't have a control source - the "State" property acts like it is persistent, then
362 [ + - ][ + - ]: 2 : resetNoBroadcast();
363 : 2 : }
364 : :
365 : : //------------------------------------------------------------------------------
366 : 69 : void ORadioButtonModel::_propertyChanged(const PropertyChangeEvent& _rEvent) throw(RuntimeException)
367 : : {
368 [ + + ]: 69 : if ( _rEvent.PropertyName.equals( PROPERTY_STATE ) )
369 : : {
370 [ + - ][ + + ]: 37 : if ( _rEvent.NewValue == (sal_Int16)1 )
371 : : {
372 : : // If my status has changed to 'checked', I have to reset all my siblings, which are in the same group as I am
373 : 13 : Any aZero;
374 [ + - ]: 13 : aZero <<= (sal_Int16)0;
375 [ + - ][ + - ]: 13 : SetSiblingPropsTo( PROPERTY_STATE, aZero );
376 : : }
377 : : }
378 [ + - ]: 32 : else if ( _rEvent.PropertyName.equals( PROPERTY_GROUP_NAME ) )
379 : : {
380 : 32 : setControlSource();
381 : : // Can't call OReferenceValueComponent::_propertyChanged(), as it
382 : : // doesn't know what to do with the GroupName property.
383 : 69 : return;
384 : : }
385 : :
386 : 37 : OReferenceValueComponent::_propertyChanged( _rEvent );
387 : : }
388 : :
389 : : //------------------------------------------------------------------------------
390 : 0 : Any ORadioButtonModel::translateDbColumnToControlValue()
391 : : {
392 : : return makeAny( (sal_Int16)
393 : 0 : ( ( m_xColumn->getString() == getReferenceValue() ) ? STATE_CHECK : STATE_NOCHECK )
394 [ # # ][ # # ]: 0 : );
395 : : }
396 : :
397 : : //------------------------------------------------------------------------------
398 : 16 : Any ORadioButtonModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const
399 : : {
400 [ + - ]: 16 : Any aControlValue = OReferenceValueComponent::translateExternalValueToControlValue( _rExternalValue );
401 : 16 : sal_Int16 nState = STATE_NOCHECK;
402 [ + - ][ + + ]: 16 : if ( ( aControlValue >>= nState ) && ( nState == STATE_DONTKNOW ) )
[ + + ]
403 : : // radio buttons do not have the DONTKNOW state
404 [ + - ]: 16 : aControlValue <<= (sal_Int16)STATE_NOCHECK;
405 : 16 : return aControlValue;
406 : : }
407 : :
408 : : //-----------------------------------------------------------------------------
409 : 0 : sal_Bool ORadioButtonModel::commitControlValueToDbColumn( bool /*_bPostReset*/ )
410 : : {
411 : 0 : Reference< XPropertySet > xField( getField() );
412 : : OSL_PRECOND( xField.is(), "ORadioButtonModel::commitControlValueToDbColumn: not bound!" );
413 [ # # ]: 0 : if ( xField.is() )
414 : : {
415 : : try
416 : : {
417 : 0 : sal_Int16 nValue = 0;
418 [ # # ][ # # ]: 0 : m_xAggregateSet->getPropertyValue( PROPERTY_STATE ) >>= nValue;
[ # # ]
419 [ # # ]: 0 : if ( nValue == 1 )
420 [ # # ][ # # ]: 0 : xField->setPropertyValue( PROPERTY_VALUE, makeAny( getReferenceValue() ) );
[ # # ][ # # ]
[ # # ]
421 : : }
422 [ # # ]: 0 : catch(const Exception&)
423 : : {
424 : : OSL_FAIL("ORadioButtonModel::commitControlValueToDbColumn: could not commit !");
425 : : }
426 : : }
427 : 0 : return sal_True;
428 : : }
429 : :
430 : : //.........................................................................
431 : : }
432 : : //.........................................................................
433 : :
434 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|