bump product version to 7.6.3.2-android
[LibreOffice.git] / forms / source / component / RadioButton.cxx
bloba700f645b2429ae63a20493eb0f88dd291e7ef42
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "RadioButton.hxx"
21 #include "GroupManager.hxx"
22 #include <property.hxx>
23 #include <services.hxx>
24 #include <comphelper/basicio.hxx>
25 #include <comphelper/property.hxx>
26 #include <tools/debug.hxx>
27 #include <com/sun/star/beans/PropertyAttribute.hpp>
28 #include <com/sun/star/container/XIndexAccess.hpp>
29 #include <com/sun/star/form/FormComponentType.hpp>
31 namespace frm
33 using namespace ::com::sun::star::uno;
34 using namespace ::com::sun::star::sdb;
35 using namespace ::com::sun::star::sdbc;
36 using namespace ::com::sun::star::beans;
37 using namespace ::com::sun::star::container;
38 using namespace ::com::sun::star::form;
39 using namespace ::com::sun::star::awt;
40 using namespace ::com::sun::star::io;
41 using namespace ::com::sun::star::lang;
42 using namespace ::com::sun::star::util;
43 using namespace ::com::sun::star::form::binding;
46 css::uno::Sequence<OUString> SAL_CALL ORadioButtonControl::getSupportedServiceNames()
48 css::uno::Sequence<OUString> aSupported = OBoundControl::getSupportedServiceNames();
49 aSupported.realloc(aSupported.getLength() + 2);
51 OUString* pArray = aSupported.getArray();
52 pArray[aSupported.getLength()-2] = FRM_SUN_CONTROL_RADIOBUTTON;
53 pArray[aSupported.getLength()-1] = STARDIV_ONE_FORM_CONTROL_RADIOBUTTON;
54 return aSupported;
58 ORadioButtonControl::ORadioButtonControl(const Reference<XComponentContext>& _rxFactory)
59 :OBoundControl(_rxFactory, VCL_CONTROL_RADIOBUTTON)
64 ORadioButtonModel::ORadioButtonModel(const Reference<XComponentContext>& _rxFactory)
65 :OReferenceValueComponent( _rxFactory, VCL_CONTROLMODEL_RADIOBUTTON, FRM_SUN_CONTROL_RADIOBUTTON )
66 // use the old control name for compytibility reasons
69 m_nClassId = FormComponentType::RADIOBUTTON;
70 m_aLabelServiceName = FRM_SUN_COMPONENT_GROUPBOX;
71 initValueProperty( PROPERTY_STATE, PROPERTY_ID_STATE );
72 startAggregatePropertyListening( PROPERTY_GROUP_NAME );
76 ORadioButtonModel::ORadioButtonModel( const ORadioButtonModel* _pOriginal, const Reference<XComponentContext>& _rxFactory )
77 :OReferenceValueComponent( _pOriginal, _rxFactory )
82 ORadioButtonModel::~ORadioButtonModel()
86 // XCloneable
88 css::uno::Reference< css::util::XCloneable > SAL_CALL ORadioButtonModel::createClone()
90 rtl::Reference<ORadioButtonModel> pClone = new ORadioButtonModel(this, getContext());
91 pClone->clonedFrom(this);
92 return pClone;
95 // XServiceInfo
97 css::uno::Sequence<OUString> SAL_CALL ORadioButtonModel::getSupportedServiceNames()
99 css::uno::Sequence<OUString> aSupported = OReferenceValueComponent::getSupportedServiceNames();
101 sal_Int32 nOldLen = aSupported.getLength();
102 aSupported.realloc( nOldLen + 9 );
103 OUString* pStoreTo = aSupported.getArray() + nOldLen;
105 *pStoreTo++ = BINDABLE_CONTROL_MODEL;
106 *pStoreTo++ = DATA_AWARE_CONTROL_MODEL;
107 *pStoreTo++ = VALIDATABLE_CONTROL_MODEL;
109 *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL;
110 *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL;
112 *pStoreTo++ = FRM_SUN_COMPONENT_RADIOBUTTON;
113 *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_RADIOBUTTON;
114 *pStoreTo++ = BINDABLE_DATABASE_RADIO_BUTTON;
116 *pStoreTo++ = FRM_COMPONENT_RADIOBUTTON;
118 return aSupported;
122 void ORadioButtonModel::SetSiblingPropsTo(const OUString& rPropName, const Any& rValue)
124 // my name
125 OUString sMyGroup;
126 if (hasProperty(PROPERTY_GROUP_NAME, this))
127 getPropertyValue(PROPERTY_GROUP_NAME) >>= sMyGroup;
128 if (sMyGroup.isEmpty())
129 sMyGroup = m_aName;
131 // Iterate over my siblings
132 Reference<XIndexAccess> xIndexAccess(getParent(), UNO_QUERY);
133 if (!xIndexAccess.is())
134 return;
136 Reference<XPropertySet> xMyProps = this;
137 OUString sCurrentGroup;
138 sal_Int32 nNumSiblings = xIndexAccess->getCount();
139 for (sal_Int32 i=0; i<nNumSiblings; ++i)
141 Reference<XPropertySet> xSiblingProperties(xIndexAccess->getByIndex(i), UNO_QUERY);
142 if (!xSiblingProperties.is())
143 continue;
144 if (xMyProps == xSiblingProperties)
145 continue; // do not set myself
147 // Only if it's a RadioButton
148 if (!hasProperty(PROPERTY_CLASSID, xSiblingProperties))
149 continue;
150 sal_Int16 nType = 0;
151 xSiblingProperties->getPropertyValue(PROPERTY_CLASSID) >>= nType;
152 if (nType != FormComponentType::RADIOBUTTON)
153 continue;
155 // The group association is attached to the name
156 sCurrentGroup = OGroupManager::GetGroupName( xSiblingProperties );
157 if (sCurrentGroup == sMyGroup)
158 xSiblingProperties->setPropertyValue(rPropName, rValue);
163 void ORadioButtonModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue)
165 OReferenceValueComponent::setFastPropertyValue_NoBroadcast( nHandle, rValue );
167 // if the label control changed ...
168 if (nHandle == PROPERTY_ID_CONTROLLABEL)
169 { // ... forward this to our siblings
170 SetSiblingPropsTo(PROPERTY_CONTROLLABEL, rValue);
173 // If the ControlSource property has changed ...
174 if (nHandle == PROPERTY_ID_CONTROLSOURCE)
175 { // ... I have to pass the new ControlSource to my siblings, which are in the same RadioButton group as I am
176 SetSiblingPropsTo(PROPERTY_CONTROLSOURCE, rValue);
179 // The other way: if my name changes ...
180 if (nHandle == PROPERTY_ID_NAME)
182 setControlSource();
185 if (nHandle != PROPERTY_ID_DEFAULT_STATE)
186 return;
188 sal_Int16 nValue;
189 rValue >>= nValue;
190 if (1 == nValue)
191 { // Reset the 'default checked' for all Radios of the same group.
192 // Because (as the Highlander already knew): "There can be only one"
193 Any aZero;
194 nValue = 0;
195 aZero <<= nValue;
196 SetSiblingPropsTo(PROPERTY_DEFAULT_STATE, aZero);
200 void ORadioButtonModel::setControlSource()
202 Reference<XIndexAccess> xIndexAccess(getParent(), UNO_QUERY);
203 if (!xIndexAccess.is())
204 return;
206 OUString sName, sGroupName;
208 if (hasProperty(PROPERTY_GROUP_NAME, this))
209 getPropertyValue(PROPERTY_GROUP_NAME) >>= sGroupName;
210 getPropertyValue(PROPERTY_NAME) >>= sName;
212 Reference<XPropertySet> xMyProps = this;
213 for (sal_Int32 i=0; i<xIndexAccess->getCount(); ++i)
215 Reference<XPropertySet> xSiblingProperties(xIndexAccess->getByIndex(i), UNO_QUERY);
216 if (!xSiblingProperties.is())
217 continue;
219 if (xMyProps == xSiblingProperties)
220 // Only if I didn't find myself
221 continue;
223 sal_Int16 nType = 0;
224 xSiblingProperties->getPropertyValue(PROPERTY_CLASSID) >>= nType;
225 if (nType != FormComponentType::RADIOBUTTON)
226 // Only RadioButtons
227 continue;
229 OUString sSiblingName, sSiblingGroupName;
230 if (hasProperty(PROPERTY_GROUP_NAME, xSiblingProperties))
231 xSiblingProperties->getPropertyValue(PROPERTY_GROUP_NAME) >>= sSiblingGroupName;
232 xSiblingProperties->getPropertyValue(PROPERTY_NAME) >>= sSiblingName;
234 if ((sGroupName.isEmpty() && sSiblingGroupName.isEmpty() && // (no group name
235 sName == sSiblingName) || // names match) or
236 (!sGroupName.isEmpty() && !sSiblingGroupName.isEmpty() && // (have group name
237 sGroupName == sSiblingGroupName)) // they match)
239 setPropertyValue(PROPERTY_CONTROLSOURCE, xSiblingProperties->getPropertyValue(PROPERTY_CONTROLSOURCE));
240 break;
246 void ORadioButtonModel::describeFixedProperties( Sequence< Property >& _rProps ) const
248 OReferenceValueComponent::describeFixedProperties( _rProps );
249 sal_Int32 nOldCount = _rProps.getLength();
250 _rProps.realloc( nOldCount + 1);
251 css::beans::Property* pProperties = _rProps.getArray() + nOldCount;
252 *pProperties++ = css::beans::Property(PROPERTY_TABINDEX, PROPERTY_ID_TABINDEX, cppu::UnoType<sal_Int16>::get(), css::beans::PropertyAttribute::BOUND);
253 DBG_ASSERT( pProperties == _rProps.getArray() + _rProps.getLength(), "<...>::describeFixedProperties/getInfoHelper: forgot to adjust the count ?");
257 OUString SAL_CALL ORadioButtonModel::getServiceName()
259 return FRM_COMPONENT_RADIOBUTTON; // old (non-sun) name for compatibility !
263 void SAL_CALL ORadioButtonModel::write(const Reference<XObjectOutputStream>& _rxOutStream)
265 OReferenceValueComponent::write(_rxOutStream);
267 // Version
268 _rxOutStream->writeShort(0x0003);
270 // Properties
271 _rxOutStream << getReferenceValue();
272 _rxOutStream << static_cast<sal_Int16>(getDefaultChecked());
273 writeHelpTextCompatibly(_rxOutStream);
275 // from version 0x0003 : common properties
276 writeCommonProperties(_rxOutStream);
280 void SAL_CALL ORadioButtonModel::read(const Reference<XObjectInputStream>& _rxInStream)
282 OReferenceValueComponent::read(_rxInStream);
283 ::osl::MutexGuard aGuard(m_aMutex);
285 // Version
286 sal_uInt16 nVersion = _rxInStream->readShort();
288 OUString sReferenceValue;
289 sal_Int16 nDefaultChecked( 0 );
290 switch (nVersion)
292 case 0x0001 :
293 _rxInStream >> sReferenceValue;
294 _rxInStream >> nDefaultChecked;
295 break;
296 case 0x0002 :
297 _rxInStream >> sReferenceValue;
298 _rxInStream >> nDefaultChecked;
299 readHelpTextCompatibly(_rxInStream);
300 break;
301 case 0x0003 :
302 _rxInStream >> sReferenceValue;
303 _rxInStream >> nDefaultChecked;
304 readHelpTextCompatibly(_rxInStream);
305 readCommonProperties(_rxInStream);
306 break;
307 default :
308 OSL_FAIL("ORadioButtonModel::read : unknown version !");
309 defaultCommonProperties();
310 break;
313 setReferenceValue( sReferenceValue );
314 setDefaultChecked( static_cast<ToggleState>(nDefaultChecked) );
316 // Display default values after read
317 if ( !getControlSource().isEmpty() )
318 // (not if we don't have a control source - the "State" property acts like it is persistent, then
319 resetNoBroadcast();
323 void ORadioButtonModel::_propertyChanged(const PropertyChangeEvent& _rEvent)
325 if ( _rEvent.PropertyName == PROPERTY_STATE )
327 if ( _rEvent.NewValue == sal_Int16(1) )
329 // If my status has changed to 'checked', I have to reset all my siblings, which are in the same group as I am
330 Any aZero;
331 aZero <<= sal_Int16(0);
332 SetSiblingPropsTo( PROPERTY_STATE, aZero );
335 else if ( _rEvent.PropertyName == PROPERTY_GROUP_NAME )
337 setControlSource();
338 // Can't call OReferenceValueComponent::_propertyChanged(), as it
339 // doesn't know what to do with the GroupName property.
340 return;
343 OReferenceValueComponent::_propertyChanged( _rEvent );
347 Any ORadioButtonModel::translateDbColumnToControlValue()
349 return Any( static_cast<sal_Int16>( ( m_xColumn->getString() == getReferenceValue() ) ? TRISTATE_TRUE : TRISTATE_FALSE )
354 Any ORadioButtonModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const
356 Any aControlValue = OReferenceValueComponent::translateExternalValueToControlValue( _rExternalValue );
357 sal_Int16 nState = TRISTATE_FALSE;
358 if ( ( aControlValue >>= nState ) && ( nState == TRISTATE_INDET ) )
359 // radio buttons do not have the DONTKNOW state
360 aControlValue <<= sal_Int16(TRISTATE_FALSE);
361 return aControlValue;
365 bool ORadioButtonModel::commitControlValueToDbColumn( bool /*_bPostReset*/ )
367 Reference< XPropertySet > xField( getField() );
368 OSL_PRECOND( xField.is(), "ORadioButtonModel::commitControlValueToDbColumn: not bound!" );
369 if ( xField.is() )
373 sal_Int16 nValue = 0;
374 m_xAggregateSet->getPropertyValue( PROPERTY_STATE ) >>= nValue;
375 if ( nValue == 1 )
376 xField->setPropertyValue( PROPERTY_VALUE, Any( getReferenceValue() ) );
378 catch(const Exception&)
380 OSL_FAIL("ORadioButtonModel::commitControlValueToDbColumn: could not commit !");
383 return true;
388 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
389 com_sun_star_form_ORadioButtonModel_get_implementation(css::uno::XComponentContext* component,
390 css::uno::Sequence<css::uno::Any> const &)
392 return cppu::acquire(new frm::ORadioButtonModel(component));
395 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
396 com_sun_star_form_ORadioButtonControl_get_implementation(css::uno::XComponentContext* component,
397 css::uno::Sequence<css::uno::Any> const &)
399 return cppu::acquire(new frm::ORadioButtonControl(component));
402 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */