| /************************************************************** | |
| * | |
| * Licensed to the Apache Software Foundation (ASF) under one | |
| * or more contributor license agreements. See the NOTICE file | |
| * distributed with this work for additional information | |
| * regarding copyright ownership. The ASF licenses this file | |
| * to you under the Apache License, Version 2.0 (the | |
| * "License"); you may not use this file except in compliance | |
| * with the License. You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, | |
| * software distributed under the License is distributed on an | |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| * KIND, either express or implied. See the License for the | |
| * specific language governing permissions and limitations | |
| * under the License. | |
| * | |
| *************************************************************/ | |
| // MARKER(update_precomp.py): autogen include statement, do not remove | |
| #include "precompiled_forms.hxx" | |
| #include "GroupManager.hxx" | |
| #include <com/sun/star/beans/XFastPropertySet.hpp> | |
| #include <com/sun/star/form/FormComponentType.hpp> | |
| #include <comphelper/property.hxx> | |
| #include <comphelper/uno3.hxx> | |
| #include <tools/solar.h> | |
| #include <tools/debug.hxx> | |
| #include "property.hrc" | |
| #include <algorithm> | |
| //......................................................................... | |
| namespace frm | |
| { | |
| //......................................................................... | |
| using namespace ::com::sun::star::uno; | |
| using namespace ::com::sun::star::sdbc; | |
| using namespace ::com::sun::star::beans; | |
| using namespace ::com::sun::star::container; | |
| using namespace ::com::sun::star::form; | |
| using namespace ::com::sun::star::awt; | |
| using namespace ::com::sun::star::lang; | |
| using namespace ::com::sun::star::form; | |
| namespace | |
| { | |
| bool isRadioButton( const Reference< XPropertySet >& _rxComponent ) | |
| { | |
| bool bIs = false; | |
| if ( hasProperty( PROPERTY_CLASSID, _rxComponent ) ) | |
| { | |
| sal_Int16 nClassId = FormComponentType::CONTROL; | |
| _rxComponent->getPropertyValue( PROPERTY_CLASSID ) >>= nClassId; | |
| if ( nClassId == FormComponentType::RADIOBUTTON ) | |
| bIs = true; | |
| } | |
| return bIs; | |
| } | |
| } | |
| //======================================================================== | |
| // class OGroupCompAcc | |
| //======================================================================== | |
| //------------------------------------------------------------------ | |
| OGroupCompAcc::OGroupCompAcc(const Reference<XPropertySet>& rxElement, const OGroupComp& _rGroupComp ) | |
| :m_xComponent( rxElement ) | |
| ,m_aGroupComp( _rGroupComp ) | |
| { | |
| } | |
| //------------------------------------------------------------------ | |
| sal_Bool OGroupCompAcc::operator==( const OGroupCompAcc& rCompAcc ) const | |
| { | |
| return (m_xComponent == rCompAcc.GetComponent()); | |
| } | |
| //------------------------------------------------------------------ | |
| class OGroupCompAccLess : public ::std::binary_function<OGroupCompAcc, OGroupCompAcc, sal_Bool> | |
| { | |
| public: | |
| sal_Bool operator() (const OGroupCompAcc& lhs, const OGroupCompAcc& rhs) const | |
| { | |
| return | |
| reinterpret_cast<sal_Int64>(lhs.m_xComponent.get()) | |
| < reinterpret_cast<sal_Int64>(rhs.m_xComponent.get()); | |
| } | |
| }; | |
| //======================================================================== | |
| // class OGroupComp | |
| //======================================================================== | |
| //------------------------------------------------------------------ | |
| OGroupComp::OGroupComp() | |
| :m_nPos( -1 ) | |
| ,m_nTabIndex( 0 ) | |
| { | |
| } | |
| //------------------------------------------------------------------ | |
| OGroupComp::OGroupComp(const OGroupComp& _rSource) | |
| :m_aName( _rSource.m_aName ) | |
| ,m_xComponent( _rSource.m_xComponent ) | |
| ,m_xControlModel(_rSource.m_xControlModel) | |
| ,m_nPos( _rSource.m_nPos ) | |
| ,m_nTabIndex( _rSource.m_nTabIndex ) | |
| { | |
| } | |
| //------------------------------------------------------------------ | |
| OGroupComp::OGroupComp(const Reference<XPropertySet>& rxSet, sal_Int32 nInsertPos ) | |
| :m_xComponent( rxSet ) | |
| ,m_xControlModel(rxSet,UNO_QUERY) | |
| ,m_nPos( nInsertPos ) | |
| ,m_nTabIndex(0) | |
| { | |
| if (m_xComponent.is()) | |
| { | |
| if (hasProperty( PROPERTY_TABINDEX, m_xComponent ) ) | |
| // Indices kleiner 0 werden wie 0 behandelt | |
| m_nTabIndex = Max(getINT16(m_xComponent->getPropertyValue( PROPERTY_TABINDEX )) , sal_Int16(0)); | |
| m_xComponent->getPropertyValue( PROPERTY_NAME ) >>= m_aName; | |
| } | |
| } | |
| //------------------------------------------------------------------ | |
| sal_Bool OGroupComp::operator==( const OGroupComp& rComp ) const | |
| { | |
| return m_nTabIndex == rComp.GetTabIndex() && m_nPos == rComp.GetPos(); | |
| } | |
| //------------------------------------------------------------------ | |
| class OGroupCompLess : public ::std::binary_function<OGroupComp, OGroupComp, sal_Bool> | |
| { | |
| public: | |
| sal_Bool operator() (const OGroupComp& lhs, const OGroupComp& rhs) const | |
| { | |
| sal_Bool bResult; | |
| // TabIndex von 0 wird hinten einsortiert | |
| if (lhs.m_nTabIndex == rhs.GetTabIndex()) | |
| bResult = lhs.m_nPos < rhs.GetPos(); | |
| else if (lhs.m_nTabIndex && rhs.GetTabIndex()) | |
| bResult = lhs.m_nTabIndex < rhs.GetTabIndex(); | |
| else | |
| bResult = lhs.m_nTabIndex != 0; | |
| return bResult; | |
| } | |
| }; | |
| //======================================================================== | |
| // class OGroup | |
| //======================================================================== | |
| DBG_NAME(OGroup) | |
| //------------------------------------------------------------------ | |
| OGroup::OGroup( const ::rtl::OUString& rGroupName ) | |
| :m_aGroupName( rGroupName ) | |
| ,m_nInsertPos(0) | |
| { | |
| DBG_CTOR(OGroup,NULL); | |
| } | |
| #ifdef DBG_UTIL | |
| //------------------------------------------------------------------ | |
| OGroup::OGroup( const OGroup& _rSource ) | |
| :m_aCompArray(_rSource.m_aCompArray) | |
| ,m_aCompAccArray(_rSource.m_aCompAccArray) | |
| ,m_aGroupName(_rSource.m_aGroupName) | |
| ,m_nInsertPos(_rSource.m_nInsertPos) | |
| { | |
| DBG_CTOR(OGroup,NULL); | |
| } | |
| #endif | |
| //------------------------------------------------------------------ | |
| OGroup::~OGroup() | |
| { | |
| DBG_DTOR(OGroup,NULL); | |
| } | |
| //------------------------------------------------------------------ | |
| void OGroup::InsertComponent( const Reference<XPropertySet>& xSet ) | |
| { | |
| OGroupComp aNewGroupComp( xSet, m_nInsertPos ); | |
| sal_Int32 nPosInserted = insert_sorted(m_aCompArray, aNewGroupComp, OGroupCompLess()); | |
| OGroupCompAcc aNewGroupCompAcc( xSet, m_aCompArray[nPosInserted] ); | |
| insert_sorted(m_aCompAccArray, aNewGroupCompAcc, OGroupCompAccLess()); | |
| m_nInsertPos++; | |
| } | |
| //------------------------------------------------------------------ | |
| void OGroup::RemoveComponent( const Reference<XPropertySet>& rxElement ) | |
| { | |
| sal_Int32 nGroupCompAccPos; | |
| OGroupCompAcc aSearchCompAcc( rxElement, OGroupComp() ); | |
| if ( seek_entry(m_aCompAccArray, aSearchCompAcc, nGroupCompAccPos, OGroupCompAccLess()) ) | |
| { | |
| OGroupCompAcc& aGroupCompAcc = m_aCompAccArray[nGroupCompAccPos]; | |
| const OGroupComp& aGroupComp = aGroupCompAcc.GetGroupComponent(); | |
| sal_Int32 nGroupCompPos; | |
| if ( seek_entry(m_aCompArray, aGroupComp, nGroupCompPos, OGroupCompLess()) ) | |
| { | |
| m_aCompAccArray.erase( m_aCompAccArray.begin() + nGroupCompAccPos ); | |
| m_aCompArray.erase( m_aCompArray.begin() + nGroupCompPos ); | |
| /*============================================================ | |
| Durch das Entfernen der GroupComp ist die Einfuegeposition | |
| ungueltig geworden. Sie braucht hier aber nicht angepasst werden, | |
| da sie fortlaufend vergeben wird und damit immer | |
| aufsteigend eindeutig ist. | |
| ============================================================*/ | |
| } | |
| else | |
| { | |
| DBG_ERROR( "OGroup::RemoveComponent: Component nicht in Gruppe" ); | |
| } | |
| } | |
| else | |
| { | |
| DBG_ERROR( "OGroup::RemoveComponent: Component nicht in Gruppe" ); | |
| } | |
| } | |
| //------------------------------------------------------------------ | |
| sal_Bool OGroup::operator==( const OGroup& rGroup ) const | |
| { | |
| return m_aGroupName.equals(rGroup.GetGroupName()); | |
| } | |
| //------------------------------------------------------------------ | |
| class OGroupLess : public ::std::binary_function<OGroup, OGroup, sal_Bool> | |
| { | |
| public: | |
| sal_Bool operator() (const OGroup& lhs, const OGroup& rhs) const | |
| { | |
| return lhs.m_aGroupName < rhs.m_aGroupName; | |
| } | |
| }; | |
| //------------------------------------------------------------------ | |
| Sequence< Reference<XControlModel> > OGroup::GetControlModels() const | |
| { | |
| sal_Int32 nLen = m_aCompArray.size(); | |
| Sequence<Reference<XControlModel> > aControlModelSeq( nLen ); | |
| Reference<XControlModel>* pModels = aControlModelSeq.getArray(); | |
| ConstOGroupCompArrIterator aGroupComps = m_aCompArray.begin(); | |
| for (sal_Int32 i = 0; i < nLen; ++i, ++pModels, ++aGroupComps) | |
| { | |
| *pModels = aGroupComps->GetControlModel(); | |
| } | |
| return aControlModelSeq; | |
| } | |
| DBG_NAME(OGroupManager); | |
| //------------------------------------------------------------------ | |
| OGroupManager::OGroupManager(const Reference< XContainer >& _rxContainer) | |
| :m_pCompGroup( new OGroup( ::rtl::OUString::createFromAscii( "AllComponentGroup" ) ) ) | |
| ,m_xContainer(_rxContainer) | |
| { | |
| DBG_CTOR(OGroupManager,NULL); | |
| increment(m_refCount); | |
| { | |
| _rxContainer->addContainerListener(this); | |
| } | |
| decrement(m_refCount); | |
| } | |
| //------------------------------------------------------------------ | |
| OGroupManager::~OGroupManager() | |
| { | |
| DBG_DTOR(OGroupManager,NULL); | |
| // Alle Components und CompGroup loeschen | |
| delete m_pCompGroup; | |
| } | |
| // XPropertyChangeListener | |
| //------------------------------------------------------------------ | |
| void OGroupManager::disposing(const EventObject& evt) throw( RuntimeException ) | |
| { | |
| Reference<XContainer> xContainer(evt.Source, UNO_QUERY); | |
| if (xContainer.get() == m_xContainer.get()) | |
| { | |
| DELETEZ(m_pCompGroup); | |
| //////////////////////////////////////////////////////////////// | |
| // Gruppen loeschen | |
| m_aGroupArr.clear(); | |
| m_xContainer.clear(); | |
| } | |
| } | |
| // ----------------------------------------------------------------------------- | |
| void OGroupManager::removeFromGroupMap(const ::rtl::OUString& _sGroupName,const Reference<XPropertySet>& _xSet) | |
| { | |
| // Component aus CompGroup entfernen | |
| m_pCompGroup->RemoveComponent( _xSet ); | |
| OGroupArr::iterator aFind = m_aGroupArr.find(_sGroupName); | |
| if ( aFind != m_aGroupArr.end() ) | |
| { | |
| // Gruppe vorhanden | |
| aFind->second.RemoveComponent( _xSet ); | |
| // Wenn Anzahl der Gruppenelemente == 1 ist, Gruppe deaktivieren | |
| if ( aFind->second.Count() == 1 ) | |
| { | |
| OActiveGroups::iterator aActiveFind = ::std::find( | |
| m_aActiveGroupMap.begin(), | |
| m_aActiveGroupMap.end(), | |
| aFind | |
| ); | |
| if ( aActiveFind != m_aActiveGroupMap.end() ) | |
| { | |
| // the group is active. Deactivate it if the remaining component | |
| // is *no* radio button | |
| if ( !isRadioButton( aFind->second.GetObject( 0 ) ) ) | |
| m_aActiveGroupMap.erase( aActiveFind ); | |
| } | |
| } | |
| } | |
| // Bei Component als PropertyChangeListener abmelden | |
| _xSet->removePropertyChangeListener( PROPERTY_NAME, this ); | |
| if (hasProperty(PROPERTY_TABINDEX, _xSet)) | |
| _xSet->removePropertyChangeListener( PROPERTY_TABINDEX, this ); | |
| } | |
| //------------------------------------------------------------------ | |
| void SAL_CALL OGroupManager::propertyChange(const PropertyChangeEvent& evt) throw ( ::com::sun::star::uno::RuntimeException) | |
| { | |
| Reference<XPropertySet> xSet(evt.Source, UNO_QUERY); | |
| // Component aus Gruppe entfernen | |
| ::rtl::OUString sGroupName; | |
| if (evt.PropertyName == PROPERTY_NAME) | |
| evt.OldValue >>= sGroupName; | |
| else | |
| xSet->getPropertyValue( PROPERTY_NAME ) >>= sGroupName; | |
| removeFromGroupMap(sGroupName,xSet); | |
| // Component neu einordnen | |
| InsertElement( xSet ); | |
| } | |
| // XContainerListener | |
| //------------------------------------------------------------------ | |
| void SAL_CALL OGroupManager::elementInserted(const ContainerEvent& Event) throw ( ::com::sun::star::uno::RuntimeException) | |
| { | |
| Reference< XPropertySet > xProps; | |
| Event.Element >>= xProps; | |
| if ( xProps.is() ) | |
| InsertElement( xProps ); | |
| } | |
| //------------------------------------------------------------------ | |
| void SAL_CALL OGroupManager::elementRemoved(const ContainerEvent& Event) throw ( ::com::sun::star::uno::RuntimeException) | |
| { | |
| Reference<XPropertySet> xProps; | |
| Event.Element >>= xProps; | |
| if ( xProps.is() ) | |
| RemoveElement( xProps ); | |
| } | |
| //------------------------------------------------------------------ | |
| void SAL_CALL OGroupManager::elementReplaced(const ContainerEvent& Event) throw ( ::com::sun::star::uno::RuntimeException) | |
| { | |
| Reference<XPropertySet> xProps; | |
| Event.ReplacedElement >>= xProps; | |
| if ( xProps.is() ) | |
| RemoveElement( xProps ); | |
| xProps.clear(); | |
| Event.Element >>= xProps; | |
| if ( xProps.is() ) | |
| InsertElement( xProps ); | |
| } | |
| // Other functions | |
| //------------------------------------------------------------------ | |
| Sequence<Reference<XControlModel> > OGroupManager::getControlModels() | |
| { | |
| return m_pCompGroup->GetControlModels(); | |
| } | |
| //------------------------------------------------------------------ | |
| sal_Int32 OGroupManager::getGroupCount() | |
| { | |
| return m_aActiveGroupMap.size(); | |
| } | |
| //------------------------------------------------------------------ | |
| void OGroupManager::getGroup(sal_Int32 nGroup, Sequence< Reference<XControlModel> >& _rGroup, ::rtl::OUString& _rName) | |
| { | |
| OSL_ENSURE(nGroup >= 0 && (size_t)nGroup < m_aActiveGroupMap.size(),"OGroupManager::getGroup: Invalid group index!"); | |
| OGroupArr::iterator aGroupPos = m_aActiveGroupMap[nGroup]; | |
| _rName = aGroupPos->second.GetGroupName(); | |
| _rGroup = aGroupPos->second.GetControlModels(); | |
| } | |
| //------------------------------------------------------------------ | |
| void OGroupManager::getGroupByName(const ::rtl::OUString& _rName, Sequence< Reference<XControlModel> >& _rGroup) | |
| { | |
| OGroupArr::iterator aFind = m_aGroupArr.find(_rName); | |
| if ( aFind != m_aGroupArr.end() ) | |
| _rGroup = aFind->second.GetControlModels(); | |
| } | |
| //------------------------------------------------------------------ | |
| void OGroupManager::InsertElement( const Reference<XPropertySet>& xSet ) | |
| { | |
| // Nur ControlModels | |
| Reference<XControlModel> xControl(xSet, UNO_QUERY); | |
| if (!xControl.is() ) | |
| return; | |
| // Component in CompGroup aufnehmen | |
| m_pCompGroup->InsertComponent( xSet ); | |
| // Component in Gruppe aufnehmen | |
| ::rtl::OUString sGroupName; | |
| xSet->getPropertyValue( PROPERTY_NAME ) >>= sGroupName; | |
| OGroupArr::iterator aFind = m_aGroupArr.find(sGroupName); | |
| if ( aFind == m_aGroupArr.end() ) | |
| { | |
| aFind = m_aGroupArr.insert(OGroupArr::value_type(sGroupName,OGroup(sGroupName))).first; | |
| } | |
| aFind->second.InsertComponent( xSet ); | |
| // if we have at least 2 elements in the group, then this is an "active group" | |
| bool bActivateGroup = aFind->second.Count() == 2; | |
| // Additionally, if the component is a radio button, then it's group becomes active, | |
| // too. With this, we ensure that in a container with n radio buttons which all are | |
| // in different groups the selection still works reliably (means that all radios can be | |
| // clicked independently) | |
| if ( aFind->second.Count() == 1 ) | |
| { | |
| if ( isRadioButton( xSet ) ) | |
| bActivateGroup = true; | |
| } | |
| if ( bActivateGroup ) | |
| { | |
| OActiveGroups::iterator aAlreadyExistent = ::std::find( | |
| m_aActiveGroupMap.begin(), | |
| m_aActiveGroupMap.end(), | |
| aFind | |
| ); | |
| if ( aAlreadyExistent == m_aActiveGroupMap.end() ) | |
| m_aActiveGroupMap.push_back( aFind ); | |
| } | |
| // Bei Component als PropertyChangeListener anmelden | |
| xSet->addPropertyChangeListener( PROPERTY_NAME, this ); | |
| // Tabindex muss nicht jeder unterstuetzen | |
| if (hasProperty(PROPERTY_TABINDEX, xSet)) | |
| xSet->addPropertyChangeListener( PROPERTY_TABINDEX, this ); | |
| } | |
| //------------------------------------------------------------------ | |
| void OGroupManager::RemoveElement( const Reference<XPropertySet>& xSet ) | |
| { | |
| // Nur ControlModels | |
| Reference<XControlModel> xControl(xSet, UNO_QUERY); | |
| if (!xControl.is() ) | |
| return; | |
| // Component aus Gruppe entfernen | |
| ::rtl::OUString sGroupName; | |
| xSet->getPropertyValue( PROPERTY_NAME ) >>= sGroupName; | |
| removeFromGroupMap(sGroupName,xSet); | |
| } | |
| //......................................................................... | |
| } // namespace frm | |
| //......................................................................... | |