LCOV - code coverage report
Current view: top level - forms/source/component - GroupManager.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 177 195 90.8 %
Date: 2014-04-11 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 <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         688 :     bool isRadioButton( const Reference< XPropertySet >& _rxComponent )
      45             :     {
      46         688 :         bool bIs = false;
      47         688 :         if ( hasProperty( PROPERTY_CLASSID, _rxComponent ) )
      48             :         {
      49         688 :             sal_Int16 nClassId = FormComponentType::CONTROL;
      50         688 :             _rxComponent->getPropertyValue( PROPERTY_CLASSID ) >>= nClassId;
      51         688 :             if ( nClassId == FormComponentType::RADIOBUTTON )
      52          39 :                 bIs = true;
      53             :         }
      54         688 :         return bIs;
      55             :     }
      56             : }
      57             : 
      58             : // class OGroupCompAcc
      59        2626 : OGroupCompAcc::OGroupCompAcc(const Reference<XPropertySet>& rxElement, const OGroupComp& _rGroupComp )
      60             :                :m_xComponent( rxElement )
      61        2626 :                ,m_aGroupComp( _rGroupComp )
      62             : {
      63        2626 : }
      64             : 
      65        1234 : sal_Bool OGroupCompAcc::operator==( const OGroupCompAcc& rCompAcc ) const
      66             : {
      67        1234 :     return (m_xComponent == rCompAcc.GetComponent());
      68             : }
      69             : 
      70             : class OGroupCompAccLess : public ::std::binary_function<OGroupCompAcc, OGroupCompAcc, sal_Bool>
      71             : {
      72             : public:
      73        2217 :     sal_Bool operator() (const OGroupCompAcc& lhs, const OGroupCompAcc& rhs) const
      74             :     {
      75             :         return
      76        2217 :             reinterpret_cast<sal_Int64>(lhs.m_xComponent.get())
      77        2217 :         <   reinterpret_cast<sal_Int64>(rhs.m_xComponent.get());
      78             :     }
      79             : };
      80             : 
      81             : // class OGroupComp
      82        1234 : OGroupComp::OGroupComp()
      83             :     :m_nPos( -1 )
      84        1234 :     ,m_nTabIndex( 0 )
      85             : {
      86        1234 : }
      87             : 
      88        6722 : 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        6722 :     ,m_nTabIndex( _rSource.m_nTabIndex )
      94             : {
      95        6722 : }
      96             : 
      97        1392 : 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        1392 :     , m_nTabIndex(0)
     103             : {
     104        1392 :     if (m_xComponent.is())
     105             :     {
     106        1392 :         if (hasProperty( PROPERTY_TABINDEX, m_xComponent ) )
     107             :             // Indices smaller than 0 are treated like 0
     108        1198 :             m_nTabIndex = std::max(getINT16(m_xComponent->getPropertyValue( PROPERTY_TABINDEX )) , sal_Int16(0));
     109             :     }
     110        1392 : }
     111             : 
     112        1234 : sal_Bool OGroupComp::operator==( const OGroupComp& rComp ) const
     113             : {
     114        1234 :     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        2212 :     sal_Bool operator() (const OGroupComp& lhs, const OGroupComp& rhs) const
     121             :     {
     122             :         sal_Bool bResult;
     123             :         // TabIndex von 0 wird hinten einsortiert
     124        2212 :         if (lhs.m_nTabIndex == rhs.GetTabIndex())
     125        1688 :             bResult = lhs.m_nPos < rhs.GetPos();
     126         524 :         else if (lhs.m_nTabIndex && rhs.GetTabIndex())
     127           2 :             bResult = lhs.m_nTabIndex < rhs.GetTabIndex();
     128             :         else
     129         522 :             bResult = lhs.m_nTabIndex != 0;
     130        2212 :         return bResult;
     131             :     }
     132             : };
     133             : 
     134             : // class OGroup
     135         655 : OGroup::OGroup( const OUString& rGroupName )
     136             :         :m_aGroupName( rGroupName )
     137         655 :         ,m_nInsertPos(0)
     138             : {
     139         655 : }
     140             : 
     141        1801 : OGroup::~OGroup()
     142             : {
     143        1801 : }
     144             : 
     145        1392 : void OGroup::InsertComponent( const Reference<XPropertySet>& xSet )
     146             : {
     147        1392 :     OGroupComp aNewGroupComp( xSet, m_nInsertPos );
     148        1392 :     sal_Int32 nPosInserted = insert_sorted(m_aCompArray, aNewGroupComp, OGroupCompLess());
     149             : 
     150        2784 :     OGroupCompAcc aNewGroupCompAcc( xSet, m_aCompArray[nPosInserted] );
     151        1392 :     insert_sorted(m_aCompAccArray, aNewGroupCompAcc, OGroupCompAccLess());
     152        2784 :     m_nInsertPos++;
     153        1392 : }
     154             : 
     155        1234 : void OGroup::RemoveComponent( const Reference<XPropertySet>& rxElement )
     156             : {
     157             :     sal_Int32 nGroupCompAccPos;
     158        1234 :     OGroupCompAcc aSearchCompAcc( rxElement, OGroupComp() );
     159        1234 :     if ( seek_entry(m_aCompAccArray, aSearchCompAcc, nGroupCompAccPos, OGroupCompAccLess()) )
     160             :     {
     161        1234 :         OGroupCompAcc& aGroupCompAcc = m_aCompAccArray[nGroupCompAccPos];
     162        1234 :         const OGroupComp& aGroupComp = aGroupCompAcc.GetGroupComponent();
     163             : 
     164             :         sal_Int32 nGroupCompPos;
     165        1234 :         if ( seek_entry(m_aCompArray, aGroupComp, nGroupCompPos, OGroupCompLess()) )
     166             :         {
     167        1234 :             m_aCompAccArray.erase( m_aCompAccArray.begin() + nGroupCompAccPos );
     168        1234 :             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        1234 :     }
     186        1234 : }
     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         239 : Sequence< Reference<XControlModel>  > OGroup::GetControlModels() const
     203             : {
     204         239 :     sal_Int32 nLen = m_aCompArray.size();
     205         239 :     Sequence<Reference<XControlModel> > aControlModelSeq( nLen );
     206         239 :     Reference<XControlModel>* pModels = aControlModelSeq.getArray();
     207             : 
     208         239 :     OGroupCompArr::const_iterator aGroupComps = m_aCompArray.begin();
     209         568 :     for (sal_Int32 i = 0; i < nLen; ++i, ++pModels, ++aGroupComps)
     210             :     {
     211         329 :         *pModels = aGroupComps->GetControlModel();
     212             :     }
     213         239 :     return aControlModelSeq;
     214             : }
     215             : 
     216         162 : OGroupManager::OGroupManager(const Reference< XContainer >& _rxContainer)
     217         162 :     :m_pCompGroup( new OGroup( OUString("AllComponentGroup") ) )
     218         324 :     ,m_xContainer(_rxContainer)
     219             : {
     220         162 :     increment(m_refCount);
     221             :     {
     222         162 :         _rxContainer->addContainerListener(this);
     223             :     }
     224         162 :     decrement(m_refCount);
     225         162 : }
     226             : 
     227         477 : OGroupManager::~OGroupManager()
     228             : {
     229             :     // delete all Components and CompGroup
     230         159 :     delete m_pCompGroup;
     231         318 : }
     232             : 
     233             : // XPropertyChangeListener
     234         326 : void OGroupManager::disposing(const EventObject& evt) throw( RuntimeException, std::exception )
     235             : {
     236         326 :     Reference<XContainer>  xContainer(evt.Source, UNO_QUERY);
     237         326 :     if (xContainer.get() == m_xContainer.get())
     238             :     {
     239         161 :         DELETEZ(m_pCompGroup);
     240             : 
     241             :         // delete group
     242         161 :         m_aGroupArr.clear();
     243         161 :         m_xContainer.clear();
     244         326 :     }
     245         326 : }
     246             : 
     247         617 : void OGroupManager::removeFromGroupMap(const OUString& _sGroupName,const Reference<XPropertySet>& _xSet)
     248             : {
     249             :     // remove Component from CompGroup
     250         617 :     m_pCompGroup->RemoveComponent( _xSet );
     251             : 
     252         617 :     OGroupArr::iterator aFind = m_aGroupArr.find(_sGroupName);
     253             : 
     254         617 :     if ( aFind != m_aGroupArr.end() )
     255             :     {
     256             :         // group exists
     257         617 :         aFind->second.RemoveComponent( _xSet );
     258             : 
     259             :         // Wenn Anzahl der Gruppenelemente == 1 ist, Gruppe deaktivieren
     260         617 :         sal_Int32 nCount = aFind->second.Count();
     261         617 :         if ( nCount == 1 || nCount == 0 )
     262             :         {
     263             :             OActiveGroups::iterator aActiveFind = ::std::find(
     264             :                 m_aActiveGroupMap.begin(),
     265             :                 m_aActiveGroupMap.end(),
     266             :                 aFind
     267         615 :             );
     268         615 :             if ( aActiveFind != m_aActiveGroupMap.end() )
     269             :             {
     270             :                 // the group is active. Deactivate it if the remaining component
     271             :                 // is *no* radio button
     272          33 :                 if ( nCount == 0 || !isRadioButton( aFind->second.GetObject( 0 ) ) )
     273          33 :                     m_aActiveGroupMap.erase( aActiveFind );
     274             :             }
     275             :         }
     276             :     }
     277             : 
     278             : 
     279             :     // Bei Component als PropertyChangeListener abmelden
     280         617 :     _xSet->removePropertyChangeListener( PROPERTY_NAME, this );
     281         617 :     if (hasProperty(PROPERTY_GROUP_NAME, _xSet))
     282          32 :         _xSet->removePropertyChangeListener( PROPERTY_GROUP_NAME, this );
     283         617 :     if (hasProperty(PROPERTY_TABINDEX, _xSet))
     284         524 :         _xSet->removePropertyChangeListener( PROPERTY_TABINDEX, this );
     285         617 : }
     286             : 
     287         405 : void SAL_CALL OGroupManager::propertyChange(const PropertyChangeEvent& evt) throw ( ::com::sun::star::uno::RuntimeException, std::exception)
     288             : {
     289         405 :     Reference<XPropertySet>  xSet(evt.Source, UNO_QUERY);
     290             : 
     291             :     // remove Component from group
     292         800 :     OUString     sGroupName;
     293         405 :     if (hasProperty( PROPERTY_GROUP_NAME, xSet ))
     294          36 :         xSet->getPropertyValue( PROPERTY_GROUP_NAME ) >>= sGroupName;
     295         405 :     if (evt.PropertyName == PROPERTY_NAME) {
     296         223 :         if (!sGroupName.isEmpty())
     297         415 :             return; // group hasn't changed; ignore this name change.
     298             :         // no GroupName; use Name as GroupNme
     299         213 :         evt.OldValue >>= sGroupName;
     300             :     }
     301         182 :     else if (evt.PropertyName == PROPERTY_GROUP_NAME) {
     302          10 :         evt.OldValue >>= sGroupName;
     303          10 :         if (sGroupName.isEmpty()) {
     304             :             // No prior GroupName; fallback to Nme
     305           3 :             xSet->getPropertyValue( PROPERTY_NAME ) >>= sGroupName;
     306             :         }
     307             :     }
     308             :     else
     309         172 :         sGroupName = GetGroupName( xSet );
     310             : 
     311         395 :     removeFromGroupMap(sGroupName,xSet);
     312             : 
     313             :     // Component neu einordnen
     314         790 :     InsertElement( xSet );
     315             : }
     316             : 
     317             : // XContainerListener
     318         305 : void SAL_CALL OGroupManager::elementInserted(const ContainerEvent& Event) throw ( ::com::sun::star::uno::RuntimeException, std::exception)
     319             : {
     320         305 :     Reference< XPropertySet > xProps;
     321         305 :     Event.Element >>= xProps;
     322         305 :     if ( xProps.is() )
     323         305 :         InsertElement( xProps );
     324         305 : }
     325             : 
     326         222 : void SAL_CALL OGroupManager::elementRemoved(const ContainerEvent& Event) throw ( ::com::sun::star::uno::RuntimeException, std::exception)
     327             : {
     328         222 :     Reference<XPropertySet> xProps;
     329         222 :     Event.Element >>= xProps;
     330         222 :     if ( xProps.is() )
     331         222 :         RemoveElement( xProps );
     332         222 : }
     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         231 : Sequence<Reference<XControlModel> > OGroupManager::getControlModels()
     349             : {
     350         231 :     return m_pCompGroup->GetControlModels();
     351             : }
     352             : 
     353         132 : sal_Int32 OGroupManager::getGroupCount()
     354             : {
     355         132 :     return m_aActiveGroupMap.size();
     356             : }
     357             : 
     358           8 : 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           8 :     OGroupArr::iterator aGroupPos   = m_aActiveGroupMap[nGroup];
     362           8 :     _rName                          = aGroupPos->second.GetGroupName();
     363           8 :     _rGroup                         = aGroupPos->second.GetControlModels();
     364           8 : }
     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         700 : void OGroupManager::InsertElement( const Reference<XPropertySet>& xSet )
     374             : {
     375             :     // Nur ControlModels
     376         700 :     Reference<XControlModel>  xControl(xSet, UNO_QUERY);
     377         700 :     if (!xControl.is() )
     378         704 :         return;
     379             : 
     380             :     // Component in CompGroup aufnehmen
     381         696 :     m_pCompGroup->InsertComponent( xSet );
     382             : 
     383             :     // Component in Gruppe aufnehmen
     384        1392 :     OUString sGroupName( GetGroupName( xSet ) );
     385             : 
     386         696 :     OGroupArr::iterator aFind = m_aGroupArr.find(sGroupName);
     387             : 
     388         696 :     if ( aFind == m_aGroupArr.end() )
     389             :     {
     390         493 :         aFind = m_aGroupArr.insert(OGroupArr::value_type(sGroupName,OGroup(sGroupName))).first;
     391             :     }
     392             : 
     393         696 :     aFind->second.InsertComponent( xSet );
     394             : 
     395             :     // if we have at least 2 elements in the group, then this is an "active group"
     396         696 :     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         696 :     if ( aFind->second.Count() == 1 )
     403             :     {
     404         687 :         if ( isRadioButton( xSet ) )
     405          39 :             bActivateGroup = true;
     406             :     }
     407             : 
     408         696 :     if ( bActivateGroup )
     409             :     {
     410             :         OActiveGroups::iterator aAlreadyExistent = ::std::find(
     411             :             m_aActiveGroupMap.begin(),
     412             :             m_aActiveGroupMap.end(),
     413             :             aFind
     414          42 :         );
     415          42 :         if ( aAlreadyExistent == m_aActiveGroupMap.end() )
     416          42 :             m_aActiveGroupMap.push_back(  aFind );
     417             :     }
     418             : 
     419             :     // Bei Component als PropertyChangeListener anmelden
     420         696 :     xSet->addPropertyChangeListener( PROPERTY_NAME, this );
     421         696 :     if (hasProperty(PROPERTY_GROUP_NAME, xSet))
     422          43 :         xSet->addPropertyChangeListener( PROPERTY_GROUP_NAME, this );
     423             : 
     424             :     // Tabindex muss nicht jeder unterstuetzen
     425         696 :     if (hasProperty(PROPERTY_TABINDEX, xSet))
     426        1295 :         xSet->addPropertyChangeListener( PROPERTY_TABINDEX, this );
     427             : }
     428             : 
     429         222 : void OGroupManager::RemoveElement( const Reference<XPropertySet>& xSet )
     430             : {
     431             :     // Nur ControlModels
     432         222 :     Reference<XControlModel>  xControl(xSet, UNO_QUERY);
     433         222 :     if (!xControl.is() )
     434         222 :         return;
     435             : 
     436             :     // Component aus Gruppe entfernen
     437         444 :     OUString     sGroupName( GetGroupName( xSet ) );
     438             : 
     439         444 :     removeFromGroupMap(sGroupName,xSet);
     440             : }
     441             : 
     442        2482 : OUString OGroupManager::GetGroupName( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet> xComponent )
     443             : {
     444        2482 :     if (!xComponent.is())
     445           0 :         return OUString();
     446        2482 :     OUString sGroupName;
     447        2482 :     if (hasProperty( PROPERTY_GROUP_NAME, xComponent )) {
     448         147 :         xComponent->getPropertyValue( PROPERTY_GROUP_NAME ) >>= sGroupName;
     449         147 :         if (sGroupName.isEmpty())
     450          74 :             xComponent->getPropertyValue( PROPERTY_NAME ) >>= sGroupName;
     451             :     }
     452             :     else
     453        2335 :         xComponent->getPropertyValue( PROPERTY_NAME ) >>= sGroupName;
     454        2482 :     return sGroupName;
     455             : }
     456             : }   // namespace frm
     457             : 
     458             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10