LCOV - code coverage report
Current view: top level - forms/source/component - GroupManager.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 177 195 90.8 %
Date: 2015-06-13 12:38:46 Functions: 29 32 90.6 %
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 <osl/diagnose.h>
      25             : #include <tools/solar.h>
      26             : 
      27             : #include "property.hrc"
      28             : 
      29             : #include <algorithm>
      30             : 
      31             : namespace frm
      32             : {
      33             : using namespace ::com::sun::star::uno;
      34             : using namespace ::com::sun::star::sdbc;
      35             : using namespace ::com::sun::star::beans;
      36             : using namespace ::com::sun::star::container;
      37             : using namespace ::com::sun::star::form;
      38             : using namespace ::com::sun::star::awt;
      39             : using namespace ::com::sun::star::lang;
      40             : 
      41             : namespace
      42             : {
      43         707 :     bool isRadioButton( const Reference< XPropertySet >& _rxComponent )
      44             :     {
      45         707 :         bool bIs = false;
      46         707 :         if ( hasProperty( PROPERTY_CLASSID, _rxComponent ) )
      47             :         {
      48         707 :             sal_Int16 nClassId = FormComponentType::CONTROL;
      49         707 :             _rxComponent->getPropertyValue( PROPERTY_CLASSID ) >>= nClassId;
      50         707 :             if ( nClassId == FormComponentType::RADIOBUTTON )
      51          41 :                 bIs = true;
      52             :         }
      53         707 :         return bIs;
      54             :     }
      55             : }
      56             : 
      57        2712 : OGroupCompAcc::OGroupCompAcc(const Reference<XPropertySet>& rxElement, const OGroupComp& _rGroupComp )
      58             :                :m_xComponent( rxElement )
      59        2712 :                ,m_aGroupComp( _rGroupComp )
      60             : {
      61        2712 : }
      62             : 
      63        1274 : bool OGroupCompAcc::operator==( const OGroupCompAcc& rCompAcc ) const
      64             : {
      65        1274 :     return (m_xComponent == rCompAcc.GetComponent());
      66             : }
      67             : 
      68             : class OGroupCompAccLess : public ::std::binary_function<OGroupCompAcc, OGroupCompAcc, sal_Bool>
      69             : {
      70             : public:
      71        2309 :     bool operator() (const OGroupCompAcc& lhs, const OGroupCompAcc& rhs) const
      72             :     {
      73             :         return
      74        2309 :             reinterpret_cast<sal_Int64>(lhs.m_xComponent.get())
      75        2309 :         <   reinterpret_cast<sal_Int64>(rhs.m_xComponent.get());
      76             :     }
      77             : };
      78             : 
      79        1274 : OGroupComp::OGroupComp()
      80             :     :m_nPos( -1 )
      81        1274 :     ,m_nTabIndex( 0 )
      82             : {
      83        1274 : }
      84             : 
      85        7110 : OGroupComp::OGroupComp(const OGroupComp& _rSource)
      86             :     :m_aName( _rSource.m_aName )
      87             :     ,m_xComponent( _rSource.m_xComponent )
      88             :     ,m_xControlModel(_rSource.m_xControlModel)
      89             :     ,m_nPos( _rSource.m_nPos )
      90        7110 :     ,m_nTabIndex( _rSource.m_nTabIndex )
      91             : {
      92        7110 : }
      93             : 
      94        1438 : OGroupComp::OGroupComp(const Reference<XPropertySet>& rxSet, sal_Int32 nInsertPos )
      95             :     : m_aName( OGroupManager::GetGroupName( rxSet ) )
      96             :     , m_xComponent( rxSet )
      97             :     , m_xControlModel(rxSet,UNO_QUERY)
      98             :     , m_nPos( nInsertPos )
      99        1438 :     , m_nTabIndex(0)
     100             : {
     101        1438 :     if (m_xComponent.is())
     102             :     {
     103        1438 :         if (hasProperty( PROPERTY_TABINDEX, m_xComponent ) )
     104             :             // Indices smaller than 0 are treated like 0
     105        1284 :             m_nTabIndex = std::max(getINT16(m_xComponent->getPropertyValue( PROPERTY_TABINDEX )) , sal_Int16(0));
     106             :     }
     107        1438 : }
     108             : 
     109        1274 : bool OGroupComp::operator==( const OGroupComp& rComp ) const
     110             : {
     111        1274 :     return m_nTabIndex == rComp.GetTabIndex() && m_nPos == rComp.GetPos();
     112             : }
     113             : 
     114             : class OGroupCompLess : public ::std::binary_function<OGroupComp, OGroupComp, sal_Bool>
     115             : {
     116             : public:
     117        2298 :     bool operator() (const OGroupComp& lhs, const OGroupComp& rhs) const
     118             :     {
     119             :         bool bResult;
     120             :         // TabIndex of 0 will be added at the end
     121        2298 :         if (lhs.m_nTabIndex == rhs.GetTabIndex())
     122        1776 :             bResult = lhs.m_nPos < rhs.GetPos();
     123         522 :         else if (lhs.m_nTabIndex && rhs.GetTabIndex())
     124           2 :             bResult = lhs.m_nTabIndex < rhs.GetTabIndex();
     125             :         else
     126         520 :             bResult = lhs.m_nTabIndex != 0;
     127        2298 :         return bResult;
     128             :     }
     129             : };
     130             : 
     131         697 : OGroup::OGroup( const OUString& rGroupName )
     132             :         :m_aGroupName( rGroupName )
     133         697 :         ,m_nInsertPos(0)
     134             : {
     135         697 : }
     136             : 
     137        1905 : OGroup::~OGroup()
     138             : {
     139        1905 : }
     140             : 
     141        1438 : void OGroup::InsertComponent( const Reference<XPropertySet>& xSet )
     142             : {
     143        1438 :     OGroupComp aNewGroupComp( xSet, m_nInsertPos );
     144        1438 :     sal_Int32 nPosInserted = insert_sorted(m_aCompArray, aNewGroupComp, OGroupCompLess());
     145             : 
     146        2876 :     OGroupCompAcc aNewGroupCompAcc( xSet, m_aCompArray[nPosInserted] );
     147        1438 :     insert_sorted(m_aCompAccArray, aNewGroupCompAcc, OGroupCompAccLess());
     148        2876 :     m_nInsertPos++;
     149        1438 : }
     150             : 
     151        1274 : void OGroup::RemoveComponent( const Reference<XPropertySet>& rxElement )
     152             : {
     153             :     sal_Int32 nGroupCompAccPos;
     154        1274 :     OGroupCompAcc aSearchCompAcc( rxElement, OGroupComp() );
     155        1274 :     if ( seek_entry(m_aCompAccArray, aSearchCompAcc, nGroupCompAccPos, OGroupCompAccLess()) )
     156             :     {
     157        1274 :         OGroupCompAcc& aGroupCompAcc = m_aCompAccArray[nGroupCompAccPos];
     158        1274 :         const OGroupComp& aGroupComp = aGroupCompAcc.GetGroupComponent();
     159             : 
     160             :         sal_Int32 nGroupCompPos;
     161        1274 :         if ( seek_entry(m_aCompArray, aGroupComp, nGroupCompPos, OGroupCompLess()) )
     162             :         {
     163        1274 :             m_aCompAccArray.erase( m_aCompAccArray.begin() + nGroupCompAccPos );
     164        1274 :             m_aCompArray.erase( m_aCompArray.begin() + nGroupCompPos );
     165             : 
     166             :             /*
     167             :              * By removing the GroupComp the insertion position has become invalid.
     168             :              * We do not to change it here, however, because its passed on continuously
     169             :              * and ascending distinctively.
     170             :              */
     171             :         }
     172             :         else
     173             :         {
     174             :             OSL_FAIL( "OGroup::RemoveComponent: Component not in Group" );
     175             :         }
     176             :     }
     177             :     else
     178             :     {
     179             :         OSL_FAIL( "OGroup::RemoveComponent: Component not in Group" );
     180        1274 :     }
     181        1274 : }
     182             : 
     183           0 : bool OGroup::operator==( const OGroup& rGroup ) const
     184             : {
     185           0 :     return m_aGroupName.equals(rGroup.GetGroupName());
     186             : }
     187             : 
     188         282 : Sequence< Reference<XControlModel>  > OGroup::GetControlModels() const
     189             : {
     190         282 :     sal_Int32 nLen = m_aCompArray.size();
     191         282 :     Sequence<Reference<XControlModel> > aControlModelSeq( nLen );
     192         282 :     Reference<XControlModel>* pModels = aControlModelSeq.getArray();
     193             : 
     194         282 :     OGroupCompArr::const_iterator aGroupComps = m_aCompArray.begin();
     195         741 :     for (sal_Int32 i = 0; i < nLen; ++i, ++pModels, ++aGroupComps)
     196             :     {
     197         459 :         *pModels = aGroupComps->GetControlModel();
     198             :     }
     199         282 :     return aControlModelSeq;
     200             : }
     201             : 
     202         184 : OGroupManager::OGroupManager(const Reference< XContainer >& _rxContainer)
     203         184 :     :m_pCompGroup( new OGroup( OUString("AllComponentGroup") ) )
     204         368 :     ,m_xContainer(_rxContainer)
     205             : {
     206         184 :     osl_atomic_increment(&m_refCount);
     207             :     {
     208         184 :         _rxContainer->addContainerListener(this);
     209             :     }
     210         184 :     osl_atomic_decrement(&m_refCount);
     211         184 : }
     212             : 
     213         546 : OGroupManager::~OGroupManager()
     214             : {
     215             :     // delete all Components and CompGroup
     216         182 :     delete m_pCompGroup;
     217         364 : }
     218             : 
     219             : // XPropertyChangeListener
     220         354 : void OGroupManager::disposing(const EventObject& evt) throw( RuntimeException, std::exception )
     221             : {
     222         354 :     Reference<XContainer>  xContainer(evt.Source, UNO_QUERY);
     223         354 :     if (xContainer.get() == m_xContainer.get())
     224             :     {
     225         183 :         DELETEZ(m_pCompGroup);
     226             : 
     227             :         // delete group
     228         183 :         m_aGroupArr.clear();
     229         183 :         m_xContainer.clear();
     230         354 :     }
     231         354 : }
     232             : 
     233         637 : void OGroupManager::removeFromGroupMap(const OUString& _sGroupName,const Reference<XPropertySet>& _xSet)
     234             : {
     235             :     // remove Component from CompGroup
     236         637 :     m_pCompGroup->RemoveComponent( _xSet );
     237             : 
     238         637 :     OGroupArr::iterator aFind = m_aGroupArr.find(_sGroupName);
     239             : 
     240         637 :     if ( aFind != m_aGroupArr.end() )
     241             :     {
     242             :         // group exists
     243         637 :         aFind->second.RemoveComponent( _xSet );
     244             : 
     245             :         // If the count of Group elements == 1 -> deactivate Group
     246         637 :         sal_Int32 nCount = aFind->second.Count();
     247         637 :         if ( nCount == 1 || nCount == 0 )
     248             :         {
     249             :             OActiveGroups::iterator aActiveFind = ::std::find(
     250             :                 m_aActiveGroupMap.begin(),
     251             :                 m_aActiveGroupMap.end(),
     252             :                 aFind
     253         631 :             );
     254         631 :             if ( aActiveFind != m_aActiveGroupMap.end() )
     255             :             {
     256             :                 // the group is active. Deactivate it if the remaining component
     257             :                 // is *no* radio button
     258          36 :                 if ( nCount == 0 || !isRadioButton( aFind->second.GetObject( 0 ) ) )
     259          36 :                     m_aActiveGroupMap.erase( aActiveFind );
     260             :             }
     261             :         }
     262             :     }
     263             : 
     264             : 
     265             :     // Deregister as PropertyChangeListener at Component
     266         637 :     _xSet->removePropertyChangeListener( PROPERTY_NAME, this );
     267         637 :     if (hasProperty(PROPERTY_GROUP_NAME, _xSet))
     268          34 :         _xSet->removePropertyChangeListener( PROPERTY_GROUP_NAME, this );
     269         637 :     if (hasProperty(PROPERTY_TABINDEX, _xSet))
     270         564 :         _xSet->removePropertyChangeListener( PROPERTY_TABINDEX, this );
     271         637 : }
     272             : 
     273         392 : void SAL_CALL OGroupManager::propertyChange(const PropertyChangeEvent& evt) throw ( ::com::sun::star::uno::RuntimeException, std::exception)
     274             : {
     275         392 :     Reference<XPropertySet>  xSet(evt.Source, UNO_QUERY);
     276             : 
     277             :     // remove Component from group
     278         774 :     OUString     sGroupName;
     279         392 :     if (hasProperty( PROPERTY_GROUP_NAME, xSet ))
     280          36 :         xSet->getPropertyValue( PROPERTY_GROUP_NAME ) >>= sGroupName;
     281         392 :     if (evt.PropertyName == PROPERTY_NAME) {
     282         211 :         if (!sGroupName.isEmpty())
     283         402 :             return; // group hasn't changed; ignore this name change.
     284             :         // no GroupName; use Name as GroupNme
     285         201 :         evt.OldValue >>= sGroupName;
     286             :     }
     287         181 :     else if (evt.PropertyName == PROPERTY_GROUP_NAME) {
     288          10 :         evt.OldValue >>= sGroupName;
     289          10 :         if (sGroupName.isEmpty()) {
     290             :             // No prior GroupName; fallback to Nme
     291           3 :             xSet->getPropertyValue( PROPERTY_NAME ) >>= sGroupName;
     292             :         }
     293             :     }
     294             :     else
     295         171 :         sGroupName = GetGroupName( xSet );
     296             : 
     297         382 :     removeFromGroupMap(sGroupName,xSet);
     298             : 
     299             :     // Re-insert Component
     300         764 :     InsertElement( xSet );
     301             : }
     302             : 
     303             : // XContainerListener
     304         341 : void SAL_CALL OGroupManager::elementInserted(const ContainerEvent& Event) throw ( ::com::sun::star::uno::RuntimeException, std::exception)
     305             : {
     306         341 :     Reference< XPropertySet > xProps;
     307         341 :     Event.Element >>= xProps;
     308         341 :     if ( xProps.is() )
     309         341 :         InsertElement( xProps );
     310         341 : }
     311             : 
     312         255 : void SAL_CALL OGroupManager::elementRemoved(const ContainerEvent& Event) throw ( ::com::sun::star::uno::RuntimeException, std::exception)
     313             : {
     314         255 :     Reference<XPropertySet> xProps;
     315         255 :     Event.Element >>= xProps;
     316         255 :     if ( xProps.is() )
     317         255 :         RemoveElement( xProps );
     318         255 : }
     319             : 
     320           0 : void SAL_CALL OGroupManager::elementReplaced(const ContainerEvent& Event) throw ( ::com::sun::star::uno::RuntimeException, std::exception)
     321             : {
     322           0 :     Reference<XPropertySet> xProps;
     323           0 :     Event.ReplacedElement >>= xProps;
     324           0 :     if ( xProps.is() )
     325           0 :         RemoveElement( xProps );
     326             : 
     327           0 :     xProps.clear();
     328           0 :     Event.Element >>= xProps;
     329           0 :     if ( xProps.is() )
     330           0 :         InsertElement( xProps );
     331           0 : }
     332             : 
     333             : // Other functions
     334         269 : Sequence<Reference<XControlModel> > OGroupManager::getControlModels()
     335             : {
     336         269 :     return m_pCompGroup->GetControlModels();
     337             : }
     338             : 
     339         149 : sal_Int32 OGroupManager::getGroupCount()
     340             : {
     341         149 :     return m_aActiveGroupMap.size();
     342             : }
     343             : 
     344          13 : void OGroupManager::getGroup(sal_Int32 nGroup, Sequence< Reference<XControlModel> >& _rGroup, OUString& _rName)
     345             : {
     346             :     OSL_ENSURE(nGroup >= 0 && (size_t)nGroup < m_aActiveGroupMap.size(),"OGroupManager::getGroup: Invalid group index!");
     347          13 :     OGroupArr::iterator aGroupPos   = m_aActiveGroupMap[nGroup];
     348          13 :     _rName                          = aGroupPos->second.GetGroupName();
     349          13 :     _rGroup                         = aGroupPos->second.GetControlModels();
     350          13 : }
     351             : 
     352           0 : void OGroupManager::getGroupByName(const OUString& _rName, Sequence< Reference<XControlModel>  >& _rGroup)
     353             : {
     354           0 :     OGroupArr::iterator aFind = m_aGroupArr.find(_rName);
     355           0 :     if ( aFind != m_aGroupArr.end() )
     356           0 :         _rGroup = aFind->second.GetControlModels();
     357           0 : }
     358             : 
     359         723 : void OGroupManager::InsertElement( const Reference<XPropertySet>& xSet )
     360             : {
     361             :     // Only ControlModels
     362         723 :     Reference<XControlModel>  xControl(xSet, UNO_QUERY);
     363         723 :     if (!xControl.is() )
     364         727 :         return;
     365             : 
     366             :     // Add Component to CompGroup
     367         719 :     m_pCompGroup->InsertComponent( xSet );
     368             : 
     369             :     // Add Component to Group
     370        1438 :     OUString sGroupName( GetGroupName( xSet ) );
     371             : 
     372         719 :     OGroupArr::iterator aFind = m_aGroupArr.find(sGroupName);
     373             : 
     374         719 :     if ( aFind == m_aGroupArr.end() )
     375             :     {
     376         513 :         aFind = m_aGroupArr.insert(OGroupArr::value_type(sGroupName,OGroup(sGroupName))).first;
     377             :     }
     378             : 
     379         719 :     aFind->second.InsertComponent( xSet );
     380             : 
     381             :     // if we have at least 2 elements in the group, then this is an "active group"
     382         719 :     bool bActivateGroup = aFind->second.Count() == 2;
     383             : 
     384             :     // Additionally, if the component is a radio button, then it's group becomes active,
     385             :     // too. With this, we ensure that in a container with n radio buttons which all are
     386             :     // in different groups the selection still works reliably (means that all radios can be
     387             :     // clicked independently)
     388         719 :     if ( aFind->second.Count() == 1 )
     389             :     {
     390         705 :         if ( isRadioButton( xSet ) )
     391          41 :             bActivateGroup = true;
     392             :     }
     393             : 
     394         719 :     if ( bActivateGroup )
     395             :     {
     396             :         OActiveGroups::iterator aAlreadyExistent = ::std::find(
     397             :             m_aActiveGroupMap.begin(),
     398             :             m_aActiveGroupMap.end(),
     399             :             aFind
     400          45 :         );
     401          45 :         if ( aAlreadyExistent == m_aActiveGroupMap.end() )
     402          45 :             m_aActiveGroupMap.push_back(  aFind );
     403             :     }
     404             : 
     405             :     // Register as PropertyChangeListener at Component
     406         719 :     xSet->addPropertyChangeListener( PROPERTY_NAME, this );
     407         719 :     if (hasProperty(PROPERTY_GROUP_NAME, xSet))
     408          45 :         xSet->addPropertyChangeListener( PROPERTY_GROUP_NAME, this );
     409             : 
     410             :     // Not everyone needs to support Tabindex
     411         719 :     if (hasProperty(PROPERTY_TABINDEX, xSet))
     412        1361 :         xSet->addPropertyChangeListener( PROPERTY_TABINDEX, this );
     413             : }
     414             : 
     415         255 : void OGroupManager::RemoveElement( const Reference<XPropertySet>& xSet )
     416             : {
     417             :     // Only ControlModels
     418         255 :     Reference<XControlModel>  xControl(xSet, UNO_QUERY);
     419         255 :     if (!xControl.is() )
     420         255 :         return;
     421             : 
     422             :     // Remove Component from Group
     423         510 :     OUString     sGroupName( GetGroupName( xSet ) );
     424             : 
     425         510 :     removeFromGroupMap(sGroupName,xSet);
     426             : }
     427             : 
     428        2583 : OUString OGroupManager::GetGroupName( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet> xComponent )
     429             : {
     430        2583 :     if (!xComponent.is())
     431           0 :         return OUString();
     432        2583 :     OUString sGroupName;
     433        2583 :     if (hasProperty( PROPERTY_GROUP_NAME, xComponent )) {
     434         155 :         xComponent->getPropertyValue( PROPERTY_GROUP_NAME ) >>= sGroupName;
     435         155 :         if (sGroupName.isEmpty())
     436          82 :             xComponent->getPropertyValue( PROPERTY_NAME ) >>= sGroupName;
     437             :     }
     438             :     else
     439        2428 :         xComponent->getPropertyValue( PROPERTY_NAME ) >>= sGroupName;
     440        2583 :     return sGroupName;
     441             : }
     442             : }   // namespace frm
     443             : 
     444             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11