update dev300-m58
[ooovba.git] / forms / source / component / GroupManager.cxx
blob35a3129778f2293036dd190220f89a840bd73f50
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: GroupManager.cxx,v $
10 * $Revision: 1.18 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_forms.hxx"
33 #include "GroupManager.hxx"
34 #include <com/sun/star/beans/XFastPropertySet.hpp>
35 #include <com/sun/star/form/FormComponentType.hpp>
36 #include <comphelper/property.hxx>
37 #include <comphelper/uno3.hxx>
38 #include <tools/solar.h>
39 #include <tools/debug.hxx>
41 #include "property.hrc"
43 #include <algorithm>
45 //.........................................................................
46 namespace frm
48 //.........................................................................
50 using namespace ::com::sun::star::uno;
51 using namespace ::com::sun::star::sdbc;
52 using namespace ::com::sun::star::beans;
53 using namespace ::com::sun::star::container;
54 using namespace ::com::sun::star::form;
55 using namespace ::com::sun::star::awt;
56 using namespace ::com::sun::star::lang;
57 using namespace ::com::sun::star::form;
59 namespace
61 bool isRadioButton( const Reference< XPropertySet >& _rxComponent )
63 bool bIs = false;
64 if ( hasProperty( PROPERTY_CLASSID, _rxComponent ) )
66 sal_Int16 nClassId = FormComponentType::CONTROL;
67 _rxComponent->getPropertyValue( PROPERTY_CLASSID ) >>= nClassId;
68 if ( nClassId == FormComponentType::RADIOBUTTON )
69 bIs = true;
71 return bIs;
75 //========================================================================
76 // class OGroupCompAcc
77 //========================================================================
78 //------------------------------------------------------------------
79 OGroupCompAcc::OGroupCompAcc(const Reference<XPropertySet>& rxElement, const OGroupComp& _rGroupComp )
80 :m_xComponent( rxElement )
81 ,m_aGroupComp( _rGroupComp )
85 //------------------------------------------------------------------
86 sal_Bool OGroupCompAcc::operator==( const OGroupCompAcc& rCompAcc ) const
88 return (m_xComponent == rCompAcc.GetComponent());
91 //------------------------------------------------------------------
92 class OGroupCompAccLess : public ::std::binary_function<OGroupCompAcc, OGroupCompAcc, sal_Bool>
94 public:
95 sal_Bool operator() (const OGroupCompAcc& lhs, const OGroupCompAcc& rhs) const
97 return
98 reinterpret_cast<sal_Int64>(lhs.m_xComponent.get())
99 < reinterpret_cast<sal_Int64>(rhs.m_xComponent.get());
103 //========================================================================
104 // class OGroupComp
105 //========================================================================
107 //------------------------------------------------------------------
108 OGroupComp::OGroupComp()
109 :m_nPos( -1 )
110 ,m_nTabIndex( 0 )
114 //------------------------------------------------------------------
115 OGroupComp::OGroupComp(const OGroupComp& _rSource)
116 :m_aName( _rSource.m_aName )
117 ,m_xComponent( _rSource.m_xComponent )
118 ,m_xControlModel(_rSource.m_xControlModel)
119 ,m_nPos( _rSource.m_nPos )
120 ,m_nTabIndex( _rSource.m_nTabIndex )
124 //------------------------------------------------------------------
125 OGroupComp::OGroupComp(const Reference<XPropertySet>& rxSet, sal_Int32 nInsertPos )
126 :m_xComponent( rxSet )
127 ,m_xControlModel(rxSet,UNO_QUERY)
128 ,m_nPos( nInsertPos )
129 ,m_nTabIndex(0)
130 ,m_aName( OGroupManager::GetGroupName( rxSet ) )
132 if (m_xComponent.is())
134 if (hasProperty( PROPERTY_TABINDEX, m_xComponent ) )
135 // Indices kleiner 0 werden wie 0 behandelt
136 m_nTabIndex = Max(getINT16(m_xComponent->getPropertyValue( PROPERTY_TABINDEX )) , sal_Int16(0));
140 //------------------------------------------------------------------
141 sal_Bool OGroupComp::operator==( const OGroupComp& rComp ) const
143 return m_nTabIndex == rComp.GetTabIndex() && m_nPos == rComp.GetPos();
146 //------------------------------------------------------------------
147 class OGroupCompLess : public ::std::binary_function<OGroupComp, OGroupComp, sal_Bool>
149 public:
150 sal_Bool operator() (const OGroupComp& lhs, const OGroupComp& rhs) const
152 sal_Bool bResult;
153 // TabIndex von 0 wird hinten einsortiert
154 if (lhs.m_nTabIndex == rhs.GetTabIndex())
155 bResult = lhs.m_nPos < rhs.GetPos();
156 else if (lhs.m_nTabIndex && rhs.GetTabIndex())
157 bResult = lhs.m_nTabIndex < rhs.GetTabIndex();
158 else
159 bResult = lhs.m_nTabIndex != 0;
160 return bResult;
164 //========================================================================
165 // class OGroup
166 //========================================================================
168 DBG_NAME(OGroup)
169 //------------------------------------------------------------------
170 OGroup::OGroup( const ::rtl::OUString& rGroupName )
171 :m_aGroupName( rGroupName )
172 ,m_nInsertPos(0)
174 DBG_CTOR(OGroup,NULL);
177 #ifdef DBG_UTIL
178 //------------------------------------------------------------------
179 OGroup::OGroup( const OGroup& _rSource )
180 :m_aCompArray(_rSource.m_aCompArray)
181 ,m_aCompAccArray(_rSource.m_aCompAccArray)
182 ,m_aGroupName(_rSource.m_aGroupName)
183 ,m_nInsertPos(_rSource.m_nInsertPos)
185 DBG_CTOR(OGroup,NULL);
187 #endif
189 //------------------------------------------------------------------
190 OGroup::~OGroup()
192 DBG_DTOR(OGroup,NULL);
195 //------------------------------------------------------------------
196 void OGroup::InsertComponent( const Reference<XPropertySet>& xSet )
198 OGroupComp aNewGroupComp( xSet, m_nInsertPos );
199 sal_Int32 nPosInserted = insert_sorted(m_aCompArray, aNewGroupComp, OGroupCompLess());
201 OGroupCompAcc aNewGroupCompAcc( xSet, m_aCompArray[nPosInserted] );
202 insert_sorted(m_aCompAccArray, aNewGroupCompAcc, OGroupCompAccLess());
203 m_nInsertPos++;
206 //------------------------------------------------------------------
207 void OGroup::RemoveComponent( const Reference<XPropertySet>& rxElement )
209 sal_Int32 nGroupCompAccPos;
210 OGroupCompAcc aSearchCompAcc( rxElement, OGroupComp() );
211 if ( seek_entry(m_aCompAccArray, aSearchCompAcc, nGroupCompAccPos, OGroupCompAccLess()) )
213 OGroupCompAcc& aGroupCompAcc = m_aCompAccArray[nGroupCompAccPos];
214 const OGroupComp& aGroupComp = aGroupCompAcc.GetGroupComponent();
216 sal_Int32 nGroupCompPos;
217 if ( seek_entry(m_aCompArray, aGroupComp, nGroupCompPos, OGroupCompLess()) )
219 m_aCompAccArray.erase( m_aCompAccArray.begin() + nGroupCompAccPos );
220 m_aCompArray.erase( m_aCompArray.begin() + nGroupCompPos );
222 /*============================================================
223 Durch das Entfernen der GroupComp ist die Einfuegeposition
224 ungueltig geworden. Sie braucht hier aber nicht angepasst werden,
225 da sie fortlaufend vergeben wird und damit immer
226 aufsteigend eindeutig ist.
227 ============================================================*/
229 else
231 DBG_ERROR( "OGroup::RemoveComponent: Component nicht in Gruppe" );
234 else
236 DBG_ERROR( "OGroup::RemoveComponent: Component nicht in Gruppe" );
240 //------------------------------------------------------------------
241 sal_Bool OGroup::operator==( const OGroup& rGroup ) const
243 return m_aGroupName.equals(rGroup.GetGroupName());
246 //------------------------------------------------------------------
247 class OGroupLess : public ::std::binary_function<OGroup, OGroup, sal_Bool>
249 public:
250 sal_Bool operator() (const OGroup& lhs, const OGroup& rhs) const
252 return lhs.m_aGroupName < rhs.m_aGroupName;
256 //------------------------------------------------------------------
257 Sequence< Reference<XControlModel> > OGroup::GetControlModels() const
259 sal_Int32 nLen = m_aCompArray.size();
260 Sequence<Reference<XControlModel> > aControlModelSeq( nLen );
261 Reference<XControlModel>* pModels = aControlModelSeq.getArray();
263 ConstOGroupCompArrIterator aGroupComps = m_aCompArray.begin();
264 for (sal_Int32 i = 0; i < nLen; ++i, ++pModels, ++aGroupComps)
266 *pModels = aGroupComps->GetControlModel();
268 return aControlModelSeq;
271 DBG_NAME(OGroupManager);
272 //------------------------------------------------------------------
273 OGroupManager::OGroupManager(const Reference< XContainer >& _rxContainer)
274 :m_pCompGroup( new OGroup( ::rtl::OUString::createFromAscii( "AllComponentGroup" ) ) )
275 ,m_xContainer(_rxContainer)
277 DBG_CTOR(OGroupManager,NULL);
279 increment(m_refCount);
281 _rxContainer->addContainerListener(this);
283 decrement(m_refCount);
286 //------------------------------------------------------------------
287 OGroupManager::~OGroupManager()
289 DBG_DTOR(OGroupManager,NULL);
290 // Alle Components und CompGroup loeschen
291 delete m_pCompGroup;
294 // XPropertyChangeListener
295 //------------------------------------------------------------------
296 void OGroupManager::disposing(const EventObject& evt) throw( RuntimeException )
298 Reference<XContainer> xContainer(evt.Source, UNO_QUERY);
299 if (xContainer.get() == m_xContainer.get())
301 DELETEZ(m_pCompGroup);
303 ////////////////////////////////////////////////////////////////
304 // Gruppen loeschen
305 m_aGroupArr.clear();
306 m_xContainer.clear();
309 // -----------------------------------------------------------------------------
310 void OGroupManager::removeFromGroupMap(const ::rtl::OUString& _sGroupName,const Reference<XPropertySet>& _xSet)
312 // Component aus CompGroup entfernen
313 m_pCompGroup->RemoveComponent( _xSet );
315 OGroupArr::iterator aFind = m_aGroupArr.find(_sGroupName);
317 if ( aFind != m_aGroupArr.end() )
319 // Gruppe vorhanden
320 aFind->second.RemoveComponent( _xSet );
322 // Wenn Anzahl der Gruppenelemente == 1 ist, Gruppe deaktivieren
323 sal_Int32 nCount = aFind->second.Count();
324 if ( nCount == 1 || nCount == 0 )
326 OActiveGroups::iterator aActiveFind = ::std::find(
327 m_aActiveGroupMap.begin(),
328 m_aActiveGroupMap.end(),
329 aFind
331 if ( aActiveFind != m_aActiveGroupMap.end() )
333 // the group is active. Deactivate it if the remaining component
334 // is *no* radio button
335 if ( nCount == 0 || !isRadioButton( aFind->second.GetObject( 0 ) ) )
336 m_aActiveGroupMap.erase( aActiveFind );
342 // Bei Component als PropertyChangeListener abmelden
343 _xSet->removePropertyChangeListener( PROPERTY_NAME, this );
344 if (hasProperty(PROPERTY_GROUP_NAME, _xSet))
345 _xSet->removePropertyChangeListener( PROPERTY_GROUP_NAME, this );
346 if (hasProperty(PROPERTY_TABINDEX, _xSet))
347 _xSet->removePropertyChangeListener( PROPERTY_TABINDEX, this );
349 //------------------------------------------------------------------
350 void SAL_CALL OGroupManager::propertyChange(const PropertyChangeEvent& evt) throw ( ::com::sun::star::uno::RuntimeException)
352 Reference<XPropertySet> xSet(evt.Source, UNO_QUERY);
354 // Component aus Gruppe entfernen
355 ::rtl::OUString sGroupName;
356 if (hasProperty( PROPERTY_GROUP_NAME, xSet ))
357 xSet->getPropertyValue( PROPERTY_GROUP_NAME ) >>= sGroupName;
358 if (evt.PropertyName == PROPERTY_NAME) {
359 if (sGroupName.getLength() > 0)
360 return; // group hasn't changed; ignore this name change.
361 // no GroupName; use Name as GroupNme
362 evt.OldValue >>= sGroupName;
364 else if (evt.PropertyName == PROPERTY_GROUP_NAME) {
365 evt.OldValue >>= sGroupName;
366 if (sGroupName.getLength() == 0) {
367 // No prior GroupName; fallback to Nme
368 xSet->getPropertyValue( PROPERTY_NAME ) >>= sGroupName;
371 else
372 sGroupName = GetGroupName( xSet );
374 removeFromGroupMap(sGroupName,xSet);
376 // Component neu einordnen
377 InsertElement( xSet );
380 // XContainerListener
381 //------------------------------------------------------------------
382 void SAL_CALL OGroupManager::elementInserted(const ContainerEvent& Event) throw ( ::com::sun::star::uno::RuntimeException)
384 Reference< XPropertySet > xProps;
385 Event.Element >>= xProps;
386 if ( xProps.is() )
387 InsertElement( xProps );
390 //------------------------------------------------------------------
391 void SAL_CALL OGroupManager::elementRemoved(const ContainerEvent& Event) throw ( ::com::sun::star::uno::RuntimeException)
393 Reference<XPropertySet> xProps;
394 Event.Element >>= xProps;
395 if ( xProps.is() )
396 RemoveElement( xProps );
399 //------------------------------------------------------------------
400 void SAL_CALL OGroupManager::elementReplaced(const ContainerEvent& Event) throw ( ::com::sun::star::uno::RuntimeException)
402 Reference<XPropertySet> xProps;
403 Event.ReplacedElement >>= xProps;
404 if ( xProps.is() )
405 RemoveElement( xProps );
407 xProps.clear();
408 Event.Element >>= xProps;
409 if ( xProps.is() )
410 InsertElement( xProps );
413 // Other functions
414 //------------------------------------------------------------------
415 Sequence<Reference<XControlModel> > OGroupManager::getControlModels()
417 return m_pCompGroup->GetControlModels();
420 //------------------------------------------------------------------
421 sal_Int32 OGroupManager::getGroupCount()
423 return m_aActiveGroupMap.size();
426 //------------------------------------------------------------------
427 void OGroupManager::getGroup(sal_Int32 nGroup, Sequence< Reference<XControlModel> >& _rGroup, ::rtl::OUString& _rName)
429 OSL_ENSURE(nGroup >= 0 && (size_t)nGroup < m_aActiveGroupMap.size(),"OGroupManager::getGroup: Invalid group index!");
430 OGroupArr::iterator aGroupPos = m_aActiveGroupMap[nGroup];
431 _rName = aGroupPos->second.GetGroupName();
432 _rGroup = aGroupPos->second.GetControlModels();
435 //------------------------------------------------------------------
436 void OGroupManager::getGroupByName(const ::rtl::OUString& _rName, Sequence< Reference<XControlModel> >& _rGroup)
438 OGroupArr::iterator aFind = m_aGroupArr.find(_rName);
439 if ( aFind != m_aGroupArr.end() )
440 _rGroup = aFind->second.GetControlModels();
443 //------------------------------------------------------------------
444 void OGroupManager::InsertElement( const Reference<XPropertySet>& xSet )
446 // Nur ControlModels
447 Reference<XControlModel> xControl(xSet, UNO_QUERY);
448 if (!xControl.is() )
449 return;
451 // Component in CompGroup aufnehmen
452 m_pCompGroup->InsertComponent( xSet );
454 // Component in Gruppe aufnehmen
455 ::rtl::OUString sGroupName( GetGroupName( xSet ) );
457 OGroupArr::iterator aFind = m_aGroupArr.find(sGroupName);
459 if ( aFind == m_aGroupArr.end() )
461 aFind = m_aGroupArr.insert(OGroupArr::value_type(sGroupName,OGroup(sGroupName))).first;
464 aFind->second.InsertComponent( xSet );
466 // if we have at least 2 elements in the group, then this is an "active group"
467 bool bActivateGroup = aFind->second.Count() == 2;
469 // Additionally, if the component is a radio button, then it's group becomes active,
470 // too. With this, we ensure that in a container with n radio buttons which all are
471 // in different groups the selection still works reliably (means that all radios can be
472 // clicked independently)
473 if ( aFind->second.Count() == 1 )
475 if ( isRadioButton( xSet ) )
476 bActivateGroup = true;
479 if ( bActivateGroup )
481 OActiveGroups::iterator aAlreadyExistent = ::std::find(
482 m_aActiveGroupMap.begin(),
483 m_aActiveGroupMap.end(),
484 aFind
486 if ( aAlreadyExistent == m_aActiveGroupMap.end() )
487 m_aActiveGroupMap.push_back( aFind );
491 // Bei Component als PropertyChangeListener anmelden
492 xSet->addPropertyChangeListener( PROPERTY_NAME, this );
493 if (hasProperty(PROPERTY_GROUP_NAME, xSet))
494 xSet->addPropertyChangeListener( PROPERTY_GROUP_NAME, this );
496 // Tabindex muss nicht jeder unterstuetzen
497 if (hasProperty(PROPERTY_TABINDEX, xSet))
498 xSet->addPropertyChangeListener( PROPERTY_TABINDEX, this );
502 //------------------------------------------------------------------
503 void OGroupManager::RemoveElement( const Reference<XPropertySet>& xSet )
505 // Nur ControlModels
506 Reference<XControlModel> xControl(xSet, UNO_QUERY);
507 if (!xControl.is() )
508 return;
510 // Component aus Gruppe entfernen
511 ::rtl::OUString sGroupName( GetGroupName( xSet ) );
513 removeFromGroupMap(sGroupName,xSet);
516 ::rtl::OUString OGroupManager::GetGroupName( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet> xComponent )
518 if (!xComponent.is())
519 return ::rtl::OUString();
520 ::rtl::OUString sGroupName;
521 if (hasProperty( PROPERTY_GROUP_NAME, xComponent )) {
522 xComponent->getPropertyValue( PROPERTY_GROUP_NAME ) >>= sGroupName;
523 if (sGroupName.getLength() == 0)
524 xComponent->getPropertyValue( PROPERTY_NAME ) >>= sGroupName;
526 else
527 xComponent->getPropertyValue( PROPERTY_NAME ) >>= sGroupName;
528 return sGroupName;
531 //.........................................................................
532 } // namespace frm
533 //.........................................................................