| /************************************************************** |
| * |
| * 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 |
| //......................................................................... |
| |