LCOV - code coverage report
Current view: top level - forms/source/component - GroupManager.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 195 0.0 %
Date: 2014-04-14 Functions: 0 32 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #include "GroupManager.hxx"
      21             : #include <com/sun/star/beans/XFastPropertySet.hpp>
      22             : #include <com/sun/star/form/FormComponentType.hpp>
      23             : #include <comphelper/property.hxx>
      24             : #include <comphelper/uno3.hxx>
      25             : #include <tools/solar.h>
      26             : #include <tools/debug.hxx>
      27             : 
      28             : #include "property.hrc"
      29             : 
      30             : #include <algorithm>
      31             : 
      32             : namespace frm
      33             : {
      34             : using namespace ::com::sun::star::uno;
      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::lang;
      41             : 
      42             : namespace
      43             : {
      44           0 :     bool isRadioButton( const Reference< XPropertySet >& _rxComponent )
      45             :     {
      46           0 :         bool bIs = false;
      47           0 :         if ( hasProperty( PROPERTY_CLASSID, _rxComponent ) )
      48             :         {
      49           0 :             sal_Int16 nClassId = FormComponentType::CONTROL;
      50           0 :             _rxComponent->getPropertyValue( PROPERTY_CLASSID ) >>= nClassId;
      51           0 :             if ( nClassId == FormComponentType::RADIOBUTTON )
      52           0 :                 bIs = true;
      53             :         }
      54           0 :         return bIs;
      55             :     }
      56             : }
      57             : 
      58             : // class OGroupCompAcc
      59           0 : OGroupCompAcc::OGroupCompAcc(const Reference<XPropertySet>& rxElement, const OGroupComp& _rGroupComp )
      60             :                :m_xComponent( rxElement )
      61           0 :                ,m_aGroupComp( _rGroupComp )
      62             : {
      63           0 : }
      64             : 
      65           0 : sal_Bool OGroupCompAcc::operator==( const OGroupCompAcc& rCompAcc ) const
      66             : {
      67           0 :     return (m_xComponent == rCompAcc.GetComponent());
      68             : }
      69             : 
      70             : class OGroupCompAccLess : public ::std::binary_function<OGroupCompAcc, OGroupCompAcc, sal_Bool>
      71             : {
      72             : public:
      73           0 :     sal_Bool operator() (const OGroupCompAcc& lhs, const OGroupCompAcc& rhs) const
      74             :     {
      75             :         return
      76           0 :             reinterpret_cast<sal_Int64>(lhs.m_xComponent.get())
      77           0 :         <   reinterpret_cast<sal_Int64>(rhs.m_xComponent.get());
      78             :     }
      79             : };
      80             : 
      81             : // class OGroupComp
      82           0 : OGroupComp::OGroupComp()
      83             :     :m_nPos( -1 )
      84           0 :     ,m_nTabIndex( 0 )
      85             : {
      86           0 : }
      87             : 
      88           0 : OGroupComp::OGroupComp(const OGroupComp& _rSource)
      89             :     :m_aName( _rSource.m_aName )
      90             :     ,m_xComponent( _rSource.m_xComponent )
      91             :     ,m_xControlModel(_rSource.m_xControlModel)
      92             :     ,m_nPos( _rSource.m_nPos )
      93           0 :     ,m_nTabIndex( _rSource.m_nTabIndex )
      94             : {
      95           0 : }
      96             : 
      97           0 : OGroupComp::OGroupComp(const Reference<XPropertySet>& rxSet, sal_Int32 nInsertPos )
      98             :     : m_aName( OGroupManager::GetGroupName( rxSet ) )
      99             :     , m_xComponent( rxSet )
     100             :     , m_xControlModel(rxSet,UNO_QUERY)
     101             :     , m_nPos( nInsertPos )
     102           0 :     , m_nTabIndex(0)
     103             : {
     104           0 :     if (m_xComponent.is())
     105             :     {
     106           0 :         if (hasProperty( PROPERTY_TABINDEX, m_xComponent ) )
     107             :             // Indices smaller than 0 are treated like 0
     108           0 :             m_nTabIndex = std::max(getINT16(m_xComponent->getPropertyValue( PROPERTY_TABINDEX )) , sal_Int16(0));
     109             :     }
     110           0 : }
     111             : 
     112           0 : sal_Bool OGroupComp::operator==( const OGroupComp& rComp ) const
     113             : {
     114           0 :     return m_nTabIndex == rComp.GetTabIndex() && m_nPos == rComp.GetPos();
     115             : }
     116             : 
     117             : class OGroupCompLess : public ::std::binary_function<OGroupComp, OGroupComp, sal_Bool>
     118             : {
     119             : public:
     120           0 :     sal_Bool operator() (const OGroupComp& lhs, const OGroupComp& rhs) const
     121             :     {
     122             :         sal_Bool bResult;
     123             :         // TabIndex von 0 wird hinten einsortiert
     124           0 :         if (lhs.m_nTabIndex == rhs.GetTabIndex())
     125           0 :             bResult = lhs.m_nPos < rhs.GetPos();
     126           0 :         else if (lhs.m_nTabIndex && rhs.GetTabIndex())
     127           0 :             bResult = lhs.m_nTabIndex < rhs.GetTabIndex();
     128             :         else
     129           0 :             bResult = lhs.m_nTabIndex != 0;
     130           0 :         return bResult;
     131             :     }
     132             : };
     133             : 
     134             : // class OGroup
     135           0 : OGroup::OGroup( const OUString& rGroupName )
     136             :         :m_aGroupName( rGroupName )
     137           0 :         ,m_nInsertPos(0)
     138             : {
     139           0 : }
     140             : 
     141           0 : OGroup::~OGroup()
     142             : {
     143           0 : }
     144             : 
     145           0 : void OGroup::InsertComponent( const Reference<XPropertySet>& xSet )
     146             : {
     147           0 :     OGroupComp aNewGroupComp( xSet, m_nInsertPos );
     148           0 :     sal_Int32 nPosInserted = insert_sorted(m_aCompArray, aNewGroupComp, OGroupCompLess());
     149             : 
     150           0 :     OGroupCompAcc aNewGroupCompAcc( xSet, m_aCompArray[nPosInserted] );
     151           0 :     insert_sorted(m_aCompAccArray, aNewGroupCompAcc, OGroupCompAccLess());
     152           0 :     m_nInsertPos++;
     153           0 : }
     154             : 
     155           0 : void OGroup::RemoveComponent( const Reference<XPropertySet>& rxElement )
     156             : {
     157             :     sal_Int32 nGroupCompAccPos;
     158           0 :     OGroupCompAcc aSearchCompAcc( rxElement, OGroupComp() );
     159           0 :     if ( seek_entry(m_aCompAccArray, aSearchCompAcc, nGroupCompAccPos, OGroupCompAccLess()) )
     160             :     {
     161           0 :         OGroupCompAcc& aGroupCompAcc = m_aCompAccArray[nGroupCompAccPos];
     162           0 :         const OGroupComp& aGroupComp = aGroupCompAcc.GetGroupComponent();
     163             : 
     164             :         sal_Int32 nGroupCompPos;
     165           0 :         if ( seek_entry(m_aCompArray, aGroupComp, nGroupCompPos, OGroupCompLess()) )
     166             :         {
     167           0 :             m_aCompAccArray.erase( m_aCompAccArray.begin() + nGroupCompAccPos );
     168           0 :             m_aCompArray.erase( m_aCompArray.begin() + nGroupCompPos );
     169             : 
     170             :             /*
     171             :             Durch das Entfernen der GroupComp ist die Einfuegeposition
     172             :             ungueltig geworden. Sie braucht hier aber nicht angepasst werden,
     173             :             da sie fortlaufend vergeben wird und damit immer
     174             :             aufsteigend eindeutig ist.
     175             :             */
     176             :         }
     177             :         else
     178             :         {
     179             :             OSL_FAIL( "OGroup::RemoveComponent: Component nicht in Gruppe" );
     180             :         }
     181             :     }
     182             :     else
     183             :     {
     184             :         OSL_FAIL( "OGroup::RemoveComponent: Component nicht in Gruppe" );
     185           0 :     }
     186           0 : }
     187             : 
     188           0 : sal_Bool OGroup::operator==( const OGroup& rGroup ) const
     189             : {
     190           0 :     return m_aGroupName.equals(rGroup.GetGroupName());
     191             : }
     192             : 
     193             : class OGroupLess : public ::std::binary_function<OGroup, OGroup, sal_Bool>
     194             : {
     195             : public:
     196             :     sal_Bool operator() (const OGroup& lhs, const OGroup& rhs) const
     197             :     {
     198             :         return lhs.m_aGroupName < rhs.m_aGroupName;
     199             :     }
     200             : };
     201             : 
     202           0 : Sequence< Reference<XControlModel>  > OGroup::GetControlModels() const
     203             : {
     204           0 :     sal_Int32 nLen = m_aCompArray.size();
     205           0 :     Sequence<Reference<XControlModel> > aControlModelSeq( nLen );
     206           0 :     Reference<XControlModel>* pModels = aControlModelSeq.getArray();
     207             : 
     208           0 :     OGroupCompArr::const_iterator aGroupComps = m_aCompArray.begin();
     209           0 :     for (sal_Int32 i = 0; i < nLen; ++i, ++pModels, ++aGroupComps)
     210             :     {
     211           0 :         *pModels = aGroupComps->GetControlModel();
     212             :     }
     213           0 :     return aControlModelSeq;
     214             : }
     215             : 
     216           0 : OGroupManager::OGroupManager(const Reference< XContainer >& _rxContainer)
     217           0 :     :m_pCompGroup( new OGroup( OUString("AllComponentGroup") ) )
     218           0 :     ,m_xContainer(_rxContainer)
     219             : {
     220           0 :     increment(m_refCount);
     221             :     {
     222           0 :         _rxContainer->addContainerListener(this);
     223             :     }
     224           0 :     decrement(m_refCount);
     225           0 : }
     226             : 
     227           0 : OGroupManager::~OGroupManager()
     228             : {
     229             :     // delete all Components and CompGroup
     230           0 :     delete m_pCompGroup;
     231           0 : }
     232             : 
     233             : // XPropertyChangeListener
     234           0 : void OGroupManager::disposing(const EventObject& evt) throw( RuntimeException, std::exception )
     235             : {
     236           0 :     Reference<XContainer>  xContainer(evt.Source, UNO_QUERY);
     237           0 :     if (xContainer.get() == m_xContainer.get())
     238             :     {
     239           0 :         DELETEZ(m_pCompGroup);
     240             : 
     241             :         // delete group
     242           0 :         m_aGroupArr.clear();
     243           0 :         m_xContainer.clear();
     244           0 :     }
     245           0 : }
     246             : 
     247           0 : void OGroupManager::removeFromGroupMap(const OUString& _sGroupName,const Reference<XPropertySet>& _xSet)
     248             : {
     249             :     // remove Component from CompGroup
     250           0 :     m_pCompGroup->RemoveComponent( _xSet );
     251             : 
     252           0 :     OGroupArr::iterator aFind = m_aGroupArr.find(_sGroupName);
     253             : 
     254           0 :     if ( aFind != m_aGroupArr.end() )
     255             :     {
     256             :         // group exists
     257           0 :         aFind->second.RemoveComponent( _xSet );
     258             : 
     259             :         // Wenn Anzahl der Gruppenelemente == 1 ist, Gruppe deaktivieren
     260           0 :         sal_Int32 nCount = aFind->second.Count();
     261           0 :         if ( nCount == 1 || nCount == 0 )
     262             :         {
     263             :             OActiveGroups::iterator aActiveFind = ::std::find(
     264             :                 m_aActiveGroupMap.begin(),
     265             :                 m_aActiveGroupMap.end(),
     266             :                 aFind
     267           0 :             );
     268           0 :             if ( aActiveFind != m_aActiveGroupMap.end() )
     269             :             {
     270             :                 // the group is active. Deactivate it if the remaining component
     271             :                 // is *no* radio button
     272           0 :                 if ( nCount == 0 || !isRadioButton( aFind->second.GetObject( 0 ) ) )
     273           0 :                     m_aActiveGroupMap.erase( aActiveFind );
     274             :             }
     275             :         }
     276             :     }
     277             : 
     278             : 
     279             :     // Bei Component als PropertyChangeListener abmelden
     280           0 :     _xSet->removePropertyChangeListener( PROPERTY_NAME, this );
     281           0 :     if (hasProperty(PROPERTY_GROUP_NAME, _xSet))
     282           0 :         _xSet->removePropertyChangeListener( PROPERTY_GROUP_NAME, this );
     283           0 :     if (hasProperty(PROPERTY_TABINDEX, _xSet))
     284           0 :         _xSet->removePropertyChangeListener( PROPERTY_TABINDEX, this );
     285           0 : }
     286             : 
     287           0 : void SAL_CALL OGroupManager::propertyChange(const PropertyChangeEvent& evt) throw ( ::com::sun::star::uno::RuntimeException, std::exception)
     288             : {
     289           0 :     Reference<XPropertySet>  xSet(evt.Source, UNO_QUERY);
     290             : 
     291             :     // remove Component from group
     292           0 :     OUString     sGroupName;
     293           0 :     if (hasProperty( PROPERTY_GROUP_NAME, xSet ))
     294           0 :         xSet->getPropertyValue( PROPERTY_GROUP_NAME ) >>= sGroupName;
     295           0 :     if (evt.PropertyName == PROPERTY_NAME) {
     296           0 :         if (!sGroupName.isEmpty())
     297           0 :             return; // group hasn't changed; ignore this name change.
     298             :         // no GroupName; use Name as GroupNme
     299           0 :         evt.OldValue >>= sGroupName;
     300             :     }
     301           0 :     else if (evt.PropertyName == PROPERTY_GROUP_NAME) {
     302           0 :         evt.OldValue >>= sGroupName;
     303           0 :         if (sGroupName.isEmpty()) {
     304             :             // No prior GroupName; fallback to Nme
     305           0 :             xSet->getPropertyValue( PROPERTY_NAME ) >>= sGroupName;
     306             :         }
     307             :     }
     308             :     else
     309           0 :         sGroupName = GetGroupName( xSet );
     310             : 
     311           0 :     removeFromGroupMap(sGroupName,xSet);
     312             : 
     313             :     // Component neu einordnen
     314           0 :     InsertElement( xSet );
     315             : }
     316             : 
     317             : // XContainerListener
     318           0 : void SAL_CALL OGroupManager::elementInserted(const ContainerEvent& Event) throw ( ::com::sun::star::uno::RuntimeException, std::exception)
     319             : {
     320           0 :     Reference< XPropertySet > xProps;
     321           0 :     Event.Element >>= xProps;
     322           0 :     if ( xProps.is() )
     323           0 :         InsertElement( xProps );
     324           0 : }
     325             : 
     326           0 : void SAL_CALL OGroupManager::elementRemoved(const ContainerEvent& Event) throw ( ::com::sun::star::uno::RuntimeException, std::exception)
     327             : {
     328           0 :     Reference<XPropertySet> xProps;
     329           0 :     Event.Element >>= xProps;
     330           0 :     if ( xProps.is() )
     331           0 :         RemoveElement( xProps );
     332           0 : }
     333             : 
     334           0 : void SAL_CALL OGroupManager::elementReplaced(const ContainerEvent& Event) throw ( ::com::sun::star::uno::RuntimeException, std::exception)
     335             : {
     336           0 :     Reference<XPropertySet> xProps;
     337           0 :     Event.ReplacedElement >>= xProps;
     338           0 :     if ( xProps.is() )
     339           0 :         RemoveElement( xProps );
     340             : 
     341           0 :     xProps.clear();
     342           0 :     Event.Element >>= xProps;
     343           0 :     if ( xProps.is() )
     344           0 :         InsertElement( xProps );
     345           0 : }
     346             : 
     347             : // Other functions
     348           0 : Sequence<Reference<XControlModel> > OGroupManager::getControlModels()
     349             : {
     350           0 :     return m_pCompGroup->GetControlModels();
     351             : }
     352             : 
     353           0 : sal_Int32 OGroupManager::getGroupCount()
     354             : {
     355           0 :     return m_aActiveGroupMap.size();
     356             : }
     357             : 
     358           0 : void OGroupManager::getGroup(sal_Int32 nGroup, Sequence< Reference<XControlModel> >& _rGroup, OUString& _rName)
     359             : {
     360             :     OSL_ENSURE(nGroup >= 0 && (size_t)nGroup < m_aActiveGroupMap.size(),"OGroupManager::getGroup: Invalid group index!");
     361           0 :     OGroupArr::iterator aGroupPos   = m_aActiveGroupMap[nGroup];
     362           0 :     _rName                          = aGroupPos->second.GetGroupName();
     363           0 :     _rGroup                         = aGroupPos->second.GetControlModels();
     364           0 : }
     365             : 
     366           0 : void OGroupManager::getGroupByName(const OUString& _rName, Sequence< Reference<XControlModel>  >& _rGroup)
     367             : {
     368           0 :     OGroupArr::iterator aFind = m_aGroupArr.find(_rName);
     369           0 :     if ( aFind != m_aGroupArr.end() )
     370           0 :         _rGroup = aFind->second.GetControlModels();
     371           0 : }
     372             : 
     373           0 : void OGroupManager::InsertElement( const Reference<XPropertySet>& xSet )
     374             : {
     375             :     // Nur ControlModels
     376           0 :     Reference<XControlModel>  xControl(xSet, UNO_QUERY);
     377           0 :     if (!xControl.is() )
     378           0 :         return;
     379             : 
     380             :     // Component in CompGroup aufnehmen
     381           0 :     m_pCompGroup->InsertComponent( xSet );
     382             : 
     383             :     // Component in Gruppe aufnehmen
     384           0 :     OUString sGroupName( GetGroupName( xSet ) );
     385             : 
     386           0 :     OGroupArr::iterator aFind = m_aGroupArr.find(sGroupName);
     387             : 
     388           0 :     if ( aFind == m_aGroupArr.end() )
     389             :     {
     390           0 :         aFind = m_aGroupArr.insert(OGroupArr::value_type(sGroupName,OGroup(sGroupName))).first;
     391             :     }
     392             : 
     393           0 :     aFind->second.InsertComponent( xSet );
     394             : 
     395             :     // if we have at least 2 elements in the group, then this is an "active group"
     396           0 :     bool bActivateGroup = aFind->second.Count() == 2;
     397             : 
     398             :     // Additionally, if the component is a radio button, then it's group becomes active,
     399             :     // too. With this, we ensure that in a container with n radio buttons which all are
     400             :     // in different groups the selection still works reliably (means that all radios can be
     401             :     // clicked independently)
     402           0 :     if ( aFind->second.Count() == 1 )
     403             :     {
     404           0 :         if ( isRadioButton( xSet ) )
     405           0 :             bActivateGroup = true;
     406             :     }
     407             : 
     408           0 :     if ( bActivateGroup )
     409             :     {
     410             :         OActiveGroups::iterator aAlreadyExistent = ::std::find(
     411             :             m_aActiveGroupMap.begin(),
     412             :             m_aActiveGroupMap.end(),
     413             :             aFind
     414           0 :         );
     415           0 :         if ( aAlreadyExistent == m_aActiveGroupMap.end() )
     416           0 :             m_aActiveGroupMap.push_back(  aFind );
     417             :     }
     418             : 
     419             :     // Bei Component als PropertyChangeListener anmelden
     420           0 :     xSet->addPropertyChangeListener( PROPERTY_NAME, this );
     421           0 :     if (hasProperty(PROPERTY_GROUP_NAME, xSet))
     422           0 :         xSet->addPropertyChangeListener( PROPERTY_GROUP_NAME, this );
     423             : 
     424             :     // Tabindex muss nicht jeder unterstuetzen
     425           0 :     if (hasProperty(PROPERTY_TABINDEX, xSet))
     426           0 :         xSet->addPropertyChangeListener( PROPERTY_TABINDEX, this );
     427             : }
     428             : 
     429           0 : void OGroupManager::RemoveElement( const Reference<XPropertySet>& xSet )
     430             : {
     431             :     // Nur ControlModels
     432           0 :     Reference<XControlModel>  xControl(xSet, UNO_QUERY);
     433           0 :     if (!xControl.is() )
     434           0 :         return;
     435             : 
     436             :     // Component aus Gruppe entfernen
     437           0 :     OUString     sGroupName( GetGroupName( xSet ) );
     438             : 
     439           0 :     removeFromGroupMap(sGroupName,xSet);
     440             : }
     441             : 
     442           0 : OUString OGroupManager::GetGroupName( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet> xComponent )
     443             : {
     444           0 :     if (!xComponent.is())
     445           0 :         return OUString();
     446           0 :     OUString sGroupName;
     447           0 :     if (hasProperty( PROPERTY_GROUP_NAME, xComponent )) {
     448           0 :         xComponent->getPropertyValue( PROPERTY_GROUP_NAME ) >>= sGroupName;
     449           0 :         if (sGroupName.isEmpty())
     450           0 :             xComponent->getPropertyValue( PROPERTY_NAME ) >>= sGroupName;
     451             :     }
     452             :     else
     453           0 :         xComponent->getPropertyValue( PROPERTY_NAME ) >>= sGroupName;
     454           0 :     return sGroupName;
     455             : }
     456             : }   // namespace frm
     457             : 
     458             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10