549 lines
18 KiB
C++
549 lines
18 KiB
C++
/*************************************************************************
|
|
*
|
|
* $RCSfile: GroupManager.cxx,v $
|
|
*
|
|
* $Revision: 1.14 $
|
|
*
|
|
* last change: $Author: vg $ $Date: 2005-02-16 17:50:36 $
|
|
*
|
|
* The Contents of this file are made available subject to the terms of
|
|
* either of the following licenses
|
|
*
|
|
* - GNU Lesser General Public License Version 2.1
|
|
* - Sun Industry Standards Source License Version 1.1
|
|
*
|
|
* Sun Microsystems Inc., October, 2000
|
|
*
|
|
* GNU Lesser General Public License Version 2.1
|
|
* =============================================
|
|
* Copyright 2000 by Sun Microsystems, Inc.
|
|
* 901 San Antonio Road, Palo Alto, CA 94303, USA
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License version 2.1, as published by the Free Software Foundation.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
* MA 02111-1307 USA
|
|
*
|
|
*
|
|
* Sun Industry Standards Source License Version 1.1
|
|
* =================================================
|
|
* The contents of this file are subject to the Sun Industry Standards
|
|
* Source License Version 1.1 (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.openoffice.org/license.html.
|
|
*
|
|
* Software provided under this License is provided on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
|
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
|
|
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
|
|
* See the License for the specific provisions governing your rights and
|
|
* obligations concerning the Software.
|
|
*
|
|
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
|
|
*
|
|
* Copyright: 2000 by Sun Microsystems, Inc.
|
|
*
|
|
* All Rights Reserved.
|
|
*
|
|
* Contributor(s): _______________________________________
|
|
*
|
|
*
|
|
************************************************************************/
|
|
|
|
#ifndef _FRM_GROUPMANAGER_HXX_
|
|
#include "GroupManager.hxx"
|
|
#endif
|
|
|
|
#ifndef _COM_SUN_STAR_BEANS_XFASTPROPERTYSET_HPP_
|
|
#include <com/sun/star/beans/XFastPropertySet.hpp>
|
|
#endif
|
|
#ifndef _COM_SUN_STAR_FORM_FORMCOMPONENTTYPE_HPP_
|
|
#include <com/sun/star/form/FormComponentType.hpp>
|
|
#endif
|
|
|
|
#ifndef _COMPHELPER_PROPERTY_HXX_
|
|
#include <comphelper/property.hxx>
|
|
#endif
|
|
#ifndef _COMPHELPER_UNO3_HXX_
|
|
#include <comphelper/uno3.hxx>
|
|
#endif
|
|
|
|
#ifndef _SOLAR_H
|
|
#include <tools/solar.h>
|
|
#endif
|
|
#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_nTabIndex( 0 )
|
|
,m_nPos( -1 )
|
|
{
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
OGroupComp::OGroupComp(const OGroupComp& _rSource)
|
|
:m_aName( _rSource.m_aName )
|
|
,m_xComponent( _rSource.m_xComponent )
|
|
,m_nTabIndex( _rSource.m_nTabIndex )
|
|
,m_nPos( _rSource.m_nPos )
|
|
,m_xControlModel(_rSource.m_xControlModel)
|
|
{
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
OGroupComp::OGroupComp(const Reference<XPropertySet>& rxSet, sal_Int32 nInsertPos )
|
|
:m_xComponent( rxSet )
|
|
,m_nTabIndex(0)
|
|
,m_nPos( nInsertPos )
|
|
,m_xControlModel(rxSet,UNO_QUERY)
|
|
{
|
|
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_aGroupName(_rSource.m_aGroupName)
|
|
,m_nInsertPos(_rSource.m_nInsertPos)
|
|
,m_aCompArray(_rSource.m_aCompArray)
|
|
,m_aCompAccArray(_rSource.m_aCompAccArray)
|
|
{
|
|
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
|
|
//.........................................................................
|
|
|