summaryrefslogtreecommitdiffstats
path: root/toolkit/source/controls
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--toolkit/source/controls/accessiblecontrolcontext.cxx358
-rw-r--r--toolkit/source/controls/animatedimages.cxx491
-rw-r--r--toolkit/source/controls/controlmodelcontainerbase.cxx1820
-rw-r--r--toolkit/source/controls/controlmodelcontainerbase_internal.hxx30
-rw-r--r--toolkit/source/controls/dialogcontrol.cxx1244
-rw-r--r--toolkit/source/controls/eventcontainer.cxx179
-rw-r--r--toolkit/source/controls/filectrl.cxx244
-rw-r--r--toolkit/source/controls/formattedcontrol.cxx476
-rw-r--r--toolkit/source/controls/geometrycontrolmodel.cxx608
-rw-r--r--toolkit/source/controls/grid/defaultgridcolumnmodel.cxx389
-rw-r--r--toolkit/source/controls/grid/defaultgriddatamodel.cxx505
-rw-r--r--toolkit/source/controls/grid/gridcolumn.cxx300
-rw-r--r--toolkit/source/controls/grid/gridcolumn.hxx128
-rw-r--r--toolkit/source/controls/grid/gridcontrol.cxx460
-rw-r--r--toolkit/source/controls/grid/gridcontrol.hxx142
-rw-r--r--toolkit/source/controls/grid/grideventforwarder.cxx128
-rw-r--r--toolkit/source/controls/grid/grideventforwarder.hxx77
-rw-r--r--toolkit/source/controls/grid/sortablegriddatamodel.cxx928
-rw-r--r--toolkit/source/controls/roadmapcontrol.cxx513
-rw-r--r--toolkit/source/controls/roadmapentry.cxx105
-rw-r--r--toolkit/source/controls/spinningprogress.cxx132
-rw-r--r--toolkit/source/controls/stdtabcontroller.cxx415
-rw-r--r--toolkit/source/controls/stdtabcontrollermodel.cxx439
-rw-r--r--toolkit/source/controls/svmedit.cxx43
-rw-r--r--toolkit/source/controls/tabpagecontainer.cxx351
-rw-r--r--toolkit/source/controls/tabpagemodel.cxx304
-rw-r--r--toolkit/source/controls/tkscrollbar.cxx324
-rw-r--r--toolkit/source/controls/tkspinbutton.cxx421
-rw-r--r--toolkit/source/controls/tree/treecontrol.cxx514
-rw-r--r--toolkit/source/controls/tree/treecontrol.hxx65
-rw-r--r--toolkit/source/controls/tree/treecontrolpeer.cxx1579
-rw-r--r--toolkit/source/controls/tree/treedatamodel.cxx523
-rw-r--r--toolkit/source/controls/unocontrol.cxx1565
-rw-r--r--toolkit/source/controls/unocontrolbase.cxx253
-rw-r--r--toolkit/source/controls/unocontrolcontainer.cxx822
-rw-r--r--toolkit/source/controls/unocontrolcontainermodel.cxx93
-rw-r--r--toolkit/source/controls/unocontrolmodel.cxx1388
-rw-r--r--toolkit/source/controls/unocontrols.cxx4760
38 files changed, 23116 insertions, 0 deletions
diff --git a/toolkit/source/controls/accessiblecontrolcontext.cxx b/toolkit/source/controls/accessiblecontrolcontext.cxx
new file mode 100644
index 000000000..219b4a610
--- /dev/null
+++ b/toolkit/source/controls/accessiblecontrolcontext.cxx
@@ -0,0 +1,358 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <controls/accessiblecontrolcontext.hxx>
+#include <unotools/accessiblestatesethelper.hxx>
+#include <com/sun/star/awt/XControl.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <vcl/svapp.hxx>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <tools/diagnose_ex.h>
+#include <vcl/window.hxx>
+
+
+namespace toolkit
+{
+
+
+ using ::comphelper::OContextEntryGuard;
+ using namespace ::com::sun::star;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::accessibility;
+
+
+ //= OAccessibleControlContext
+
+
+ OAccessibleControlContext::OAccessibleControlContext()
+ {
+ // nothing to do here, we have a late ctor
+ }
+
+
+ OAccessibleControlContext::~OAccessibleControlContext()
+ {
+ ensureDisposed();
+ }
+
+
+ // (order matters: the first is the class name, the second is the class doing the ref counting)
+ IMPLEMENT_FORWARD_XINTERFACE3( OAccessibleControlContext, OAccessibleControlContext_Base, OAccessibleImplementationAccess, OAccessibleControlContext_IBase )
+ css::uno::Sequence< css::uno::Type > SAL_CALL OAccessibleControlContext::getTypes()
+ {
+ return ::comphelper::concatSequences(
+ OAccessibleControlContext_Base::getTypes(),
+ OAccessibleImplementationAccess::getTypes(),
+ OAccessibleControlContext_IBase::getTypes()
+ );
+ }
+ IMPLEMENT_GET_IMPLEMENTATION_ID( OAccessibleControlContext )
+
+
+ void OAccessibleControlContext::Init( const Reference< XAccessible >& _rxCreator )
+ {
+ OContextEntryGuard aGuard( this );
+
+ // retrieve the model of the control
+ OSL_ENSURE( !m_xControlModel.is(), "OAccessibleControlContext::Init: already know a control model...!???" );
+
+ Reference< awt::XControl > xControl( _rxCreator, UNO_QUERY );
+ if ( xControl.is() )
+ m_xControlModel.set(xControl->getModel(), css::uno::UNO_QUERY);
+ OSL_ENSURE( m_xControlModel.is(), "OAccessibleControlContext::Init: invalid creator (no control, or control without model!" );
+ if ( !m_xControlModel.is() )
+ throw DisposedException(); // caught by the caller (the create method)
+
+ // start listening at the model
+ startModelListening();
+
+ // announce the XAccessible to our base class
+ OAccessibleControlContext_Base::lateInit( _rxCreator );
+ }
+
+
+ rtl::Reference<OAccessibleControlContext> OAccessibleControlContext::create( const Reference< XAccessible >& _rxCreator )
+ {
+ rtl::Reference<OAccessibleControlContext> pNew;
+ try
+ {
+ pNew = new OAccessibleControlContext;
+ pNew->Init( _rxCreator );
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "toolkit", "OAccessibleControlContext::create: caught an exception from the late ctor!" );
+ }
+ return pNew;
+ }
+
+
+ void OAccessibleControlContext::startModelListening( )
+ {
+ Reference< XComponent > xModelComp( m_xControlModel, UNO_QUERY );
+ OSL_ENSURE( xModelComp.is(), "OAccessibleControlContext::startModelListening: invalid model!" );
+ if ( xModelComp.is() )
+ xModelComp->addEventListener( this );
+ }
+
+
+ void OAccessibleControlContext::stopModelListening( )
+ {
+ Reference< XComponent > xModelComp( m_xControlModel, UNO_QUERY );
+ OSL_ENSURE( xModelComp.is(), "OAccessibleControlContext::stopModelListening: invalid model!" );
+ if ( xModelComp.is() )
+ xModelComp->removeEventListener( this );
+ }
+
+
+ sal_Int32 SAL_CALL OAccessibleControlContext::getAccessibleChildCount( )
+ {
+ // we do not have children
+ return 0;
+ }
+
+
+ Reference< XAccessible > SAL_CALL OAccessibleControlContext::getAccessibleChild( sal_Int32 )
+ {
+ // we do not have children
+ throw IndexOutOfBoundsException();
+ }
+
+
+ Reference< XAccessible > SAL_CALL OAccessibleControlContext::getAccessibleParent( )
+ {
+ return Reference< XAccessible >();
+ }
+
+
+ sal_Int16 SAL_CALL OAccessibleControlContext::getAccessibleRole( )
+ {
+ return AccessibleRole::SHAPE;
+ }
+
+
+ OUString SAL_CALL OAccessibleControlContext::getAccessibleDescription( )
+ {
+ OContextEntryGuard aGuard( this );
+ return getModelStringProperty( "HelpText" );
+ }
+
+
+ OUString SAL_CALL OAccessibleControlContext::getAccessibleName( )
+ {
+ OContextEntryGuard aGuard( this );
+ return getModelStringProperty( "Name" );
+ }
+
+
+ Reference< XAccessibleRelationSet > SAL_CALL OAccessibleControlContext::getAccessibleRelationSet( )
+ {
+ return nullptr;
+ }
+
+
+ Reference< XAccessibleStateSet > SAL_CALL OAccessibleControlContext::getAccessibleStateSet( )
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ // no OContextEntryGuard here, as we do not want to throw an exception in case we're not alive anymore
+
+ rtl::Reference<::utl::AccessibleStateSetHelper> pStateSet;
+ if ( isAlive() )
+ {
+ // no own states, only the ones which are foreign controlled
+ pStateSet = new ::utl::AccessibleStateSetHelper( 0 );
+ }
+ else
+ { // only the DEFUNC state if we're already disposed
+ pStateSet = new ::utl::AccessibleStateSetHelper;
+ pStateSet->AddState( AccessibleStateType::DEFUNC );
+ }
+ return pStateSet;
+ }
+
+
+ void SAL_CALL OAccessibleControlContext::disposing( const EventObject& _rSource )
+ {
+ OSL_ENSURE( Reference< XPropertySet >( _rSource.Source, UNO_QUERY ).get() == m_xControlModel.get(),
+ "OAccessibleControlContext::disposing: where did this come from?" );
+
+ stopModelListening( );
+ m_xControlModel.clear();
+ m_xModelPropsInfo.clear();
+
+ OAccessibleControlContext_Base::disposing();
+ }
+
+
+ OUString OAccessibleControlContext::getModelStringProperty( const char* _pPropertyName )
+ {
+ OUString sReturn;
+ try
+ {
+ if ( !m_xModelPropsInfo.is() && m_xControlModel.is() )
+ m_xModelPropsInfo = m_xControlModel->getPropertySetInfo();
+
+ OUString sPropertyName( OUString::createFromAscii( _pPropertyName ) );
+ if ( m_xModelPropsInfo.is() && m_xModelPropsInfo->hasPropertyByName( sPropertyName ) )
+ m_xControlModel->getPropertyValue( sPropertyName ) >>= sReturn;
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "toolkit", "OAccessibleControlContext::getModelStringProperty" );
+ }
+ return sReturn;
+ }
+
+
+ vcl::Window* OAccessibleControlContext::implGetWindow( Reference< awt::XWindow >* _pxUNOWindow ) const
+ {
+ Reference< awt::XControl > xControl( getAccessibleCreator(), UNO_QUERY );
+ Reference< awt::XWindow > xWindow;
+ if ( xControl.is() )
+ xWindow.set(xControl->getPeer(), css::uno::UNO_QUERY);
+
+ vcl::Window* pWindow = xWindow.is() ? VCLUnoHelper::GetWindow( xWindow ) : nullptr;
+
+ if ( _pxUNOWindow )
+ *_pxUNOWindow = xWindow;
+
+ return pWindow;
+ }
+
+
+ awt::Rectangle OAccessibleControlContext::implGetBounds( )
+ {
+ SolarMutexGuard aSolarGuard;
+ // want to do some VCL stuff here ...
+ OContextEntryGuard aGuard( this );
+
+ OSL_FAIL( "OAccessibleControlContext::implGetBounds: performance issue: forced to calc the size myself!" );
+ // In design mode (and this is what this class is for), the surrounding shape (if any) should handle this call
+ // The problem is that in design mode, our size may not be correct (in the drawing layer, controls are
+ // positioned/sized for painting only), and that calculation of our position is expensive
+
+ // what we know (or can obtain from somewhere):
+ // * the PosSize of our peer, relative to its parent window
+ // * the parent window which the PosSize is relative to
+ // * our foreign controlled accessible parent
+ // from this info, we can determine the position of our peer relative to the foreign parent
+
+ // our control
+ Reference< awt::XWindow > xWindow;
+ VclPtr< vcl::Window > pVCLWindow = implGetWindow( &xWindow );
+
+ awt::Rectangle aBounds( 0, 0, 0, 0 );
+ if ( xWindow.is() )
+ {
+ // ugly, but... though the XWindow has a getPosSize, it is impossible to determine the
+ // parent which this position/size is relative to. This means we must tunnel UNO and ask the
+ // implementation
+ vcl::Window* pVCLParent = pVCLWindow ? pVCLWindow->GetParent() : nullptr;
+
+ // the relative location of the window
+ ::Point aWindowRelativePos( 0, 0);
+ if ( pVCLWindow )
+ aWindowRelativePos = pVCLWindow->GetPosPixel();
+
+ // the screen position of the "window parent" of the control
+ ::Point aVCLParentScreenPos( 0, 0 );
+ if ( pVCLParent )
+ aVCLParentScreenPos = pVCLParent->GetPosPixel();
+
+ // now the size of the control
+ aBounds = xWindow->getPosSize();
+
+ // correct the pos
+ aBounds.X = aWindowRelativePos.X() + aVCLParentScreenPos.X();
+ aBounds.Y = aWindowRelativePos.Y() + aVCLParentScreenPos.Y();
+ }
+
+ return aBounds;
+ }
+
+
+ Reference< XAccessible > SAL_CALL OAccessibleControlContext::getAccessibleAtPoint( const awt::Point& /* _rPoint */ )
+ {
+ // no children at all
+ return nullptr;
+ }
+
+
+ void SAL_CALL OAccessibleControlContext::grabFocus( )
+ {
+ OSL_FAIL( "OAccessibleControlContext::grabFocus: !isFocusTraversable, but grabFocus!" );
+ }
+
+
+ sal_Int32 SAL_CALL OAccessibleControlContext::getForeground( )
+ {
+ SolarMutexGuard aSolarGuard;
+ // want to do some VCL stuff here ...
+ OContextEntryGuard aGuard( this );
+
+ VclPtr< vcl::Window > pWindow = implGetWindow();
+ Color nColor;
+ if ( pWindow )
+ {
+ if ( pWindow->IsControlForeground() )
+ nColor = pWindow->GetControlForeground();
+ else
+ {
+ vcl::Font aFont;
+ if ( pWindow->IsControlFont() )
+ aFont = pWindow->GetControlFont();
+ else
+ aFont = pWindow->GetFont();
+ nColor = aFont.GetColor();
+ }
+ }
+ return sal_Int32(nColor);
+ }
+
+
+ sal_Int32 SAL_CALL OAccessibleControlContext::getBackground( )
+ {
+ SolarMutexGuard aSolarGuard;
+ // want to do some VCL stuff here ...
+ OContextEntryGuard aGuard( this );
+
+ VclPtr< vcl::Window > pWindow = implGetWindow();
+ Color nColor;
+ if ( pWindow )
+ {
+ if ( pWindow->IsControlBackground() )
+ nColor = pWindow->GetControlBackground();
+ else
+ nColor = pWindow->GetBackground().GetColor();
+ }
+
+ return sal_Int32(nColor);
+ }
+
+
+} //namespace toolkit
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/animatedimages.cxx b/toolkit/source/controls/animatedimages.cxx
new file mode 100644
index 000000000..99fd5df85
--- /dev/null
+++ b/toolkit/source/controls/animatedimages.cxx
@@ -0,0 +1,491 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <controls/animatedimages.hxx>
+#include <toolkit/helper/property.hxx>
+
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/awt/VisualEffect.hpp>
+#include <com/sun/star/awt/ImageScaleMode.hpp>
+#include <com/sun/star/awt/XAnimation.hpp>
+#include <com/sun/star/awt/XAnimatedImages.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/container/XContainerListener.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/util/XModifyListener.hpp>
+#include <o3tl/safeint.hxx>
+#include <toolkit/controls/unocontrolbase.hxx>
+#include <toolkit/controls/unocontrolmodel.hxx>
+
+#include <cppuhelper/implbase2.hxx>
+
+#include <helper/unopropertyarrayhelper.hxx>
+
+using namespace css::awt;
+using namespace css::container;
+using namespace css::lang;
+using namespace css::uno;
+
+namespace {
+
+typedef ::cppu::AggImplInheritanceHelper2 < UnoControlBase
+ , css::awt::XAnimation
+ , css::container::XContainerListener
+ > AnimatedImagesControl_Base;
+
+class AnimatedImagesControl : public AnimatedImagesControl_Base
+{
+public:
+ AnimatedImagesControl();
+ OUString GetComponentServiceName() const override;
+
+ // XAnimation
+ virtual void SAL_CALL startAnimation( ) override;
+ virtual void SAL_CALL stopAnimation( ) override;
+ virtual sal_Bool SAL_CALL isAnimationRunning( ) override;
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName( ) override;
+ css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // XControl
+ sal_Bool SAL_CALL setModel( const css::uno::Reference< css::awt::XControlModel >& i_rModel ) override;
+ void SAL_CALL createPeer( const css::uno::Reference< css::awt::XToolkit >& i_toolkit, const css::uno::Reference< css::awt::XWindowPeer >& i_parentPeer ) override;
+
+
+ // XContainerListener
+ virtual void SAL_CALL elementInserted( const css::container::ContainerEvent& Event ) override;
+ virtual void SAL_CALL elementRemoved( const css::container::ContainerEvent& Event ) override;
+ virtual void SAL_CALL elementReplaced( const css::container::ContainerEvent& Event ) override;
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& i_event ) override;
+};
+
+ AnimatedImagesControl::AnimatedImagesControl()
+ {
+ }
+
+
+ OUString AnimatedImagesControl::GetComponentServiceName() const
+ {
+ return "AnimatedImages";
+ }
+
+
+ void SAL_CALL AnimatedImagesControl::startAnimation( )
+ {
+ Reference< XAnimation > xAnimation( getPeer(), UNO_QUERY );
+ if ( xAnimation.is() )
+ xAnimation->startAnimation();
+ }
+
+
+ void SAL_CALL AnimatedImagesControl::stopAnimation( )
+ {
+ Reference< XAnimation > xAnimation( getPeer(), UNO_QUERY );
+ if ( xAnimation.is() )
+ xAnimation->stopAnimation();
+ }
+
+
+ sal_Bool SAL_CALL AnimatedImagesControl::isAnimationRunning( )
+ {
+ Reference< XAnimation > xAnimation( getPeer(), UNO_QUERY );
+ if ( xAnimation.is() )
+ return xAnimation->isAnimationRunning();
+ return false;
+ }
+
+
+ OUString SAL_CALL AnimatedImagesControl::getImplementationName( )
+ {
+ return "org.openoffice.comp.toolkit.AnimatedImagesControl";
+ }
+
+
+ Sequence< OUString > SAL_CALL AnimatedImagesControl::getSupportedServiceNames()
+ {
+ Sequence< OUString > aServices( AnimatedImagesControl_Base::getSupportedServiceNames() );
+ aServices.realloc( aServices.getLength() + 1 );
+ aServices.getArray()[ aServices.getLength() - 1 ] = "com.sun.star.awt.AnimatedImagesControl";
+ return aServices;
+ }
+
+ void lcl_updatePeer( Reference< XWindowPeer > const& i_peer, Reference< XControlModel > const& i_model )
+ {
+ const Reference< css::util::XModifyListener > xPeerModify( i_peer, UNO_QUERY );
+ if ( xPeerModify.is() )
+ {
+ EventObject aEvent;
+ aEvent.Source = i_model;
+ xPeerModify->modified( aEvent );
+ }
+ }
+
+ sal_Bool SAL_CALL AnimatedImagesControl::setModel( const Reference< XControlModel >& i_rModel )
+ {
+ const Reference< XAnimatedImages > xOldContainer( getModel(), UNO_QUERY );
+ const Reference< XAnimatedImages > xNewContainer( i_rModel, UNO_QUERY );
+
+ if ( !AnimatedImagesControl_Base::setModel( i_rModel ) )
+ return false;
+
+ if ( xOldContainer.is() )
+ xOldContainer->removeContainerListener( this );
+
+ if ( xNewContainer.is() )
+ xNewContainer->addContainerListener( this );
+
+ lcl_updatePeer( getPeer(), getModel() );
+
+ return true;
+ }
+
+
+ void SAL_CALL AnimatedImagesControl::createPeer( const Reference< XToolkit >& i_toolkit, const Reference< XWindowPeer >& i_parentPeer )
+ {
+ AnimatedImagesControl_Base::createPeer( i_toolkit, i_parentPeer );
+
+ lcl_updatePeer( getPeer(), getModel() );
+ }
+
+
+ void SAL_CALL AnimatedImagesControl::elementInserted( const ContainerEvent& i_event )
+ {
+ const Reference< XContainerListener > xPeerListener( getPeer(), UNO_QUERY );
+ if ( xPeerListener.is() )
+ xPeerListener->elementInserted( i_event );
+ }
+
+
+ void SAL_CALL AnimatedImagesControl::elementRemoved( const ContainerEvent& i_event )
+ {
+ const Reference< XContainerListener > xPeerListener( getPeer(), UNO_QUERY );
+ if ( xPeerListener.is() )
+ xPeerListener->elementRemoved( i_event );
+ }
+
+
+ void SAL_CALL AnimatedImagesControl::elementReplaced( const ContainerEvent& i_event )
+ {
+ const Reference< XContainerListener > xPeerListener( getPeer(), UNO_QUERY );
+ if ( xPeerListener.is() )
+ xPeerListener->elementReplaced( i_event );
+ }
+
+
+ void SAL_CALL AnimatedImagesControl::disposing( const EventObject& i_event )
+ {
+ UnoControlBase::disposing( i_event );
+ }
+
+}
+
+namespace toolkit {
+
+ namespace
+ {
+ void lcl_checkIndex( const std::vector< css::uno::Sequence< OUString > > & rImageSets, const sal_Int32 i_index, const Reference< XInterface >& i_context,
+ const bool i_forInsert = false )
+ {
+ if ( ( i_index < 0 ) || ( o3tl::make_unsigned( i_index ) > rImageSets.size() + ( i_forInsert ? 1 : 0 ) ) )
+ throw IndexOutOfBoundsException( OUString(), i_context );
+ }
+
+ void lcl_notify( ::osl::ClearableMutexGuard& i_guard, ::cppu::OBroadcastHelper const & i_broadcaseHelper,
+ void ( SAL_CALL XContainerListener::*i_notificationMethod )( const ContainerEvent& ),
+ const sal_Int32 i_accessor, const Sequence< OUString >& i_imageURLs, const Reference< XInterface >& i_context )
+ {
+ ::cppu::OInterfaceContainerHelper* pContainerListeners = i_broadcaseHelper.getContainer( cppu::UnoType<XContainerListener>::get() );
+ if ( pContainerListeners == nullptr )
+ return;
+
+ ContainerEvent aEvent;
+ aEvent.Source = i_context;
+ aEvent.Accessor <<= i_accessor;
+ aEvent.Element <<= i_imageURLs;
+
+ i_guard.clear();
+ pContainerListeners->notifyEach( i_notificationMethod, aEvent );
+ }
+ }
+
+
+ AnimatedImagesControlModel::AnimatedImagesControlModel( Reference< css::uno::XComponentContext > const & i_factory )
+ :AnimatedImagesControlModel_Base( i_factory )
+ {
+ ImplRegisterProperty( BASEPROPERTY_AUTO_REPEAT );
+ ImplRegisterProperty( BASEPROPERTY_BORDER );
+ ImplRegisterProperty( BASEPROPERTY_BORDERCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
+ ImplRegisterProperty( BASEPROPERTY_ENABLEVISIBLE );
+ ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
+ ImplRegisterProperty( BASEPROPERTY_HELPURL );
+ ImplRegisterProperty( BASEPROPERTY_IMAGE_SCALE_MODE );
+ ImplRegisterProperty( BASEPROPERTY_STEP_TIME );
+ }
+
+
+ AnimatedImagesControlModel::AnimatedImagesControlModel( const AnimatedImagesControlModel& i_copySource )
+ :AnimatedImagesControlModel_Base( i_copySource )
+ ,maImageSets( i_copySource.maImageSets )
+ {
+ }
+
+
+ AnimatedImagesControlModel::~AnimatedImagesControlModel()
+ {
+ }
+
+
+ rtl::Reference<UnoControlModel> AnimatedImagesControlModel::Clone() const
+ {
+ return new AnimatedImagesControlModel( *this );
+ }
+
+
+ Reference< css::beans::XPropertySetInfo > SAL_CALL AnimatedImagesControlModel::getPropertySetInfo( )
+ {
+ static Reference< css::beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+ }
+
+
+ OUString SAL_CALL AnimatedImagesControlModel::getServiceName()
+ {
+ return "com.sun.star.awt.AnimatedImagesControlModel";
+ }
+
+
+ OUString SAL_CALL AnimatedImagesControlModel::getImplementationName( )
+ {
+ return "org.openoffice.comp.toolkit.AnimatedImagesControlModel";
+ }
+
+
+ Sequence< OUString > SAL_CALL AnimatedImagesControlModel::getSupportedServiceNames()
+ {
+ return { "com.sun.star.awt.AnimatedImagesControlModel", "com.sun.star.awt.UnoControlModel" };
+ }
+
+
+ void SAL_CALL AnimatedImagesControlModel::setFastPropertyValue_NoBroadcast( sal_Int32 i_handle, const Any& i_value )
+ {
+ switch ( i_handle )
+ {
+ case BASEPROPERTY_IMAGE_SCALE_MODE:
+ {
+ sal_Int16 nImageScaleMode( ImageScaleMode::ANISOTROPIC );
+ OSL_VERIFY( i_value >>= nImageScaleMode ); // convertFastPropertyValue ensures that this has the proper type
+ if ( ( nImageScaleMode != ImageScaleMode::NONE )
+ && ( nImageScaleMode != ImageScaleMode::ISOTROPIC )
+ && ( nImageScaleMode != ImageScaleMode::ANISOTROPIC )
+ )
+ throw IllegalArgumentException( OUString(), *this, 1 );
+ }
+ break;
+ }
+
+ AnimatedImagesControlModel_Base::setFastPropertyValue_NoBroadcast( i_handle, i_value );
+ }
+
+
+ Any AnimatedImagesControlModel::ImplGetDefaultValue( sal_uInt16 i_propertyId ) const
+ {
+ switch ( i_propertyId )
+ {
+ case BASEPROPERTY_DEFAULTCONTROL:
+ return Any( OUString("com.sun.star.awt.AnimatedImagesControl") );
+
+ case BASEPROPERTY_BORDER:
+ return Any( css::awt::VisualEffect::NONE );
+
+ case BASEPROPERTY_STEP_TIME:
+ return Any( sal_Int32(100) );
+
+ case BASEPROPERTY_AUTO_REPEAT:
+ return Any( true );
+
+ case BASEPROPERTY_IMAGE_SCALE_MODE:
+ return Any( ImageScaleMode::NONE );
+
+ default:
+ return UnoControlModel::ImplGetDefaultValue( i_propertyId );
+ }
+ }
+
+
+ ::cppu::IPropertyArrayHelper& SAL_CALL AnimatedImagesControlModel::getInfoHelper()
+ {
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+ }
+
+
+ ::sal_Int32 SAL_CALL AnimatedImagesControlModel::getStepTime()
+ {
+ sal_Int32 nStepTime( 100 );
+ OSL_VERIFY( getPropertyValue( GetPropertyName( BASEPROPERTY_STEP_TIME ) ) >>= nStepTime );
+ return nStepTime;
+ }
+
+
+ void SAL_CALL AnimatedImagesControlModel::setStepTime( ::sal_Int32 i_stepTime )
+ {
+ setPropertyValue( GetPropertyName( BASEPROPERTY_STEP_TIME ), Any( i_stepTime ) );
+ }
+
+
+ sal_Bool SAL_CALL AnimatedImagesControlModel::getAutoRepeat()
+ {
+ bool bAutoRepeat( true );
+ OSL_VERIFY( getPropertyValue( GetPropertyName( BASEPROPERTY_AUTO_REPEAT ) ) >>= bAutoRepeat );
+ return bAutoRepeat;
+ }
+
+
+ void SAL_CALL AnimatedImagesControlModel::setAutoRepeat( sal_Bool i_autoRepeat )
+ {
+ setPropertyValue( GetPropertyName( BASEPROPERTY_AUTO_REPEAT ), Any( i_autoRepeat ) );
+ }
+
+
+ ::sal_Int16 SAL_CALL AnimatedImagesControlModel::getScaleMode()
+ {
+ sal_Int16 nImageScaleMode( ImageScaleMode::ANISOTROPIC );
+ OSL_VERIFY( getPropertyValue( GetPropertyName( BASEPROPERTY_IMAGE_SCALE_MODE ) ) >>= nImageScaleMode );
+ return nImageScaleMode;
+ }
+
+
+ void SAL_CALL AnimatedImagesControlModel::setScaleMode( ::sal_Int16 i_scaleMode )
+ {
+ setPropertyValue( GetPropertyName( BASEPROPERTY_IMAGE_SCALE_MODE ), Any( i_scaleMode ) );
+ }
+
+
+ ::sal_Int32 SAL_CALL AnimatedImagesControlModel::getImageSetCount( )
+ {
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+ if ( GetBroadcastHelper().bDisposed || GetBroadcastHelper().bInDispose )
+ throw DisposedException();
+
+ return maImageSets.size();
+ }
+
+
+ Sequence< OUString > SAL_CALL AnimatedImagesControlModel::getImageSet( ::sal_Int32 i_index )
+ {
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+ if ( GetBroadcastHelper().bDisposed || GetBroadcastHelper().bInDispose )
+ throw DisposedException();
+
+ lcl_checkIndex( maImageSets, i_index, *this );
+
+ return maImageSets[ i_index ];
+ }
+
+
+ void SAL_CALL AnimatedImagesControlModel::insertImageSet( ::sal_Int32 i_index, const Sequence< OUString >& i_imageURLs )
+ {
+ ::osl::ClearableMutexGuard aGuard( GetMutex() );
+ // sanity checks
+ if ( GetBroadcastHelper().bDisposed || GetBroadcastHelper().bInDispose )
+ throw DisposedException();
+
+ lcl_checkIndex( maImageSets, i_index, *this, true );
+
+ // actual insertion
+ maImageSets.insert( maImageSets.begin() + i_index, i_imageURLs );
+
+ // listener notification
+ lcl_notify( aGuard, BrdcstHelper, &XContainerListener::elementInserted, i_index, i_imageURLs, *this );
+ }
+
+
+ void SAL_CALL AnimatedImagesControlModel::replaceImageSet( ::sal_Int32 i_index, const Sequence< OUString >& i_imageURLs )
+ {
+ ::osl::ClearableMutexGuard aGuard( GetMutex() );
+ // sanity checks
+ if ( GetBroadcastHelper().bDisposed || GetBroadcastHelper().bInDispose )
+ throw DisposedException();
+
+ lcl_checkIndex( maImageSets, i_index, *this );
+
+ // actual insertion
+ maImageSets[ i_index ] = i_imageURLs;
+
+ // listener notification
+ lcl_notify( aGuard, BrdcstHelper, &XContainerListener::elementReplaced, i_index, i_imageURLs, *this );
+ }
+
+
+ void SAL_CALL AnimatedImagesControlModel::removeImageSet( ::sal_Int32 i_index )
+ {
+ ::osl::ClearableMutexGuard aGuard( GetMutex() );
+ // sanity checks
+ if ( GetBroadcastHelper().bDisposed || GetBroadcastHelper().bInDispose )
+ throw DisposedException();
+
+ lcl_checkIndex( maImageSets, i_index, *this );
+
+ // actual removal
+ ::std::vector< Sequence< OUString > >::iterator removalPos = maImageSets.begin() + i_index;
+ Sequence< OUString > aRemovedElement( *removalPos );
+ maImageSets.erase( removalPos );
+
+ // listener notification
+ lcl_notify( aGuard, BrdcstHelper, &XContainerListener::elementRemoved, i_index, aRemovedElement, *this );
+ }
+
+
+ void SAL_CALL AnimatedImagesControlModel::addContainerListener( const Reference< XContainerListener >& i_listener )
+ {
+ BrdcstHelper.addListener( cppu::UnoType<XContainerListener>::get(), i_listener );
+ }
+
+
+ void SAL_CALL AnimatedImagesControlModel::removeContainerListener( const Reference< XContainerListener >& i_listener )
+ {
+ BrdcstHelper.removeListener( cppu::UnoType<XContainerListener>::get(), i_listener );
+ }
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+org_openoffice_comp_toolkit_AnimatedImagesControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new AnimatedImagesControl());
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+org_openoffice_comp_toolkit_AnimatedImagesControlModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new toolkit::AnimatedImagesControlModel(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/controlmodelcontainerbase.cxx b/toolkit/source/controls/controlmodelcontainerbase.cxx
new file mode 100644
index 000000000..677d000f9
--- /dev/null
+++ b/toolkit/source/controls/controlmodelcontainerbase.cxx
@@ -0,0 +1,1820 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <controls/controlmodelcontainerbase.hxx>
+#include <vcl/svapp.hxx>
+#include <o3tl/safeint.hxx>
+#include <osl/mutex.hxx>
+#include <toolkit/helper/property.hxx>
+#include <helper/servicenames.hxx>
+#include <controls/geometrycontrolmodel.hxx>
+#include <toolkit/controls/unocontrols.hxx>
+#include <controls/formattedcontrol.hxx>
+#include <controls/roadmapcontrol.hxx>
+#include <controls/tkscrollbar.hxx>
+#include <controls/tabpagemodel.hxx>
+#include <controls/stdtabcontroller.hxx>
+#include <com/sun/star/awt/PosSize.hpp>
+#include <com/sun/star/resource/XStringResourceResolver.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/weak.hxx>
+#include <cppuhelper/weakagg.hxx>
+#include <tools/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <vcl/outdev.hxx>
+#include <comphelper/types.hxx>
+
+#include "tree/treecontrol.hxx"
+#include "grid/gridcontrol.hxx"
+#include <controls/tabpagecontainer.hxx>
+
+#include <map>
+#include <algorithm>
+#include <tools/urlobj.hxx>
+#include <osl/file.hxx>
+#include <sal/log.hxx>
+#include <controls/dialogcontrol.hxx>
+
+#include <helper/unopropertyarrayhelper.hxx>
+#include "controlmodelcontainerbase_internal.hxx"
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::util;
+using namespace toolkit;
+
+constexpr OUStringLiteral PROPERTY_RESOURCERESOLVER = u"ResourceResolver";
+
+
+namespace
+{
+ const Sequence< OUString >& lcl_getLanguageDependentProperties()
+ {
+ // note: properties must be sorted
+ static Sequence<OUString> s_aLanguageDependentProperties{ "HelpText", "Title" };
+ return s_aLanguageDependentProperties;
+ }
+
+// functor for disposing a control model
+struct DisposeControlModel
+{
+ void operator()( Reference< XControlModel >& _rxModel )
+ {
+ try
+ {
+ ::comphelper::disposeComponent( _rxModel );
+ }
+ catch (const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("toolkit", "caught an exception while disposing a component" );
+ }
+ }
+};
+
+}
+
+
+// functor for cloning a control model, and insertion into a target list
+struct CloneControlModel
+{
+private:
+ ControlModelContainerBase::UnoControlModelHolderVector& m_rTargetVector;
+
+public:
+ explicit CloneControlModel( ControlModelContainerBase::UnoControlModelHolderVector& _rTargetVector )
+ :m_rTargetVector( _rTargetVector )
+ {
+ }
+
+ void operator()( const ControlModelContainerBase::UnoControlModelHolder& _rSource )
+ {
+ // clone the source object
+ Reference< XCloneable > xCloneSource( _rSource.first, UNO_QUERY );
+ Reference< XControlModel > xClone( xCloneSource->createClone(), UNO_QUERY );
+ // add to target list
+ m_rTargetVector.emplace_back( xClone, _rSource.second );
+ }
+};
+
+
+// functor for comparing a XControlModel with a given reference
+struct CompareControlModel
+{
+private:
+ Reference< XControlModel > m_xReference;
+public:
+ explicit CompareControlModel( const Reference< XControlModel >& _rxReference ) : m_xReference( _rxReference ) { }
+
+ bool operator()( const ControlModelContainerBase::UnoControlModelHolder& _rCompare )
+ {
+ return _rCompare.first.get() == m_xReference.get();
+ }
+};
+
+
+static void lcl_throwIllegalArgumentException( )
+{ // throwing is expensive (in terms of code size), thus we hope the compiler does not inline this...
+ throw IllegalArgumentException();
+}
+
+
+static void lcl_throwNoSuchElementException( )
+{ // throwing is expensive (in terms of code size), thus we hope the compiler does not inline this...
+ throw NoSuchElementException();
+}
+
+
+static void lcl_throwElementExistException( )
+{ // throwing is expensive (in terms of code size), thus we hope the compiler does not inline this...
+ throw ElementExistException();
+}
+
+
+static OUString getTabIndexPropertyName( )
+{
+ return "TabIndex";
+}
+
+
+static OUString getStepPropertyName( )
+{
+ return "Step";
+}
+
+
+
+ControlModelContainerBase::ControlModelContainerBase( const Reference< XComponentContext >& rxContext )
+ :ControlModelContainer_IBase( rxContext )
+ ,maContainerListeners( *this )
+ ,maChangeListeners ( GetMutex() )
+ ,mbGroupsUpToDate( false )
+ ,m_nTabPageId(0)
+{
+ ImplRegisterProperty(BASEPROPERTY_ENABLED);
+}
+
+ControlModelContainerBase::ControlModelContainerBase( const ControlModelContainerBase& rModel )
+ : ControlModelContainer_IBase( rModel )
+ , maContainerListeners( *this )
+ , maChangeListeners ( GetMutex() )
+ , mbGroupsUpToDate( false )
+ , m_nTabPageId( rModel.m_nTabPageId )
+{
+}
+
+ControlModelContainerBase::~ControlModelContainerBase()
+{
+ maModels.clear();
+ mbGroupsUpToDate = false;
+}
+
+Any ControlModelContainerBase::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ Any aAny;
+
+ switch ( nPropId )
+ {
+ case BASEPROPERTY_DEFAULTCONTROL:
+ aAny <<= OUString::createFromAscii( szServiceName_UnoControlDialog );
+ break;
+ default:
+ aAny = UnoControlModel::ImplGetDefaultValue( nPropId );
+ }
+
+ return aAny;
+}
+
+::cppu::IPropertyArrayHelper& ControlModelContainerBase::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+void SAL_CALL ControlModelContainerBase::dispose( )
+{
+
+ // tell our listeners
+ {
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ EventObject aDisposeEvent;
+ aDisposeEvent.Source = static_cast< XAggregation* >( static_cast< ::cppu::OWeakAggObject* >( this ) );
+
+ maContainerListeners.disposeAndClear( aDisposeEvent );
+ maChangeListeners.disposeAndClear( aDisposeEvent );
+ }
+
+
+ // call the base class
+ UnoControlModel::dispose();
+
+
+ // dispose our child models
+ // for this, collect the models (we collect them from maModels, and this is modified when disposing children)
+ ::std::vector< Reference< XControlModel > > aChildModels( maModels.size() );
+
+ ::std::transform(
+ maModels.begin(), maModels.end(), // source range
+ aChildModels.begin(), // target location
+ []( const UnoControlModelHolder& rUnoControlModelHolder )
+ { return rUnoControlModelHolder.first; } // operation to apply -> select the XControlModel part
+ );
+
+ // now dispose
+ ::std::for_each( aChildModels.begin(), aChildModels.end(), DisposeControlModel() );
+ aChildModels.clear();
+
+ mbGroupsUpToDate = false;
+}
+
+// XMultiPropertySet
+Reference< XPropertySetInfo > ControlModelContainerBase::getPropertySetInfo( )
+{
+ static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+void ControlModelContainerBase::Clone_Impl(ControlModelContainerBase& _rClone) const
+{
+ // clone all children
+ ::std::for_each(
+ maModels.begin(), maModels.end(),
+ CloneControlModel( _rClone.maModels )
+ );
+}
+rtl::Reference<UnoControlModel> ControlModelContainerBase::Clone() const
+{
+ // clone the container itself
+ rtl::Reference<ControlModelContainerBase> pClone = new ControlModelContainerBase( *this );
+ Clone_Impl(*pClone);
+
+ return pClone;
+}
+
+ControlModelContainerBase::UnoControlModelHolderVector::iterator ControlModelContainerBase::ImplFindElement( std::u16string_view rName )
+{
+ return ::std::find_if( maModels.begin(), maModels.end(), [&](const UnoControlModelHolder& elem) { return elem.second == rName; });
+}
+
+// ::XMultiServiceFactory
+Reference< XInterface > ControlModelContainerBase::createInstance( const OUString& aServiceSpecifier )
+{
+ SolarMutexGuard aGuard;
+
+ rtl::Reference<OGeometryControlModel_Base> pNewModel;
+
+ if ( aServiceSpecifier == "com.sun.star.awt.UnoControlEditModel" )
+ pNewModel = new OGeometryControlModel< UnoControlEditModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.UnoControlFormattedFieldModel" )
+ pNewModel = new OGeometryControlModel< UnoControlFormattedFieldModel >( m_xContext);
+ else if ( aServiceSpecifier == "com.sun.star.awt.UnoControlFileControlModel" )
+ pNewModel = new OGeometryControlModel< UnoControlFileControlModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.UnoControlButtonModel" )
+ pNewModel = new OGeometryControlModel< UnoControlButtonModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.UnoControlImageControlModel" )
+ pNewModel = new OGeometryControlModel< UnoControlImageControlModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.UnoControlRadioButtonModel" )
+ pNewModel = new OGeometryControlModel< UnoControlRadioButtonModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.UnoControlCheckBoxModel" )
+ pNewModel = new OGeometryControlModel< UnoControlCheckBoxModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.UnoControlFixedHyperlinkModel" )
+ pNewModel = new OGeometryControlModel< UnoControlFixedHyperlinkModel >( m_xContext );
+ else if ( aServiceSpecifier == "stardiv.vcl.controlmodel.FixedText" )
+ pNewModel = new OGeometryControlModel< UnoControlFixedTextModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.UnoControlGroupBoxModel" )
+ pNewModel = new OGeometryControlModel< UnoControlGroupBoxModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.UnoControlListBoxModel" )
+ pNewModel = new OGeometryControlModel< UnoControlListBoxModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.UnoControlComboBoxModel" )
+ pNewModel = new OGeometryControlModel< UnoControlComboBoxModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.UnoControlDateFieldModel" )
+ pNewModel = new OGeometryControlModel< UnoControlDateFieldModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.UnoControlTimeFieldModel" )
+ pNewModel = new OGeometryControlModel< UnoControlTimeFieldModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.UnoControlNumericFieldModel" )
+ pNewModel = new OGeometryControlModel< UnoControlNumericFieldModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.UnoControlCurrencyFieldModel" )
+ pNewModel = new OGeometryControlModel< UnoControlCurrencyFieldModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.UnoControlPatternFieldModel" )
+ pNewModel = new OGeometryControlModel< UnoControlPatternFieldModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.UnoControlProgressBarModel" )
+ pNewModel = new OGeometryControlModel< UnoControlProgressBarModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.UnoControlScrollBarModel" )
+ pNewModel = new OGeometryControlModel< UnoControlScrollBarModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.UnoControlFixedLineModel" )
+ pNewModel = new OGeometryControlModel< UnoControlFixedLineModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.UnoControlRoadmapModel" )
+ pNewModel = new OGeometryControlModel< UnoControlRoadmapModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.tree.TreeControlModel" )
+ pNewModel = new OGeometryControlModel< UnoTreeModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.grid.UnoControlGridModel" )
+ pNewModel = new OGeometryControlModel< UnoGridModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.tab.UnoControlTabPageContainerModel" )
+ pNewModel = new OGeometryControlModel< UnoControlTabPageContainerModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.UnoMultiPageModel" )
+ pNewModel = new OGeometryControlModel< UnoMultiPageModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.tab.UnoControlTabPageModel" )
+ pNewModel = new OGeometryControlModel< UnoControlTabPageModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.UnoPageModel" )
+ pNewModel = new OGeometryControlModel< UnoPageModel >( m_xContext );
+ else if ( aServiceSpecifier == "com.sun.star.awt.UnoFrameModel" )
+ pNewModel = new OGeometryControlModel< UnoFrameModel >( m_xContext );
+
+ if ( !pNewModel )
+ {
+ Reference< XInterface > xObject = m_xContext->getServiceManager()->createInstanceWithContext(aServiceSpecifier, m_xContext);
+ Reference< XServiceInfo > xSI( xObject, UNO_QUERY );
+ Reference< XCloneable > xCloneAccess( xSI, UNO_QUERY );
+ Reference< XAggregation > xAgg( xCloneAccess, UNO_QUERY );
+ if ( xAgg.is() )
+ {
+ if ( xSI->supportsService("com.sun.star.awt.UnoControlModel") )
+ {
+ // release 3 of the 4 references we have to the object
+ xAgg.clear();
+ xSI.clear();
+ xObject.clear();
+
+ pNewModel = new OCommonGeometryControlModel( xCloneAccess, aServiceSpecifier );
+ }
+ }
+ }
+
+ Reference< XInterface > xNewModel = static_cast<cppu::OWeakObject*>(pNewModel.get());
+ return xNewModel;
+}
+
+Reference< XInterface > ControlModelContainerBase::createInstanceWithArguments( const OUString& ServiceSpecifier, const Sequence< Any >& i_arguments )
+{
+ const Reference< XInterface > xInstance( createInstance( ServiceSpecifier ) );
+ const Reference< XInitialization > xInstanceInit( xInstance, UNO_QUERY );
+ ENSURE_OR_RETURN( xInstanceInit.is(), "ControlModelContainerBase::createInstanceWithArguments: can't pass the arguments!", xInstance );
+ xInstanceInit->initialize( i_arguments );
+ return xInstance;
+}
+
+Sequence< OUString > ControlModelContainerBase::getAvailableServiceNames()
+{
+ return { "com.sun.star.awt.UnoControlEditModel",
+ "com.sun.star.awt.UnoControlFormattedFieldModel",
+ "com.sun.star.awt.UnoControlFileControlModel",
+ "com.sun.star.awt.UnoControlButtonModel",
+ "com.sun.star.awt.UnoControlImageControlModel",
+ "com.sun.star.awt.UnoControlRadioButtonModel",
+ "com.sun.star.awt.UnoControlCheckBoxModel",
+ "com.sun.star.awt.UnoControlFixedTextModel",
+ "com.sun.star.awt.UnoControlGroupBoxModel",
+ "com.sun.star.awt.UnoControlListBoxModel",
+ "com.sun.star.awt.UnoControlComboBoxModel",
+ "com.sun.star.awt.UnoControlDateFieldModel",
+ "com.sun.star.awt.UnoControlTimeFieldModel",
+ "com.sun.star.awt.UnoControlNumericFieldModel",
+ "com.sun.star.awt.UnoControlCurrencyFieldModel",
+ "com.sun.star.awt.UnoControlPatternFieldModel",
+ "com.sun.star.awt.UnoControlProgressBarModel",
+ "com.sun.star.awt.UnoControlScrollBarModel",
+ "com.sun.star.awt.UnoControlFixedLineModel",
+ "com.sun.star.awt.UnoControlRoadmapModel",
+ "com.sun.star.awt.tree.TreeControlModel",
+ "com.sun.star.awt.grid.UnoControlGridModel",
+ "com.sun.star.awt.UnoControlFixedHyperlinkModel",
+ "com.sun.star.awt.tab.UnoControlTabPageContainerModel",
+ "com.sun.star.awt.tab.UnoControlTabPageModel",
+ "com.sun.star.awt.UnoMultiPageModel",
+ "com.sun.star.awt.UnoFrameModel"
+ };
+}
+
+// XContainer
+void ControlModelContainerBase::addContainerListener( const Reference< XContainerListener >& l )
+{
+ maContainerListeners.addInterface( l );
+}
+
+void ControlModelContainerBase::removeContainerListener( const Reference< XContainerListener >& l )
+{
+ maContainerListeners.removeInterface( l );
+}
+
+// XElementAccess
+Type ControlModelContainerBase::getElementType()
+{
+ Type aType = cppu::UnoType<XControlModel>::get();
+ return aType;
+}
+
+sal_Bool ControlModelContainerBase::hasElements()
+{
+ return !maModels.empty();
+}
+
+// XNameContainer, XNameReplace, XNameAccess
+void ControlModelContainerBase::replaceByName( const OUString& aName, const Any& aElement )
+{
+ SolarMutexGuard aGuard;
+
+ Reference< XControlModel > xNewModel;
+ aElement >>= xNewModel;
+ if ( !xNewModel.is() )
+ lcl_throwIllegalArgumentException();
+
+ UnoControlModelHolderVector::iterator aElementPos = ImplFindElement( aName );
+ if ( maModels.end() == aElementPos )
+ lcl_throwNoSuchElementException();
+ // Dialog behaviour is to have all containee names unique (MSO Userform is the same)
+ // With container controls you could have constructed an existing hierarchy and are now
+ // add this to an existing container, in this case a name nested in the containment
+ // hierarchy of the added control could contain a name clash, if we have access to the
+ // list of global names then recursively check for previously existing names (we need
+ // to do this obviously before the 'this' objects container is updated)
+ Reference< XNameContainer > xAllChildren( getPropertyValue( GetPropertyName( BASEPROPERTY_USERFORMCONTAINEES ) ), UNO_QUERY );
+ if ( xAllChildren.is() )
+ {
+ // remove old control (and children) from global list of containers
+ updateUserFormChildren( xAllChildren, aName, Remove, uno::Reference< XControlModel >() );
+ // Add new control (and containers if they exist)
+ updateUserFormChildren( xAllChildren, aName, Insert, xNewModel );
+ }
+ // stop listening at the old model
+ stopControlListening( aElementPos->first );
+ Reference< XControlModel > xReplaced( aElementPos->first );
+ // remember the new model, and start listening
+ aElementPos->first = xNewModel;
+ startControlListening( xNewModel );
+
+ ContainerEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.Element = aElement;
+ aEvent.ReplacedElement <<= xReplaced;
+ aEvent.Accessor <<= aName;
+
+ // notify the container listener
+ maContainerListeners.elementReplaced( aEvent );
+
+ // our "tab controller model" has potentially changed -> notify this
+ implNotifyTabModelChange( aName );
+}
+
+Any ControlModelContainerBase::getByName( const OUString& aName )
+{
+ UnoControlModelHolderVector::iterator aElementPos = ImplFindElement( aName );
+ if ( maModels.end() == aElementPos )
+ lcl_throwNoSuchElementException();
+
+ return Any( aElementPos->first );
+}
+
+Sequence< OUString > ControlModelContainerBase::getElementNames()
+{
+ Sequence< OUString > aNames( maModels.size() );
+
+ ::std::transform(
+ maModels.begin(), maModels.end(), // source range
+ aNames.getArray(), // target range
+ []( const UnoControlModelHolder& rUnoControlModelHolder )
+ { return rUnoControlModelHolder.second; } // operator to apply: select the second element (the name)
+ );
+
+ return aNames;
+}
+
+sal_Bool ControlModelContainerBase::hasByName( const OUString& aName )
+{
+ return maModels.end() != ImplFindElement( aName );
+}
+
+void ControlModelContainerBase::insertByName( const OUString& aName, const Any& aElement )
+{
+ SolarMutexGuard aGuard;
+
+ Reference< XControlModel > xM;
+ aElement >>= xM;
+
+ if ( xM.is() )
+ {
+ Reference< beans::XPropertySet > xProps( xM, UNO_QUERY );
+ if ( xProps.is() )
+ {
+
+ Reference< beans::XPropertySetInfo > xPropInfo = xProps->getPropertySetInfo();
+
+ const OUString& sImageSourceProperty = GetPropertyName( BASEPROPERTY_IMAGEURL );
+ if ( xPropInfo->hasPropertyByName( sImageSourceProperty ) && ImplHasProperty(BASEPROPERTY_DIALOGSOURCEURL) )
+ {
+ Any aUrl = xProps->getPropertyValue( sImageSourceProperty );
+
+ OUString absoluteUrl =
+ getPhysicalLocation( getPropertyValue( GetPropertyName( BASEPROPERTY_DIALOGSOURCEURL ) ), aUrl );
+
+ aUrl <<= absoluteUrl;
+
+ xProps->setPropertyValue( sImageSourceProperty , aUrl );
+ }
+ }
+ }
+
+
+ if ( aName.isEmpty() || !xM.is() )
+ lcl_throwIllegalArgumentException();
+
+ UnoControlModelHolderVector::iterator aElementPos = ImplFindElement( aName );
+ if ( maModels.end() != aElementPos )
+ lcl_throwElementExistException();
+
+ // Dialog behaviour is to have all containee names unique (MSO Userform is the same)
+ // With container controls you could have constructed an existing hierarchy and are now
+ // add this to an existing container, in this case a name nested in the containment
+ // hierarchy of the added control could contain a name clash, if we have access to the
+ // list of global names then we need to recursively check for previously existing
+ // names (we need to do this obviously before the 'this' objects container is updated)
+ // remove old control (and children) from global list of containers
+ Reference< XNameContainer > xAllChildren( getPropertyValue( GetPropertyName( BASEPROPERTY_USERFORMCONTAINEES ) ), UNO_QUERY );
+
+ if ( xAllChildren.is() )
+ updateUserFormChildren( xAllChildren, aName, Insert, xM );
+ maModels.emplace_back( xM, aName );
+ mbGroupsUpToDate = false;
+ startControlListening( xM );
+
+ ContainerEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.Element = aElement;
+ aEvent.Accessor <<= aName;
+ maContainerListeners.elementInserted( aEvent );
+
+ // our "tab controller model" has potentially changed -> notify this
+ implNotifyTabModelChange( aName );
+}
+
+void ControlModelContainerBase::removeByName( const OUString& aName )
+{
+ SolarMutexGuard aGuard;
+
+ UnoControlModelHolderVector::iterator aElementPos = ImplFindElement( aName );
+ if ( maModels.end() == aElementPos )
+ lcl_throwNoSuchElementException();
+
+ // Dialog behaviour is to have all containee names unique (MSO Userform is the same)
+ // With container controls you could have constructed an existing hierarchy and are now
+ // removing this control from an existing container, in this case all nested names in
+ // the containment hierarchy of the control to be removed need to be removed from the global
+ // names cache (we need to do this obviously before the 'this' objects container is updated)
+ Reference< XNameContainer > xAllChildren( getPropertyValue( GetPropertyName( BASEPROPERTY_USERFORMCONTAINEES ) ), UNO_QUERY );
+ if ( xAllChildren.is() )
+ updateUserFormChildren( xAllChildren, aName, Remove, uno::Reference< XControlModel >() );
+
+ ContainerEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.Element <<= aElementPos->first;
+ aEvent.Accessor <<= aName;
+ maContainerListeners.elementRemoved( aEvent );
+
+ stopControlListening( aElementPos->first );
+ Reference< XPropertySet > xPS( aElementPos->first, UNO_QUERY );
+ maModels.erase( aElementPos );
+ mbGroupsUpToDate = false;
+
+ if ( xPS.is() )
+ {
+ try
+ {
+ xPS->setPropertyValue( PROPERTY_RESOURCERESOLVER, Any( Reference< resource::XStringResourceResolver >() ) );
+ }
+ catch (const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+ }
+
+ // our "tab controller model" has potentially changed -> notify this
+ implNotifyTabModelChange( aName );
+}
+
+
+sal_Bool SAL_CALL ControlModelContainerBase::getGroupControl( )
+{
+ return true;
+}
+
+
+void SAL_CALL ControlModelContainerBase::setGroupControl( sal_Bool )
+{
+ SAL_WARN("toolkit", "explicit grouping not supported" );
+}
+
+
+void SAL_CALL ControlModelContainerBase::setControlModels( const Sequence< Reference< XControlModel > >& _rControls )
+{
+ SolarMutexGuard aGuard;
+
+ // set the tab indexes according to the order of models in the sequence
+
+ sal_Int16 nTabIndex = 1;
+
+ for ( auto const & control : _rControls )
+ {
+ // look up the control in our own structure. This is to prevent invalid arguments
+ UnoControlModelHolderVector::const_iterator aPos =
+ ::std::find_if(
+ maModels.begin(), maModels.end(),
+ CompareControlModel( control )
+ );
+ if ( maModels.end() != aPos )
+ {
+ // okay, this is an existent model
+ // now set the TabIndex property (if applicable)
+ Reference< XPropertySet > xProps( aPos->first, UNO_QUERY );
+ Reference< XPropertySetInfo > xPSI;
+ if ( xProps.is() )
+ xPSI = xProps->getPropertySetInfo();
+ if ( xPSI.is() && xPSI->hasPropertyByName( getTabIndexPropertyName() ) )
+ xProps->setPropertyValue( getTabIndexPropertyName(), Any( nTabIndex++ ) );
+ }
+ mbGroupsUpToDate = false;
+ }
+}
+
+
+typedef ::std::multimap< sal_Int32, Reference< XControlModel > > MapIndexToModel;
+
+
+Sequence< Reference< XControlModel > > SAL_CALL ControlModelContainerBase::getControlModels( )
+{
+ SolarMutexGuard aGuard;
+
+ MapIndexToModel aSortedModels;
+ // will be the sorted container of all models which have a tab index property
+ ::std::vector< Reference< XControlModel > > aUnindexedModels;
+ // will be the container of all models which do not have a tab index property
+
+ for ( const auto& rModel : maModels )
+ {
+ Reference< XControlModel > xModel( rModel.first );
+
+ // see if the model has a TabIndex property
+ Reference< XPropertySet > xControlProps( xModel, UNO_QUERY );
+ Reference< XPropertySetInfo > xPSI;
+ if ( xControlProps.is() )
+ xPSI = xControlProps->getPropertySetInfo( );
+ DBG_ASSERT( xPSI.is(), "ControlModelContainerBase::getControlModels: invalid child model!" );
+
+ // has it?
+ if ( xPSI.is() && xPSI->hasPropertyByName( getTabIndexPropertyName() ) )
+ { // yes
+ sal_Int32 nTabIndex = -1;
+ xControlProps->getPropertyValue( getTabIndexPropertyName() ) >>= nTabIndex;
+
+ aSortedModels.emplace( nTabIndex, xModel );
+ }
+ else if ( xModel.is() )
+ // no, it hasn't, but we have to include it, anyway
+ aUnindexedModels.push_back( xModel );
+ }
+
+ // okay, here we have a container of all our models, sorted by tab index,
+ // plus a container of "unindexed" models
+ // -> merge them
+ Sequence< Reference< XControlModel > > aReturn( aUnindexedModels.size() + aSortedModels.size() );
+ ::std::transform(
+ aSortedModels.begin(), aSortedModels.end(),
+ ::std::copy( aUnindexedModels.begin(), aUnindexedModels.end(), aReturn.getArray() ),
+ [] ( const MapIndexToModel::value_type& entryIndexToModel )
+ { return entryIndexToModel.second; }
+ );
+
+ return aReturn;
+}
+
+
+void SAL_CALL ControlModelContainerBase::setGroup( const Sequence< Reference< XControlModel > >&, const OUString& )
+{
+ // not supported. We have only implicit grouping:
+ // We only have a sequence of control models, and we _know_ (yes, that's a HACK relying on
+ // implementation details) that VCL does grouping according to the order of controls automatically
+ // At least VCL does this for all we're interested in: Radio buttons.
+ SAL_WARN("toolkit", "grouping not supported" );
+}
+
+////----- XInitialization -------------------------------------------------------------------
+void SAL_CALL ControlModelContainerBase::initialize (const Sequence<Any>& rArguments)
+{
+ if ( rArguments.getLength() == 1 )
+ {
+ sal_Int16 nPageId = -1;
+ if ( !( rArguments[ 0 ] >>= nPageId ))
+ throw lang::IllegalArgumentException();
+ m_nTabPageId = nPageId;
+ }
+ else
+ m_nTabPageId = -1;
+}
+::sal_Int16 SAL_CALL ControlModelContainerBase::getTabPageID()
+{
+ return m_nTabPageId;
+}
+sal_Bool SAL_CALL ControlModelContainerBase::getEnabled()
+{
+ SolarMutexGuard aGuard;
+ Reference<XPropertySet> xThis(*this, UNO_QUERY);
+ bool bEnabled = false;
+ xThis->getPropertyValue(GetPropertyName(BASEPROPERTY_ENABLED)) >>= bEnabled;
+ return bEnabled;
+}
+void SAL_CALL ControlModelContainerBase::setEnabled( sal_Bool _enabled )
+{
+ SolarMutexGuard aGuard;
+ Reference<XPropertySet> xThis(*this, UNO_QUERY);
+ xThis->setPropertyValue(GetPropertyName(BASEPROPERTY_ENABLED), Any(_enabled));
+}
+OUString SAL_CALL ControlModelContainerBase::getTitle()
+{
+ SolarMutexGuard aGuard;
+ Reference<XPropertySet> xThis(*this,UNO_QUERY);
+ OUString sTitle;
+ xThis->getPropertyValue(GetPropertyName(BASEPROPERTY_TITLE)) >>= sTitle;
+ return sTitle;
+}
+void SAL_CALL ControlModelContainerBase::setTitle( const OUString& _title )
+{
+ SolarMutexGuard aGuard;
+ Reference<XPropertySet> xThis(*this,UNO_QUERY);
+ xThis->setPropertyValue(GetPropertyName(BASEPROPERTY_TITLE),Any(_title));
+}
+OUString SAL_CALL ControlModelContainerBase::getImageURL()
+{
+ return m_sImageURL;
+}
+void SAL_CALL ControlModelContainerBase::setImageURL( const OUString& _imageurl )
+{
+ m_sImageURL = _imageurl;
+}
+OUString SAL_CALL ControlModelContainerBase::getToolTip()
+{
+ return m_sTooltip;
+}
+void SAL_CALL ControlModelContainerBase::setToolTip( const OUString& _tooltip )
+{
+ m_sTooltip = _tooltip;
+}
+
+
+namespace
+{
+ enum GroupingMachineState
+ {
+ eLookingForGroup,
+ eExpandingGroup
+ };
+
+
+ sal_Int32 lcl_getDialogStep( const Reference< XControlModel >& _rxModel )
+ {
+ sal_Int32 nStep = 0;
+ try
+ {
+ Reference< XPropertySet > xModelProps( _rxModel, UNO_QUERY );
+ xModelProps->getPropertyValue( getStepPropertyName() ) >>= nStep;
+ }
+ catch (const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("toolkit", "caught an exception while determining the dialog page" );
+ }
+ return nStep;
+ }
+}
+
+
+sal_Int32 SAL_CALL ControlModelContainerBase::getGroupCount( )
+{
+ SolarMutexGuard aGuard;
+
+ implUpdateGroupStructure();
+
+ return maGroups.size();
+}
+
+
+void SAL_CALL ControlModelContainerBase::getGroup( sal_Int32 _nGroup, Sequence< Reference< XControlModel > >& _rGroup, OUString& _rName )
+{
+ SolarMutexGuard aGuard;
+
+ implUpdateGroupStructure();
+
+ if ( ( _nGroup < 0 ) || ( o3tl::make_unsigned(_nGroup) >= maGroups.size() ) )
+ {
+ SAL_WARN("toolkit", "invalid argument and I am not allowed to throw exception!" );
+ _rGroup.realloc( 0 );
+ _rName.clear();
+ }
+ else
+ {
+ AllGroups::const_iterator aGroupPos = maGroups.begin() + _nGroup;
+ _rGroup.realloc( aGroupPos->size() );
+ // copy the models
+ ::std::copy( aGroupPos->begin(), aGroupPos->end(), _rGroup.getArray() );
+ // give the group a name
+ _rName = OUString::number( _nGroup );
+ }
+}
+
+
+void SAL_CALL ControlModelContainerBase::getGroupByName( const OUString& _rName, Sequence< Reference< XControlModel > >& _rGroup )
+{
+ SolarMutexGuard aGuard;
+
+ OUString sDummyName;
+ getGroup( _rName.toInt32( ), _rGroup, sDummyName );
+}
+
+
+void SAL_CALL ControlModelContainerBase::addChangesListener( const Reference< XChangesListener >& _rxListener )
+{
+ maChangeListeners.addInterface( _rxListener );
+}
+
+
+void SAL_CALL ControlModelContainerBase::removeChangesListener( const Reference< XChangesListener >& _rxListener )
+{
+ maChangeListeners.removeInterface( _rxListener );
+}
+
+
+void ControlModelContainerBase::implNotifyTabModelChange( const OUString& _rAccessor )
+{
+ // multiplex to our change listeners:
+ // the changes event
+ ChangesEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.Base <<= aEvent.Source; // the "base of the changes root" is also ourself
+ aEvent.Changes.realloc( 1 ); // exactly one change
+ aEvent.Changes.getArray()[ 0 ].Accessor <<= _rAccessor;
+
+
+ std::vector< Reference< css::util::XChangesListener > > aChangeListeners( maChangeListeners.getElements() );
+ for ( const auto& rListener : aChangeListeners )
+ rListener->changesOccurred( aEvent );
+}
+
+
+void ControlModelContainerBase::implUpdateGroupStructure()
+{
+ if ( mbGroupsUpToDate )
+ // nothing to do
+ return;
+
+ // conditions for a group:
+ // * all elements of the group are radio buttons
+ // * all elements of the group are on the same dialog page
+ // * in the overall control order (determined by the tab index), all elements are subsequent
+
+ maGroups.clear();
+
+ const Sequence< Reference< XControlModel > > aControlModels = getControlModels();
+
+ // in extreme we have as much groups as controls
+ maGroups.reserve( aControlModels.getLength() );
+
+ GroupingMachineState eState = eLookingForGroup; // the current state of our machine
+ Reference< XServiceInfo > xModelSI; // for checking for a radio button
+ AllGroups::iterator aCurrentGroup = maGroups.end(); // the group which we're currently building
+ sal_Int32 nCurrentGroupStep = -1; // the step which all controls of the current group belong to
+
+
+ for ( const Reference< XControlModel >& rControlModel : aControlModels )
+ {
+ // we'll need this in every state
+ xModelSI.set(rControlModel, css::uno::UNO_QUERY);
+ // is it a radio button?
+ bool bIsRadioButton = xModelSI.is() && xModelSI->supportsService( "com.sun.star.awt.UnoControlRadioButtonModel" );
+
+ switch ( eState )
+ {
+ case eLookingForGroup:
+ {
+ if ( !bIsRadioButton )
+ // this is no radio button -> still looking for the beginning of a group
+ continue;
+ // the current model is a radio button
+ // -> we found the beginning of a new group
+ // create the place for this group
+ size_t nGroups = maGroups.size();
+ maGroups.resize( nGroups + 1 );
+ aCurrentGroup = maGroups.begin() + nGroups;
+ // and add the (only, til now) member
+ aCurrentGroup->push_back( rControlModel );
+
+ // get the step which all controls of this group now have to belong to
+ nCurrentGroupStep = lcl_getDialogStep( rControlModel );
+ // new state: looking for further members
+ eState = eExpandingGroup;
+
+ }
+ break;
+
+ case eExpandingGroup:
+ {
+ if ( !bIsRadioButton )
+ { // no radio button -> the group is done
+ aCurrentGroup = maGroups.end();
+ eState = eLookingForGroup;
+ continue;
+ }
+
+ // it is a radio button - is it on the proper page?
+ const sal_Int32 nThisModelStep = lcl_getDialogStep( rControlModel );
+ if ( ( nThisModelStep == nCurrentGroupStep ) // the current button is on the same dialog page
+ || ( 0 == nThisModelStep ) // the current button appears on all pages
+ )
+ {
+ // -> it belongs to the same group
+ aCurrentGroup->push_back( rControlModel );
+ // state still is eExpandingGroup - we're looking for further elements
+ eState = eExpandingGroup;
+
+ continue;
+ }
+
+ // it's a radio button, but on a different page
+ // -> we open a new group for it
+
+
+ // open a new group
+ size_t nGroups = maGroups.size();
+ maGroups.resize( nGroups + 1 );
+ aCurrentGroup = maGroups.begin() + nGroups;
+ // and add the (only, til now) member
+ aCurrentGroup->push_back( rControlModel );
+
+ nCurrentGroupStep = nThisModelStep;
+
+ // state is the same: we still are looking for further elements of the current group
+ eState = eExpandingGroup;
+ }
+ break;
+ }
+ }
+
+ mbGroupsUpToDate = true;
+}
+
+
+void SAL_CALL ControlModelContainerBase::propertyChange( const PropertyChangeEvent& _rEvent )
+{
+ SolarMutexGuard aGuard;
+
+ DBG_ASSERT( _rEvent.PropertyName == "TabIndex",
+ "ControlModelContainerBase::propertyChange: not listening for this property!" );
+
+ // the accessor for the changed element
+ OUString sAccessor;
+ UnoControlModelHolderVector::const_iterator aPos =
+ ::std::find_if(
+ maModels.begin(), maModels.end(),
+ CompareControlModel( Reference< XControlModel >( _rEvent.Source, UNO_QUERY ) )
+ );
+ OSL_ENSURE( maModels.end() != aPos, "ControlModelContainerBase::propertyChange: don't know this model!" );
+ if ( maModels.end() != aPos )
+ sAccessor = aPos->second;
+
+ // our groups are not up-to-date
+ mbGroupsUpToDate = false;
+
+ // notify
+ implNotifyTabModelChange( sAccessor );
+}
+
+
+void SAL_CALL ControlModelContainerBase::disposing( const EventObject& /*rEvent*/ )
+{
+}
+
+
+void ControlModelContainerBase::startControlListening( const Reference< XControlModel >& _rxChildModel )
+{
+ SolarMutexGuard aGuard;
+
+ Reference< XPropertySet > xModelProps( _rxChildModel, UNO_QUERY );
+ Reference< XPropertySetInfo > xPSI;
+ if ( xModelProps.is() )
+ xPSI = xModelProps->getPropertySetInfo();
+
+ if ( xPSI.is() && xPSI->hasPropertyByName( getTabIndexPropertyName() ) )
+ xModelProps->addPropertyChangeListener( getTabIndexPropertyName(), this );
+}
+
+
+void ControlModelContainerBase::stopControlListening( const Reference< XControlModel >& _rxChildModel )
+{
+ SolarMutexGuard aGuard;
+
+ Reference< XPropertySet > xModelProps( _rxChildModel, UNO_QUERY );
+ Reference< XPropertySetInfo > xPSI;
+ if ( xModelProps.is() )
+ xPSI = xModelProps->getPropertySetInfo();
+
+ if ( xPSI.is() && xPSI->hasPropertyByName( getTabIndexPropertyName() ) )
+ xModelProps->removePropertyChangeListener( getTabIndexPropertyName(), this );
+}
+
+
+// = class ResourceListener
+
+
+ResourceListener::ResourceListener(
+ const Reference< util::XModifyListener >& rListener ) :
+ m_xListener( rListener ),
+ m_bListening( false )
+{
+}
+
+ResourceListener::~ResourceListener()
+{
+}
+
+// XInterface
+Any SAL_CALL ResourceListener::queryInterface( const Type& rType )
+{
+ Any a = ::cppu::queryInterface(
+ rType ,
+ static_cast< XModifyListener* >( this ),
+ static_cast< XEventListener* >( this ));
+
+ if ( a.hasValue() )
+ return a;
+
+ return OWeakObject::queryInterface( rType );
+}
+
+void SAL_CALL ResourceListener::acquire() noexcept
+{
+ OWeakObject::acquire();
+}
+
+void SAL_CALL ResourceListener::release() noexcept
+{
+ OWeakObject::release();
+}
+
+void ResourceListener::startListening(
+ const Reference< resource::XStringResourceResolver >& rResource )
+{
+ {
+ // --- SAFE ---
+ std::unique_lock aGuard( m_aMutex );
+ bool bListening( m_bListening );
+ bool bResourceSet( m_xResource.is() );
+ aGuard.unlock();
+ // --- SAFE ---
+
+ if ( bListening && bResourceSet )
+ stopListening();
+
+ // --- SAFE ---
+ aGuard.lock();
+ m_xResource = rResource;
+ aGuard.unlock();
+ // --- SAFE ---
+ }
+
+ if ( !rResource.is() )
+ return;
+
+ try
+ {
+ rResource->addModifyListener( this );
+
+ // --- SAFE ---
+ std::scoped_lock aGuard( m_aMutex );
+ m_bListening = true;
+ // --- SAFE ---
+ }
+ catch (const RuntimeException&)
+ {
+ throw;
+ }
+ catch (const Exception&)
+ {
+ }
+}
+
+void ResourceListener::stopListening()
+{
+ Reference< util::XModifyBroadcaster > xModifyBroadcaster;
+
+ // --- SAFE ---
+ std::unique_lock aGuard( m_aMutex );
+ if ( m_bListening && m_xResource.is() )
+ xModifyBroadcaster = m_xResource;
+ aGuard.unlock();
+ // --- SAFE ---
+
+ if ( !xModifyBroadcaster.is() )
+ return;
+
+ try
+ {
+ // --- SAFE ---
+ aGuard.lock();
+ m_bListening = false;
+ m_xResource.clear();
+ aGuard.unlock();
+ // --- SAFE ---
+
+ xModifyBroadcaster->removeModifyListener( this );
+ }
+ catch (const RuntimeException&)
+ {
+ throw;
+ }
+ catch (const Exception&)
+ {
+ }
+}
+
+// XModifyListener
+void SAL_CALL ResourceListener::modified(
+ const lang::EventObject& aEvent )
+{
+ Reference< util::XModifyListener > xListener;
+
+ // --- SAFE ---
+ std::unique_lock aGuard( m_aMutex );
+ xListener = m_xListener;
+ aGuard.unlock();
+ // --- SAFE ---
+
+ if ( !xListener.is() )
+ return;
+
+ try
+ {
+ xListener->modified( aEvent );
+ }
+ catch (const RuntimeException&)
+ {
+ throw;
+ }
+ catch (const Exception&)
+ {
+ }
+}
+
+// XEventListener
+void SAL_CALL ResourceListener::disposing(
+ const EventObject& Source )
+{
+ Reference< lang::XEventListener > xListener;
+ Reference< resource::XStringResourceResolver > xResource;
+
+ // --- SAFE ---
+ std::unique_lock aGuard( m_aMutex );
+ Reference< XInterface > xIfacRes( m_xResource, UNO_QUERY );
+ Reference< XInterface > xIfacList( m_xListener, UNO_QUERY );
+ aGuard.unlock();
+ // --- SAFE ---
+
+ if ( Source.Source == xIfacRes )
+ {
+ // --- SAFE ---
+ aGuard.lock();
+ m_bListening = false;
+ xResource = m_xResource;
+ xListener = m_xListener;
+ m_xResource.clear();
+ aGuard.unlock();
+ // --- SAFE ---
+
+ if ( xListener.is() )
+ {
+ try
+ {
+ xListener->disposing( Source );
+ }
+ catch (const RuntimeException&)
+ {
+ throw;
+ }
+ catch (const Exception&)
+ {
+ }
+ }
+ }
+ else if ( Source.Source == xIfacList )
+ {
+ // --- SAFE ---
+ aGuard.lock();
+ m_bListening = false;
+ xListener = m_xListener;
+ xResource = m_xResource;
+ m_xResource.clear();
+ m_xListener.clear();
+ aGuard.unlock();
+ // --- SAFE ---
+
+ // Remove ourself as listener from resource resolver
+ if ( xResource.is() )
+ {
+ try
+ {
+ xResource->removeModifyListener( this );
+ }
+ catch (const RuntimeException&)
+ {
+ throw;
+ }
+ catch (const Exception&)
+ {
+ }
+ }
+ }
+}
+
+
+
+ControlContainerBase::ControlContainerBase( const Reference< XComponentContext >& rxContext )
+ :m_xContext(rxContext)
+ ,mbSizeModified(false)
+ ,mbPosModified(false)
+{
+ maComponentInfos.nWidth = 280;
+ maComponentInfos.nHeight = 400;
+ mxListener = new ResourceListener( Reference< util::XModifyListener >(this) );
+}
+
+ControlContainerBase::~ControlContainerBase()
+{
+}
+
+void ControlContainerBase::createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer > & rParentPeer )
+{
+ SolarMutexGuard aGuard;
+ UnoControlContainer::createPeer( rxToolkit, rParentPeer );
+}
+
+void ControlContainerBase::ImplInsertControl( Reference< XControlModel > const & rxModel, const OUString& rName )
+{
+ Reference< XPropertySet > xP( rxModel, UNO_QUERY );
+
+ OUString aDefCtrl;
+ xP->getPropertyValue( GetPropertyName( BASEPROPERTY_DEFAULTCONTROL ) ) >>= aDefCtrl;
+ Reference < XControl > xCtrl( m_xContext->getServiceManager()->createInstanceWithContext(aDefCtrl, m_xContext), UNO_QUERY );
+
+ DBG_ASSERT( xCtrl.is(), "ControlContainerBase::ImplInsertControl: could not create the control!" );
+ if ( xCtrl.is() )
+ {
+ xCtrl->setModel( rxModel );
+ addControl( rName, xCtrl );
+ // will implicitly call addingControl, where we can add the PropertiesChangeListener to the model
+ // (which we formerly did herein)
+ // 08.01.2001 - 96008 - fs@openoffice.org
+
+ ImplSetPosSize( xCtrl );
+ }
+}
+
+void ControlContainerBase::ImplRemoveControl( Reference< XControlModel > const & rxModel )
+{
+ Sequence< Reference< XControl > > aControls = getControls();
+ Reference< XControl > xCtrl = StdTabController::FindControl( aControls, rxModel );
+ if ( xCtrl.is() )
+ {
+ removeControl( xCtrl );
+ try
+ {
+ xCtrl->dispose();
+ }
+ catch (const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+ }
+}
+
+void ControlContainerBase::ImplSetPosSize( Reference< XControl >& rxCtrl )
+{
+ Reference< XPropertySet > xP( rxCtrl->getModel(), UNO_QUERY );
+
+ sal_Int32 nX = 0, nY = 0, nWidth = 0, nHeight = 0;
+ xP->getPropertyValue("PositionX") >>= nX;
+ xP->getPropertyValue("PositionY") >>= nY;
+ xP->getPropertyValue("Width") >>= nWidth;
+ xP->getPropertyValue("Height") >>= nHeight;
+ MapMode aMode( MapUnit::MapAppFont );
+ OutputDevice*pOutDev = Application::GetDefaultDevice();
+ if ( pOutDev )
+ {
+ ::Size aTmp( nX, nY );
+ aTmp = pOutDev->LogicToPixel( aTmp, aMode );
+ nX = aTmp.Width();
+ nY = aTmp.Height();
+ aTmp = ::Size( nWidth, nHeight );
+ aTmp = pOutDev->LogicToPixel( aTmp, aMode );
+ nWidth = aTmp.Width();
+ nHeight = aTmp.Height();
+ }
+ else
+ {
+ Reference< XWindowPeer > xPeer = ImplGetCompatiblePeer();
+ Reference< XDevice > xD( xPeer, UNO_QUERY );
+
+ SimpleFontMetric aFM;
+ FontDescriptor aFD;
+ Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_FONTDESCRIPTOR ) );
+ aVal >>= aFD;
+ if ( !aFD.StyleName.isEmpty() )
+ {
+ Reference< XFont > xFont = xD->getFont( aFD );
+ aFM = xFont->getFontMetric();
+ }
+ else
+ {
+ Reference< XGraphics > xG = xD->createGraphics();
+ aFM = xG->getFontMetric();
+ }
+
+ sal_Int16 nH = aFM.Ascent + aFM.Descent;
+ sal_Int16 nW = nH/2; // calculate average width?!
+
+ nX *= nW;
+ nX /= 4;
+ nWidth *= nW;
+ nWidth /= 4;
+ nY *= nH;
+ nY /= 8;
+ nHeight *= nH;
+ nHeight /= 8;
+ }
+ Reference < XWindow > xW( rxCtrl, UNO_QUERY );
+ xW->setPosSize( nX, nY, nWidth, nHeight, PosSize::POSSIZE );
+}
+
+void ControlContainerBase::dispose()
+{
+ EventObject aEvt;
+ aEvt.Source = static_cast< ::cppu::OWeakObject* >( this );
+ // Notify our listener helper about dispose
+ // --- SAFE ---
+
+ SolarMutexClearableGuard aGuard;
+ Reference< XEventListener > xListener = mxListener;
+ mxListener.clear();
+ aGuard.clear();
+ // --- SAFE ---
+
+ if ( xListener.is() )
+ xListener->disposing( aEvt );
+ UnoControlContainer::dispose();
+}
+
+void SAL_CALL ControlContainerBase::disposing(
+ const EventObject& Source )
+{
+ UnoControlContainer::disposing( Source );
+}
+
+sal_Bool ControlContainerBase::setModel( const Reference< XControlModel >& rxModel )
+{
+ SolarMutexGuard aGuard;
+
+ // destroy the old tab controller, if existent
+ if ( mxTabController.is() )
+ {
+ mxTabController->setModel( nullptr ); // just to be sure, should not be necessary
+ removeTabController( mxTabController );
+ ::comphelper::disposeComponent( mxTabController ); // just to be sure, should not be necessary
+ mxTabController.clear();
+ }
+
+ if ( getModel().is() )
+ {
+ const Sequence< Reference< XControl > > aControls = getControls();
+
+ for ( const Reference< XControl >& rCtrl : aControls )
+ removeControl( rCtrl );
+ // will implicitly call removingControl, which will remove the PropertyChangeListener
+ // (which we formerly did herein)
+ // 08.01.2001 - 96008 - fs@openoffice.org
+
+ Reference< XContainer > xC( getModel(), UNO_QUERY );
+ if ( xC.is() )
+ xC->removeContainerListener( this );
+
+ Reference< XChangesNotifier > xChangeNotifier( getModel(), UNO_QUERY );
+ if ( xChangeNotifier.is() )
+ xChangeNotifier->removeChangesListener( this );
+ }
+
+ bool bRet = UnoControl::setModel( rxModel );
+
+ if ( getModel().is() )
+ {
+ Reference< XNameAccess > xNA( getModel(), UNO_QUERY );
+ if ( xNA.is() )
+ {
+ const Sequence< OUString > aNames = xNA->getElementNames();
+
+ Reference< XControlModel > xCtrlModel;
+ for( const OUString& rName : aNames )
+ {
+ xNA->getByName( rName ) >>= xCtrlModel;
+ ImplInsertControl( xCtrlModel, rName );
+ }
+ }
+
+ Reference< XContainer > xC( getModel(), UNO_QUERY );
+ if ( xC.is() )
+ xC->addContainerListener( this );
+
+ Reference< XChangesNotifier > xChangeNotifier( getModel(), UNO_QUERY );
+ if ( xChangeNotifier.is() )
+ xChangeNotifier->addChangesListener( this );
+ }
+
+ Reference< XTabControllerModel > xTabbing( getModel(), UNO_QUERY );
+ if ( xTabbing.is() )
+ {
+ mxTabController = new StdTabController;
+ mxTabController->setModel( xTabbing );
+ addTabController( mxTabController );
+ }
+ ImplStartListingForResourceEvents();
+
+ return bRet;
+}
+void ControlContainerBase::setDesignMode( sal_Bool bOn )
+{
+ SolarMutexGuard aGuard;
+
+ UnoControl::setDesignMode( bOn );
+
+ Sequence< Reference< XControl > > xCtrls = getControls();
+ for ( Reference< XControl >& rControl : asNonConstRange(xCtrls) )
+ rControl->setDesignMode( bOn );
+
+ // #109067# in design mode the tab controller is not notified about
+ // tab index changes, therefore the tab order must be activated
+ // when switching from design mode to live mode
+ if ( mxTabController.is() && !bOn )
+ mxTabController->activateTabOrder();
+}
+
+void ControlContainerBase::elementInserted( const ContainerEvent& Event )
+{
+ SolarMutexGuard aGuard;
+
+ Reference< XControlModel > xModel;
+ OUString aName;
+
+ Event.Accessor >>= aName;
+ Event.Element >>= xModel;
+ ENSURE_OR_RETURN_VOID( xModel.is(), "ControlContainerBase::elementInserted: illegal element!" );
+ try
+ {
+ ImplInsertControl( xModel, aName );
+ }
+ catch (const RuntimeException&)
+ {
+ throw;
+ }
+ catch (const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+}
+
+void ControlContainerBase::elementRemoved( const ContainerEvent& Event )
+{
+ SolarMutexGuard aGuard;
+
+ Reference< XControlModel > xModel;
+ Event.Element >>= xModel;
+ ENSURE_OR_RETURN_VOID( xModel.is(), "ControlContainerBase::elementRemoved: illegal element!" );
+ try
+ {
+ ImplRemoveControl( xModel );
+ }
+ catch (const RuntimeException&)
+ {
+ throw;
+ }
+ catch (const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+}
+
+void ControlContainerBase::elementReplaced( const ContainerEvent& Event )
+{
+ SolarMutexGuard aGuard;
+
+ Reference< XControlModel > xModel;
+ Event.ReplacedElement >>= xModel;
+ try
+ {
+ OSL_ENSURE( xModel.is(), "ControlContainerBase::elementReplaced: invalid ReplacedElement!" );
+ if ( xModel.is() )
+ ImplRemoveControl( xModel );
+ }
+ catch (const RuntimeException&)
+ {
+ throw;
+ }
+ catch (const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+
+ OUString aName;
+ Event.Accessor >>= aName;
+ Event.Element >>= xModel;
+ ENSURE_OR_RETURN_VOID( xModel.is(), "ControlContainerBase::elementReplaced: invalid new element!" );
+ try
+ {
+ ImplInsertControl( xModel, aName );
+ }
+ catch (const RuntimeException&)
+ {
+ throw;
+ }
+ catch (const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+}
+
+// XPropertiesChangeListener
+void ControlContainerBase::ImplModelPropertiesChanged( const Sequence< PropertyChangeEvent >& rEvents )
+{
+ if( !isDesignMode() && !mbCreatingCompatiblePeer )
+ {
+ auto pEvt = std::find_if(rEvents.begin(), rEvents.end(),
+ [](const PropertyChangeEvent& rEvt) {
+ return rEvt.PropertyName == "PositionX"
+ || rEvt.PropertyName == "PositionY"
+ || rEvt.PropertyName == "Width"
+ || rEvt.PropertyName == "Height";
+ });
+ if (pEvt != rEvents.end())
+ {
+ Reference< XControlModel > xModel( pEvt->Source, UNO_QUERY );
+ bool bOwnModel = xModel.get() == getModel().get();
+ if ( bOwnModel )
+ {
+ if ( !mbPosModified && !mbSizeModified )
+ {
+ // Don't set new pos/size if we get new values from window listener
+ Reference< XControl > xThis(this);
+ ImplSetPosSize( xThis );
+ }
+ }
+ else
+ {
+ Sequence<Reference<XControl> > aControlSequence(getControls());
+ Reference<XControl> aControlRef( StdTabController::FindControl( aControlSequence, xModel ) );
+ ImplSetPosSize( aControlRef );
+ }
+ }
+ }
+
+ UnoControlContainer::ImplModelPropertiesChanged( rEvents );
+}
+
+void ControlContainerBase::addingControl( const Reference< XControl >& _rxControl )
+{
+ SolarMutexGuard aGuard;
+ UnoControlContainer::addingControl( _rxControl );
+
+ if ( !_rxControl.is() )
+ return;
+
+ Reference< XMultiPropertySet > xProps( _rxControl->getModel(), UNO_QUERY );
+ if ( xProps.is() )
+ {
+ const Sequence< OUString > aNames {
+ "PositionX",
+ "PositionY",
+ "Width",
+ "Height"
+ };
+
+ xProps->addPropertiesChangeListener( aNames, this );
+ }
+}
+
+void ControlContainerBase::removingControl( const Reference< XControl >& _rxControl )
+{
+ SolarMutexGuard aGuard;
+ UnoControlContainer::removingControl( _rxControl );
+
+ if ( _rxControl.is() )
+ {
+ Reference< XMultiPropertySet > xProps( _rxControl->getModel(), UNO_QUERY );
+ if ( xProps.is() )
+ xProps->removePropertiesChangeListener( this );
+ }
+
+}
+
+void SAL_CALL ControlContainerBase::changesOccurred( const ChangesEvent& )
+{
+ SolarMutexGuard aGuard;
+ // a tab controller model may have changed
+
+ // #109067# in design mode don't notify the tab controller
+ // about tab index changes
+ if ( mxTabController.is() && !mbDesignMode )
+ mxTabController->activateTabOrder();
+}
+static void lcl_ApplyResolverToNestedContainees( const Reference< resource::XStringResourceResolver >& xStringResourceResolver, const Reference< XControlContainer >& xContainer )
+{
+ OUString aPropName( PROPERTY_RESOURCERESOLVER );
+
+ Any aNewStringResourceResolver;
+ aNewStringResourceResolver <<= xStringResourceResolver;
+
+ Sequence< OUString > aPropNames { aPropName };
+
+ const Sequence< Reference< awt::XControl > > aSeq = xContainer->getControls();
+ for ( const Reference< XControl >& xControl : aSeq )
+ {
+ Reference< XPropertySet > xPropertySet;
+
+ if ( xControl.is() )
+ xPropertySet.set( xControl->getModel(), UNO_QUERY );
+
+ if ( !xPropertySet.is() )
+ continue;
+
+ try
+ {
+ Reference< resource::XStringResourceResolver > xCurrStringResourceResolver;
+ Any aOldValue = xPropertySet->getPropertyValue( aPropName );
+ if ( ( aOldValue >>= xCurrStringResourceResolver )
+ && ( xStringResourceResolver == xCurrStringResourceResolver )
+ )
+ {
+ Reference< XMultiPropertySet > xMultiPropSet( xPropertySet, UNO_QUERY );
+ Reference< XPropertiesChangeListener > xListener( xPropertySet, UNO_QUERY );
+ xMultiPropSet->firePropertiesChangeEvent( aPropNames, xListener );
+ }
+ else
+ xPropertySet->setPropertyValue( aPropName, aNewStringResourceResolver );
+ }
+ catch (const Exception&)
+ {
+ }
+
+ uno::Reference< XControlContainer > xNestedContainer( xControl, uno::UNO_QUERY );
+ if ( xNestedContainer.is() )
+ lcl_ApplyResolverToNestedContainees( xStringResourceResolver, xNestedContainer );
+
+ }
+
+}
+void ControlContainerBase::ImplStartListingForResourceEvents()
+{
+ Reference< resource::XStringResourceResolver > xStringResourceResolver;
+
+ if ( !ImplHasProperty(PROPERTY_RESOURCERESOLVER) )
+ return;
+
+ ImplGetPropertyValue( PROPERTY_RESOURCERESOLVER ) >>= xStringResourceResolver;
+
+ // Add our helper as listener to retrieve notifications about changes
+ Reference< util::XModifyListener > rListener( mxListener );
+ ResourceListener* pResourceListener = static_cast< ResourceListener* >( rListener.get() );
+
+ // resource listener will stop listening if resolver reference is empty
+ if ( pResourceListener )
+ pResourceListener->startListening( xStringResourceResolver );
+ ImplUpdateResourceResolver();
+}
+
+void ControlContainerBase::ImplUpdateResourceResolver()
+{
+ Reference< resource::XStringResourceResolver > xStringResourceResolver;
+
+ if ( !ImplHasProperty(PROPERTY_RESOURCERESOLVER) )
+ return;
+
+ ImplGetPropertyValue(PROPERTY_RESOURCERESOLVER) >>= xStringResourceResolver;
+
+ if ( !xStringResourceResolver.is() )
+ return;
+
+ lcl_ApplyResolverToNestedContainees( xStringResourceResolver, this );
+
+ // propagate resource resolver changes to language dependent props of the dialog
+ Reference< XPropertySet > xPropertySet( getModel(), UNO_QUERY );
+ if ( xPropertySet.is() )
+ {
+ Reference< XMultiPropertySet > xMultiPropSet( xPropertySet, UNO_QUERY );
+ Reference< XPropertiesChangeListener > xListener( xPropertySet, UNO_QUERY );
+ xMultiPropSet->firePropertiesChangeEvent( lcl_getLanguageDependentProperties(), xListener );
+ }
+}
+
+//// ----------------------------------------------------
+//// Helper Method to convert relative url to physical location
+//// ----------------------------------------------------
+
+OUString getPhysicalLocation( const css::uno::Any& rbase, const css::uno::Any& rUrl )
+{
+
+ OUString baseLocation;
+ OUString url;
+
+ rbase >>= baseLocation;
+ rUrl >>= url;
+
+ OUString absoluteURL( url );
+ if ( !url.isEmpty() )
+ {
+ INetURLObject urlObj(baseLocation);
+ urlObj.removeSegment();
+ baseLocation = urlObj.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+
+ const INetURLObject protocolCheck( url );
+ const INetProtocol protocol = protocolCheck.GetProtocol();
+ if ( protocol == INetProtocol::NotValid )
+ {
+ OUString testAbsoluteURL;
+ if ( ::osl::FileBase::E_None == ::osl::FileBase::getAbsoluteFileURL( baseLocation, url, testAbsoluteURL ) )
+ absoluteURL = testAbsoluteURL;
+ }
+ }
+
+ return absoluteURL;
+}
+
+void
+ControlModelContainerBase::updateUserFormChildren( const Reference< XNameContainer >& xAllChildren, const OUString& aName, ChildOperation Operation, const css::uno::Reference< css::awt::XControlModel >& xTarget )
+{
+ if ( Operation < Insert || Operation > Remove )
+ throw IllegalArgumentException();
+
+ if ( !xAllChildren.is() )
+ throw IllegalArgumentException();
+
+ if ( Operation == Remove )
+ {
+ Reference< XControlModel > xOldModel( xAllChildren->getByName( aName ), UNO_QUERY );
+ xAllChildren->removeByName( aName );
+
+ Reference< XNameContainer > xChildContainer( xOldModel, UNO_QUERY );
+ if ( xChildContainer.is() )
+ {
+ Reference< XPropertySet > xProps( xChildContainer, UNO_QUERY );
+ // container control is being removed from this container, reset the
+ // global list of containers
+ if ( xProps.is() )
+ xProps->setPropertyValue( GetPropertyName( BASEPROPERTY_USERFORMCONTAINEES ), uno::Any( uno::Reference< XNameContainer >() ) );
+ const Sequence< OUString > aChildNames = xChildContainer->getElementNames();
+ for ( const auto& rName : aChildNames )
+ updateUserFormChildren( xAllChildren, rName, Operation, Reference< XControlModel > () );
+ }
+ }
+ else if ( Operation == Insert )
+ {
+ xAllChildren->insertByName( aName, uno::Any( xTarget ) );
+ Reference< XNameContainer > xChildContainer( xTarget, UNO_QUERY );
+ if ( xChildContainer.is() )
+ {
+ // container control is being added from this container, reset the
+ // global list of containers to point to the correct global list
+ Reference< XPropertySet > xProps( xChildContainer, UNO_QUERY );
+ if ( xProps.is() )
+ xProps->setPropertyValue( GetPropertyName( BASEPROPERTY_USERFORMCONTAINEES ), uno::Any( xAllChildren ) );
+ const Sequence< OUString > aChildNames = xChildContainer->getElementNames();
+ for ( const auto& rName : aChildNames )
+ {
+ Reference< XControlModel > xChildTarget( xChildContainer->getByName( rName ), UNO_QUERY );
+ updateUserFormChildren( xAllChildren, rName, Operation, xChildTarget );
+ }
+ }
+ }
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/controlmodelcontainerbase_internal.hxx b/toolkit/source/controls/controlmodelcontainerbase_internal.hxx
new file mode 100644
index 000000000..c65cabc8a
--- /dev/null
+++ b/toolkit/source/controls/controlmodelcontainerbase_internal.hxx
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_TOOLKIT_SOURCE_CONTROLS_CONTROLMODELCONTAINERBASE_INTERNAL_HXX
+#define INCLUDED_TOOLKIT_SOURCE_CONTROLS_CONTROLMODELCONTAINERBASE_INTERNAL_HXX
+
+#include <com/sun/star/uno/Any.hxx>
+
+////HELPER
+OUString getPhysicalLocation(const css::uno::Any& rbase, const css::uno::Any& rUrl);
+
+#endif // INCLUDED_TOOLKIT_SOURCE_CONTROLS_CONTROLMODELCONTAINERBASE_INTERNAL_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/dialogcontrol.cxx b/toolkit/source/controls/dialogcontrol.cxx
new file mode 100644
index 000000000..67ee3bcc6
--- /dev/null
+++ b/toolkit/source/controls/dialogcontrol.cxx
@@ -0,0 +1,1244 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <algorithm>
+
+#include <sal/types.h>
+#include <vcl/svapp.hxx>
+#include <controls/dialogcontrol.hxx>
+#include <controls/geometrycontrolmodel.hxx>
+#include <toolkit/helper/property.hxx>
+#include <helper/servicenames.hxx>
+#include <com/sun/star/awt/PosSize.hpp>
+#include <com/sun/star/awt/WindowAttribute.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/weak.hxx>
+#include <tools/debug.hxx>
+#include <comphelper/sequence.hxx>
+#include <vcl/outdev.hxx>
+
+#include <vcl/image.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <unordered_map>
+
+#include <vcl/tabctrl.hxx>
+#include <toolkit/controls/unocontrols.hxx>
+
+#include <awt/vclxwindows.hxx>
+#include <helper/unopropertyarrayhelper.hxx>
+#include "controlmodelcontainerbase_internal.hxx"
+#include <mutex>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::util;
+
+constexpr OUStringLiteral PROPERTY_DIALOGSOURCEURL = u"DialogSourceURL";
+constexpr OUStringLiteral PROPERTY_IMAGEURL = u"ImageURL";
+constexpr OUStringLiteral PROPERTY_GRAPHIC = u"Graphic";
+
+
+// we probably will need both a hash of control models and hash of controls
+// => use some template magic
+
+namespace {
+
+template< typename T >
+class SimpleNamedThingContainer : public ::cppu::WeakImplHelper< container::XNameContainer >
+{
+ std::unordered_map< OUString, Reference< T > > things;
+ std::mutex m_aMutex;
+public:
+ // css::container::XNameContainer, XNameReplace, XNameAccess
+ virtual void SAL_CALL replaceByName( const OUString& aName, const Any& aElement ) override
+ {
+ std::scoped_lock aGuard( m_aMutex );
+ auto it = things.find( aName );
+ if ( it == things.end() )
+ throw NoSuchElementException();
+ Reference< T > xElement;
+ if ( ! ( aElement >>= xElement ) )
+ throw IllegalArgumentException();
+ it->second = xElement;
+ }
+ virtual Any SAL_CALL getByName( const OUString& aName ) override
+ {
+ std::scoped_lock aGuard( m_aMutex );
+ auto it = things.find( aName );
+ if ( it == things.end() )
+ throw NoSuchElementException();
+ return uno::Any( it->second );
+ }
+ virtual Sequence< OUString > SAL_CALL getElementNames( ) override
+ {
+ std::scoped_lock aGuard( m_aMutex );
+ return comphelper::mapKeysToSequence( things );
+ }
+ virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override
+ {
+ std::scoped_lock aGuard( m_aMutex );
+ return ( things.find( aName ) != things.end() );
+ }
+ virtual void SAL_CALL insertByName( const OUString& aName, const Any& aElement ) override
+ {
+ std::scoped_lock aGuard( m_aMutex );
+ auto it = things.find( aName );
+ if ( it != things.end() )
+ throw ElementExistException();
+ Reference< T > xElement;
+ if ( ! ( aElement >>= xElement ) )
+ throw IllegalArgumentException();
+ things[ aName ] = xElement;
+ }
+ virtual void SAL_CALL removeByName( const OUString& aName ) override
+ {
+ std::scoped_lock aGuard( m_aMutex );
+ if ( things.erase( aName ) == 0 )
+ throw NoSuchElementException();
+ }
+ virtual Type SAL_CALL getElementType( ) override
+ {
+ return cppu::UnoType<T>::get();
+ }
+ virtual sal_Bool SAL_CALL hasElements( ) override
+ {
+ std::scoped_lock aGuard( m_aMutex );
+ return !things.empty();
+ }
+};
+
+class UnoControlDialogModel : public ControlModelContainerBase
+{
+protected:
+ css::uno::Reference< css::graphic::XGraphicObject > mxGrfObj;
+ css::uno::Any ImplGetDefaultValue( sal_uInt16 nPropId ) const override;
+ ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+ // ::cppu::OPropertySetHelper
+ void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const css::uno::Any& rValue ) override;
+public:
+ explicit UnoControlDialogModel( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
+ UnoControlDialogModel( const UnoControlDialogModel& rModel );
+
+ rtl::Reference<UnoControlModel> Clone() const override;
+ // css::beans::XMultiPropertySet
+ css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+
+ // css::io::XPersistObject
+ OUString SAL_CALL getServiceName() override;
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName() override
+ { return "stardiv.Toolkit.UnoControlDialogModel"; }
+
+ css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
+ {
+ auto s(ControlModelContainerBase::getSupportedServiceNames());
+ s.realloc(s.getLength() + 2);
+ auto ps = s.getArray();
+ ps[s.getLength() - 2] = "com.sun.star.awt.UnoControlDialogModel";
+ ps[s.getLength() - 1] = "stardiv.vcl.controlmodel.Dialog";
+ return s;
+ }
+};
+
+UnoControlDialogModel::UnoControlDialogModel( const Reference< XComponentContext >& rxContext )
+ :ControlModelContainerBase( rxContext )
+{
+ ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
+// ImplRegisterProperty( BASEPROPERTY_BORDER );
+ ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
+ ImplRegisterProperty( BASEPROPERTY_ENABLED );
+ ImplRegisterProperty( BASEPROPERTY_FONTDESCRIPTOR );
+// ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
+ ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
+ ImplRegisterProperty( BASEPROPERTY_HELPURL );
+ ImplRegisterProperty( BASEPROPERTY_TITLE );
+ ImplRegisterProperty( BASEPROPERTY_SIZEABLE );
+ ImplRegisterProperty( BASEPROPERTY_DESKTOP_AS_PARENT );
+ ImplRegisterProperty( BASEPROPERTY_DECORATION );
+ ImplRegisterProperty( BASEPROPERTY_DIALOGSOURCEURL );
+ ImplRegisterProperty( BASEPROPERTY_GRAPHIC );
+ ImplRegisterProperty( BASEPROPERTY_IMAGEURL );
+ ImplRegisterProperty( BASEPROPERTY_HSCROLL );
+ ImplRegisterProperty( BASEPROPERTY_VSCROLL );
+ ImplRegisterProperty( BASEPROPERTY_SCROLLWIDTH );
+ ImplRegisterProperty( BASEPROPERTY_SCROLLHEIGHT );
+ ImplRegisterProperty( BASEPROPERTY_SCROLLTOP );
+ ImplRegisterProperty( BASEPROPERTY_SCROLLLEFT );
+
+ Any aBool;
+ aBool <<= true;
+ ImplRegisterProperty( BASEPROPERTY_MOVEABLE, aBool );
+ ImplRegisterProperty( BASEPROPERTY_CLOSEABLE, aBool );
+ // #TODO separate class for 'UserForm' ( instead of re-using Dialog ? )
+ uno::Reference< XNameContainer > xNameCont = new SimpleNamedThingContainer< XControlModel >;
+ ImplRegisterProperty( BASEPROPERTY_USERFORMCONTAINEES, uno::Any( xNameCont ) );
+}
+
+UnoControlDialogModel::UnoControlDialogModel( const UnoControlDialogModel& rModel )
+ : ControlModelContainerBase( rModel )
+{
+ // need to clone BASEPROPERTY_USERFORMCONTAINEES too
+ Reference< XNameContainer > xSrcNameCont( const_cast< UnoControlDialogModel& >(rModel).getPropertyValue( GetPropertyName( BASEPROPERTY_USERFORMCONTAINEES ) ), UNO_QUERY );
+ Reference<XNameContainer > xNameCont( new SimpleNamedThingContainer< XControlModel > );
+
+ const uno::Sequence< OUString > sNames = xSrcNameCont->getElementNames();
+ for ( OUString const & name : sNames )
+ {
+ if ( xSrcNameCont->hasByName( name ) )
+ xNameCont->insertByName( name, xSrcNameCont->getByName( name ) );
+ }
+ setFastPropertyValue_NoBroadcast( BASEPROPERTY_USERFORMCONTAINEES, Any( xNameCont ) );
+}
+
+rtl::Reference<UnoControlModel> UnoControlDialogModel::Clone() const
+{
+ // clone the container itself
+ rtl::Reference<UnoControlDialogModel> pClone = new UnoControlDialogModel( *this );
+
+ Clone_Impl(*pClone);
+
+ return pClone;
+}
+
+
+OUString UnoControlDialogModel::getServiceName( )
+{
+ return "stardiv.vcl.controlmodel.Dialog";
+}
+
+Any UnoControlDialogModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ Any aAny;
+
+ switch ( nPropId )
+ {
+ case BASEPROPERTY_DEFAULTCONTROL:
+ aAny <<= OUString::createFromAscii( szServiceName_UnoControlDialog );
+ break;
+ case BASEPROPERTY_SCROLLWIDTH:
+ case BASEPROPERTY_SCROLLHEIGHT:
+ case BASEPROPERTY_SCROLLTOP:
+ case BASEPROPERTY_SCROLLLEFT:
+ aAny <<= sal_Int32(0);
+ break;
+ default:
+ aAny = UnoControlModel::ImplGetDefaultValue( nPropId );
+ }
+
+ return aAny;
+}
+
+::cppu::IPropertyArrayHelper& UnoControlDialogModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+// XMultiPropertySet
+Reference< XPropertySetInfo > UnoControlDialogModel::getPropertySetInfo( )
+{
+ static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+void SAL_CALL UnoControlDialogModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const css::uno::Any& rValue )
+{
+ ControlModelContainerBase::setFastPropertyValue_NoBroadcast( nHandle, rValue );
+ try
+ {
+ if ( nHandle == BASEPROPERTY_IMAGEURL && ImplHasProperty( BASEPROPERTY_GRAPHIC ) )
+ {
+ OUString sImageURL;
+ uno::Reference<graphic::XGraphic> xGraphic;
+ if (rValue >>= sImageURL)
+ {
+ setPropertyValue(
+ GetPropertyName(BASEPROPERTY_GRAPHIC),
+ uno::Any(ImageHelper::getGraphicAndGraphicObjectFromURL_nothrow(
+ mxGrfObj, sImageURL)));
+ }
+ else if (rValue >>= xGraphic)
+ {
+ setPropertyValue("Graphic", uno::Any(xGraphic));
+ }
+ }
+ }
+ catch( const css::uno::Exception& )
+ {
+ OSL_ENSURE( false, "UnoControlDialogModel::setFastPropertyValue_NoBroadcast: caught an exception while setting ImageURL properties!" );
+ }
+}
+
+}
+
+
+// = class UnoDialogControl
+
+
+UnoDialogControl::UnoDialogControl( const uno::Reference< uno::XComponentContext >& rxContext )
+ :UnoDialogControl_Base( rxContext )
+ ,maTopWindowListeners( *this )
+ ,mbWindowListener(false)
+{
+ maComponentInfos.nWidth = 300;
+ maComponentInfos.nHeight = 450;
+ }
+
+UnoDialogControl::~UnoDialogControl()
+{
+}
+
+OUString UnoDialogControl::GetComponentServiceName() const
+{
+
+ bool bDecoration( true );
+ ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_DECORATION )) >>= bDecoration;
+ if ( bDecoration )
+ return "Dialog";
+ else
+ return "TabPage";
+}
+
+void UnoDialogControl::dispose()
+{
+ SolarMutexGuard aGuard;
+
+ EventObject aEvt;
+ aEvt.Source = static_cast< ::cppu::OWeakObject* >( this );
+ maTopWindowListeners.disposeAndClear( aEvt );
+ ControlContainerBase::dispose();
+}
+
+void SAL_CALL UnoDialogControl::disposing(
+ const EventObject& Source )
+{
+ ControlContainerBase::disposing( Source );
+}
+
+sal_Bool UnoDialogControl::setModel( const Reference< XControlModel >& rxModel )
+{
+ // #Can we move all the Resource stuff to the ControlContainerBase ?
+ SolarMutexGuard aGuard;
+ bool bRet = ControlContainerBase::setModel( rxModel );
+ ImplStartListingForResourceEvents();
+ return bRet;
+}
+
+void UnoDialogControl::createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer > & rParentPeer )
+{
+ SolarMutexGuard aGuard;
+
+ UnoControlContainer::createPeer( rxToolkit, rParentPeer );
+
+ Reference < XTopWindow > xTW( getPeer(), UNO_QUERY );
+ if ( !xTW.is() )
+ return;
+
+ xTW->setMenuBar( mxMenuBar );
+
+ if ( !mbWindowListener )
+ {
+ Reference< XWindowListener > xWL(this);
+ addWindowListener( xWL );
+ mbWindowListener = true;
+ }
+
+ if ( maTopWindowListeners.getLength() )
+ xTW->addTopWindowListener( &maTopWindowListeners );
+ // there must be a better way than doing this, we can't
+ // process the scrolltop & scrollleft in XDialog because
+ // the children haven't been added when those props are applied
+ ImplSetPeerProperty( GetPropertyName( BASEPROPERTY_SCROLLTOP ), ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_SCROLLTOP ) ) );
+ ImplSetPeerProperty( GetPropertyName( BASEPROPERTY_SCROLLLEFT ), ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_SCROLLLEFT ) ) );
+}
+
+OUString UnoDialogControl::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoDialogControl";
+}
+
+sal_Bool UnoDialogControl::supportsService(OUString const & ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+css::uno::Sequence<OUString> UnoDialogControl::getSupportedServiceNames()
+{
+ return css::uno::Sequence<OUString>{
+ "com.sun.star.awt.UnoControlDialog",
+ "stardiv.vcl.control.Dialog"};
+}
+
+void UnoDialogControl::PrepareWindowDescriptor( css::awt::WindowDescriptor& rDesc )
+{
+ UnoControlContainer::PrepareWindowDescriptor( rDesc );
+ bool bDecoration( true );
+ ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_DECORATION )) >>= bDecoration;
+ if ( !bDecoration )
+ {
+ // Now we have to manipulate the WindowDescriptor
+ rDesc.WindowAttributes = rDesc.WindowAttributes | css::awt::WindowAttribute::NODECORATION;
+ }
+
+ // We have to set the graphic property before the peer
+ // will be created. Otherwise the properties will be copied
+ // into the peer via propertiesChangeEvents. As the order of
+ // can lead to overwrites we have to set the graphic property
+ // before the propertiesChangeEvents are sent!
+ OUString aImageURL;
+ Reference< graphic::XGraphic > xGraphic;
+ if (( ImplGetPropertyValue( PROPERTY_IMAGEURL ) >>= aImageURL ) &&
+ ( !aImageURL.isEmpty() ))
+ {
+ OUString absoluteUrl = getPhysicalLocation(ImplGetPropertyValue(PROPERTY_DIALOGSOURCEURL), uno::Any(aImageURL));
+ xGraphic = ImageHelper::getGraphicFromURL_nothrow( absoluteUrl );
+ ImplSetPropertyValue( PROPERTY_GRAPHIC, uno::Any( xGraphic ), true );
+ }
+}
+
+void UnoDialogControl::addTopWindowListener( const Reference< XTopWindowListener >& rxListener )
+{
+ maTopWindowListeners.addInterface( rxListener );
+ if( getPeer().is() && maTopWindowListeners.getLength() == 1 )
+ {
+ Reference < XTopWindow > xTW( getPeer(), UNO_QUERY );
+ xTW->addTopWindowListener( &maTopWindowListeners );
+ }
+}
+
+void UnoDialogControl::removeTopWindowListener( const Reference< XTopWindowListener >& rxListener )
+{
+ if( getPeer().is() && maTopWindowListeners.getLength() == 1 )
+ {
+ Reference < XTopWindow > xTW( getPeer(), UNO_QUERY );
+ xTW->removeTopWindowListener( &maTopWindowListeners );
+ }
+ maTopWindowListeners.removeInterface( rxListener );
+}
+
+void UnoDialogControl::toFront( )
+{
+ SolarMutexGuard aGuard;
+ if ( getPeer().is() )
+ {
+ Reference< XTopWindow > xTW( getPeer(), UNO_QUERY );
+ if( xTW.is() )
+ xTW->toFront();
+ }
+}
+
+void UnoDialogControl::toBack( )
+{
+ SolarMutexGuard aGuard;
+ if ( getPeer().is() )
+ {
+ Reference< XTopWindow > xTW( getPeer(), UNO_QUERY );
+ if( xTW.is() )
+ xTW->toBack();
+ }
+}
+
+void UnoDialogControl::setMenuBar( const Reference< XMenuBar >& rxMenuBar )
+{
+ SolarMutexGuard aGuard;
+ mxMenuBar = rxMenuBar;
+ if ( getPeer().is() )
+ {
+ Reference< XTopWindow > xTW( getPeer(), UNO_QUERY );
+ if( xTW.is() )
+ xTW->setMenuBar( mxMenuBar );
+ }
+}
+static ::Size ImplMapPixelToAppFont( OutputDevice const * pOutDev, const ::Size& aSize )
+{
+ ::Size aTmp = pOutDev->PixelToLogic(aSize, MapMode(MapUnit::MapAppFont));
+ return aTmp;
+}
+// css::awt::XWindowListener
+void SAL_CALL UnoDialogControl::windowResized( const css::awt::WindowEvent& e )
+{
+ OutputDevice*pOutDev = Application::GetDefaultDevice();
+ DBG_ASSERT( pOutDev, "Missing Default Device!" );
+ if ( !pOutDev || mbSizeModified )
+ return;
+
+ // Currently we are simply using MapUnit::MapAppFont
+ ::Size aAppFontSize( e.Width, e.Height );
+
+ Reference< XControl > xDialogControl( *this, UNO_QUERY_THROW );
+ Reference< XDevice > xDialogDevice( xDialogControl->getPeer(), UNO_QUERY );
+ OSL_ENSURE( xDialogDevice.is(), "UnoDialogControl::windowResized: no peer, but a windowResized event?" );
+
+ // #i87592 In design mode the drawing layer works with sizes with decoration.
+ // Therefore we have to subtract them before writing back to the properties (model).
+ if ( xDialogDevice.is() && mbDesignMode )
+ {
+ DeviceInfo aDeviceInfo( xDialogDevice->getInfo() );
+ aAppFontSize.AdjustWidth( -(aDeviceInfo.LeftInset + aDeviceInfo.RightInset) );
+ aAppFontSize.AdjustHeight( -(aDeviceInfo.TopInset + aDeviceInfo.BottomInset) );
+ }
+
+ aAppFontSize = ImplMapPixelToAppFont( pOutDev, aAppFontSize );
+
+ // Remember that changes have been done by listener. No need to
+ // update the position because of property change event.
+ mbSizeModified = true;
+ // Properties in a sequence must be sorted!
+ Sequence< OUString > aProps{ "Height", "Width" };
+ Sequence< Any > aValues{
+ Any(sal_Int32(
+ std::clamp(aAppFontSize.Height(), tools::Long(SAL_MIN_INT32), tools::Long(SAL_MAX_INT32)))),
+ Any(sal_Int32(
+ std::clamp(aAppFontSize.Width(), tools::Long(SAL_MIN_INT32), tools::Long(SAL_MAX_INT32))))
+ };
+
+ ImplSetPropertyValues( aProps, aValues, true );
+ mbSizeModified = false;
+
+}
+
+void SAL_CALL UnoDialogControl::windowMoved( const css::awt::WindowEvent& e )
+{
+ OutputDevice*pOutDev = Application::GetDefaultDevice();
+ DBG_ASSERT( pOutDev, "Missing Default Device!" );
+ if ( !pOutDev || mbPosModified )
+ return;
+
+ // Currently we are simply using MapUnit::MapAppFont
+ ::Size aTmp( e.X, e.Y );
+ aTmp = ImplMapPixelToAppFont( pOutDev, aTmp );
+
+ // Remember that changes have been done by listener. No need to
+ // update the position because of property change event.
+ mbPosModified = true;
+ Sequence< OUString > aProps{ "PositionX", "PositionY" };
+ Sequence< Any > aValues{
+ Any(sal_Int32(
+ std::clamp(aTmp.Width(), tools::Long(SAL_MIN_INT32), tools::Long(SAL_MAX_INT32)))),
+ Any(sal_Int32(
+ std::clamp(aTmp.Height(), tools::Long(SAL_MIN_INT32), tools::Long(SAL_MAX_INT32))))
+ };
+
+ ImplSetPropertyValues( aProps, aValues, true );
+ mbPosModified = false;
+
+}
+
+void SAL_CALL UnoDialogControl::windowShown( const EventObject& ) {}
+
+void SAL_CALL UnoDialogControl::windowHidden( const EventObject& ) {}
+
+void SAL_CALL UnoDialogControl::endDialog( ::sal_Int32 i_result )
+{
+ Reference< XDialog2 > xPeerDialog( getPeer(), UNO_QUERY );
+ if ( xPeerDialog.is() )
+ xPeerDialog->endDialog( i_result );
+}
+
+void SAL_CALL UnoDialogControl::setHelpId( const OUString& i_id )
+{
+ Reference< XDialog2 > xPeerDialog( getPeer(), UNO_QUERY );
+ if ( xPeerDialog.is() )
+ xPeerDialog->setHelpId( i_id );
+}
+
+void UnoDialogControl::setTitle( const OUString& Title )
+{
+ SolarMutexGuard aGuard;
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_TITLE ), uno::Any(Title), true );
+}
+
+OUString UnoDialogControl::getTitle()
+{
+ SolarMutexGuard aGuard;
+ return ImplGetPropertyValue_UString( BASEPROPERTY_TITLE );
+}
+
+sal_Int16 UnoDialogControl::execute()
+{
+ SolarMutexGuard aGuard;
+ sal_Int16 nDone = -1;
+ if ( getPeer().is() )
+ {
+ Reference< XDialog > xDlg( getPeer(), UNO_QUERY );
+ if( xDlg.is() )
+ {
+ GetComponentInfos().bVisible = true;
+ nDone = xDlg->execute();
+ GetComponentInfos().bVisible = false;
+ }
+ }
+ return nDone;
+}
+
+void UnoDialogControl::endExecute()
+{
+ SolarMutexGuard aGuard;
+ if ( getPeer().is() )
+ {
+ Reference< XDialog > xDlg( getPeer(), UNO_QUERY );
+ if( xDlg.is() )
+ {
+ xDlg->endExecute();
+ GetComponentInfos().bVisible = false;
+ }
+ }
+}
+
+// XModifyListener
+void SAL_CALL UnoDialogControl::modified(
+ const lang::EventObject& /*rEvent*/ )
+{
+ ImplUpdateResourceResolver();
+}
+
+void UnoDialogControl::ImplModelPropertiesChanged( const Sequence< PropertyChangeEvent >& rEvents )
+{
+ for( const PropertyChangeEvent& rEvt : rEvents )
+ {
+ Reference< XControlModel > xModel( rEvt.Source, UNO_QUERY );
+ bool bOwnModel = xModel.get() == getModel().get();
+ if (bOwnModel && rEvt.PropertyName == "ImageURL" && !ImplHasProperty(BASEPROPERTY_GRAPHIC))
+ {
+ OUString aImageURL;
+ Reference< graphic::XGraphic > xGraphic;
+ if (( ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_IMAGEURL ) ) >>= aImageURL ) &&
+ ( !aImageURL.isEmpty() ))
+ {
+ OUString absoluteUrl = getPhysicalLocation(ImplGetPropertyValue(GetPropertyName(BASEPROPERTY_DIALOGSOURCEURL)), uno::Any(aImageURL));
+ xGraphic = ImageHelper::getGraphicFromURL_nothrow( absoluteUrl );
+ }
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_GRAPHIC), uno::Any( xGraphic ), true );
+ break;
+ }
+ else if (bOwnModel && rEvt.PropertyName == "Graphic")
+ {
+ uno::Reference<graphic::XGraphic> xGraphic;
+ if (ImplGetPropertyValue("Graphic") >>= xGraphic)
+ {
+ ImplSetPropertyValue("Graphic", uno::Any(xGraphic), true);
+ }
+ break;
+ }
+ }
+ ControlContainerBase::ImplModelPropertiesChanged(rEvents);
+}
+
+
+
+UnoMultiPageControl::UnoMultiPageControl( const uno::Reference< uno::XComponentContext >& rxContext ) : ControlContainerBase(rxContext), maTabListeners( *this )
+{
+ maComponentInfos.nWidth = 280;
+ maComponentInfos.nHeight = 400;
+}
+
+UnoMultiPageControl::~UnoMultiPageControl()
+{
+}
+// XTabListener
+
+void SAL_CALL UnoMultiPageControl::inserted( SAL_UNUSED_PARAMETER ::sal_Int32 )
+{
+}
+void SAL_CALL UnoMultiPageControl::removed( SAL_UNUSED_PARAMETER ::sal_Int32 )
+{
+}
+void SAL_CALL UnoMultiPageControl::changed( SAL_UNUSED_PARAMETER ::sal_Int32,
+ SAL_UNUSED_PARAMETER const Sequence< NamedValue >& )
+{
+}
+void SAL_CALL UnoMultiPageControl::activated( ::sal_Int32 ID )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_MULTIPAGEVALUE ), uno::Any( ID ), false );
+
+}
+void SAL_CALL UnoMultiPageControl::deactivated( SAL_UNUSED_PARAMETER ::sal_Int32 )
+{
+}
+void SAL_CALL UnoMultiPageControl::disposing(const EventObject&)
+{
+}
+
+void SAL_CALL UnoMultiPageControl::dispose()
+{
+ lang::EventObject aEvt;
+ aEvt.Source = static_cast<cppu::OWeakObject*>(this);
+ maTabListeners.disposeAndClear( aEvt );
+ ControlContainerBase::dispose();
+}
+
+// css::awt::XSimpleTabController
+::sal_Int32 SAL_CALL UnoMultiPageControl::insertTab()
+{
+ Reference< XSimpleTabController > xMultiPage( getPeer(), UNO_QUERY_THROW );
+ return xMultiPage->insertTab();
+}
+
+void SAL_CALL UnoMultiPageControl::removeTab( ::sal_Int32 ID )
+{
+ Reference< XSimpleTabController > xMultiPage( getPeer(), UNO_QUERY_THROW );
+ xMultiPage->removeTab( ID );
+}
+
+void SAL_CALL UnoMultiPageControl::setTabProps( ::sal_Int32 ID, const Sequence< NamedValue >& Properties )
+{
+ Reference< XSimpleTabController > xMultiPage( getPeer(), UNO_QUERY_THROW );
+ xMultiPage->setTabProps( ID, Properties );
+}
+
+Sequence< NamedValue > SAL_CALL UnoMultiPageControl::getTabProps( ::sal_Int32 ID )
+{
+ Reference< XSimpleTabController > xMultiPage( getPeer(), UNO_QUERY_THROW );
+ return xMultiPage->getTabProps( ID );
+}
+
+void SAL_CALL UnoMultiPageControl::activateTab( ::sal_Int32 ID )
+{
+ Reference< XSimpleTabController > xMultiPage( getPeer(), UNO_QUERY_THROW );
+ xMultiPage->activateTab( ID );
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_MULTIPAGEVALUE ), uno::Any( ID ), true );
+
+}
+
+::sal_Int32 SAL_CALL UnoMultiPageControl::getActiveTabID()
+{
+ Reference< XSimpleTabController > xMultiPage( getPeer(), UNO_QUERY_THROW );
+ return xMultiPage->getActiveTabID();
+}
+
+void SAL_CALL UnoMultiPageControl::addTabListener( const Reference< XTabListener >& Listener )
+{
+ maTabListeners.addInterface( Listener );
+ Reference< XSimpleTabController > xMultiPage( getPeer(), UNO_QUERY );
+ if ( xMultiPage.is() && maTabListeners.getLength() == 1 )
+ xMultiPage->addTabListener( &maTabListeners );
+}
+
+void SAL_CALL UnoMultiPageControl::removeTabListener( const Reference< XTabListener >& Listener )
+{
+ Reference< XSimpleTabController > xMultiPage( getPeer(), UNO_QUERY );
+ if ( xMultiPage.is() && maTabListeners.getLength() == 1 )
+ xMultiPage->removeTabListener( &maTabListeners );
+ maTabListeners.removeInterface( Listener );
+}
+
+IMPL_IMPLEMENTATION_ID( UnoMultiPageControl )
+
+// lang::XTypeProvider
+css::uno::Sequence< css::uno::Type > UnoMultiPageControl::getTypes()
+{
+ static const ::cppu::OTypeCollection aTypeList(
+ cppu::UnoType<css::lang::XTypeProvider>::get(),
+ cppu::UnoType<awt::XSimpleTabController>::get(),
+ cppu::UnoType<awt::XTabListener>::get(),
+ ControlContainerBase::getTypes()
+ );
+ return aTypeList.getTypes();
+}
+
+// uno::XInterface
+uno::Any UnoMultiPageControl::queryAggregation( const uno::Type & rType )
+{
+ uno::Any aRet = ::cppu::queryInterface( rType,
+ static_cast< awt::XTabListener* >(this),
+ static_cast< awt::XSimpleTabController* >(this) );
+ return (aRet.hasValue() ? aRet : ControlContainerBase::queryAggregation( rType ));
+}
+
+OUString UnoMultiPageControl::GetComponentServiceName() const
+{
+ bool bDecoration( true );
+ ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_DECORATION )) >>= bDecoration;
+ if ( bDecoration )
+ return "tabcontrol";
+ // Hopefully we can tweak the tabcontrol to display without tabs
+ return "tabcontrolnotabs";
+}
+
+void UnoMultiPageControl::bindPage( const uno::Reference< awt::XControl >& _rxControl )
+{
+ uno::Reference< awt::XWindowPeer > xPage( _rxControl->getPeer() );
+ uno::Reference< awt::XSimpleTabController > xTabCntrl( getPeer(), uno::UNO_QUERY );
+ uno::Reference< beans::XPropertySet > xProps( _rxControl->getModel(), uno::UNO_QUERY );
+
+ VCLXTabPage* pXPage = dynamic_cast< VCLXTabPage* >( xPage.get() );
+ TabPage* pPage = pXPage ? pXPage->getTabPage() : nullptr;
+ if ( xTabCntrl.is() && pPage )
+ {
+ VCLXMultiPage* pXTab = dynamic_cast< VCLXMultiPage* >( xTabCntrl.get() );
+ if ( pXTab )
+ {
+ OUString sTitle;
+ xProps->getPropertyValue( GetPropertyName( BASEPROPERTY_TITLE ) ) >>= sTitle;
+ pXTab->insertTab( pPage, sTitle);
+ }
+ }
+
+}
+
+void UnoMultiPageControl::createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer > & rParentPeer )
+{
+ SolarMutexGuard aSolarGuard;
+
+ UnoControlContainer::createPeer( rxToolkit, rParentPeer );
+
+ const uno::Sequence< uno::Reference< awt::XControl > > aCtrls = getControls();
+ for( const auto& rCtrl : aCtrls )
+ bindPage( rCtrl );
+ sal_Int32 nActiveTab(0);
+ Reference< XPropertySet > xMultiProps( getModel(), UNO_QUERY );
+ xMultiProps->getPropertyValue( GetPropertyName( BASEPROPERTY_MULTIPAGEVALUE ) ) >>= nActiveTab;
+
+ uno::Reference< awt::XSimpleTabController > xTabCntrl( getPeer(), uno::UNO_QUERY );
+ if ( xTabCntrl.is() )
+ {
+ xTabCntrl->addTabListener( this );
+ if ( nActiveTab && aCtrls.hasElements() ) // Ensure peer is initialise with correct activated tab
+ {
+ xTabCntrl->activateTab( nActiveTab );
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_MULTIPAGEVALUE ), uno::Any( nActiveTab ), true );
+ }
+ }
+}
+
+void UnoMultiPageControl::impl_createControlPeerIfNecessary( const uno::Reference< awt::XControl >& _rxControl)
+{
+ OSL_PRECOND( _rxControl.is(), "UnoMultiPageControl::impl_createControlPeerIfNecessary: invalid control, this will crash!" );
+
+ // if the container already has a peer, then also create a peer for the control
+ uno::Reference< awt::XWindowPeer > xMyPeer( getPeer() );
+
+ if( xMyPeer.is() )
+ {
+ _rxControl->createPeer( nullptr, xMyPeer );
+ bindPage( _rxControl );
+ ImplActivateTabControllers();
+ }
+
+}
+
+// ------------- UnoMultiPageModel -----------------
+
+UnoMultiPageModel::UnoMultiPageModel( const Reference< XComponentContext >& rxContext ) : ControlModelContainerBase( rxContext )
+{
+ ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
+ ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_ENABLEVISIBLE );
+ ImplRegisterProperty( BASEPROPERTY_ENABLED );
+
+ ImplRegisterProperty( BASEPROPERTY_FONTDESCRIPTOR );
+ ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
+ ImplRegisterProperty( BASEPROPERTY_HELPURL );
+ ImplRegisterProperty( BASEPROPERTY_SIZEABLE );
+ //ImplRegisterProperty( BASEPROPERTY_DIALOGSOURCEURL );
+ ImplRegisterProperty( BASEPROPERTY_MULTIPAGEVALUE );
+ ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
+ ImplRegisterProperty( BASEPROPERTY_USERFORMCONTAINEES );
+
+ Any aBool;
+ aBool <<= true;
+ ImplRegisterProperty( BASEPROPERTY_MOVEABLE, aBool );
+ ImplRegisterProperty( BASEPROPERTY_CLOSEABLE, aBool );
+ ImplRegisterProperty( BASEPROPERTY_DECORATION, aBool );
+ // MultiPage Control has the tab stop property. And the default value is True.
+ ImplRegisterProperty( BASEPROPERTY_TABSTOP, aBool );
+
+ uno::Reference< XNameContainer > xNameCont = new SimpleNamedThingContainer< XControlModel >;
+ ImplRegisterProperty( BASEPROPERTY_USERFORMCONTAINEES, uno::Any( xNameCont ) );
+}
+
+UnoMultiPageModel::~UnoMultiPageModel()
+{
+}
+
+rtl::Reference<UnoControlModel> UnoMultiPageModel::Clone() const
+{
+ // clone the container itself
+ rtl::Reference<UnoMultiPageModel> pClone = new UnoMultiPageModel( *this );
+ Clone_Impl( *pClone );
+ return pClone;
+}
+
+OUString UnoMultiPageModel::getServiceName()
+{
+ return "com.sun.star.awt.UnoMultiPageModel";
+}
+
+uno::Any UnoMultiPageModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
+ {
+ return uno::Any( OUString( "com.sun.star.awt.UnoControlMultiPage" ) );
+ }
+ return ControlModelContainerBase::ImplGetDefaultValue( nPropId );
+}
+
+::cppu::IPropertyArrayHelper& UnoMultiPageModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+// beans::XMultiPropertySet
+uno::Reference< beans::XPropertySetInfo > UnoMultiPageModel::getPropertySetInfo( )
+{
+ static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+void UnoMultiPageModel::insertByName( const OUString& aName, const Any& aElement )
+{
+ Reference< XServiceInfo > xInfo;
+ aElement >>= xInfo;
+
+ if ( !xInfo.is() )
+ throw IllegalArgumentException();
+
+ // Only a Page model can be inserted into the multipage
+ if ( !xInfo->supportsService( "com.sun.star.awt.UnoPageModel" ) )
+ throw IllegalArgumentException();
+
+ return ControlModelContainerBase::insertByName( aName, aElement );
+}
+
+
+sal_Bool SAL_CALL UnoMultiPageModel::getGroupControl( )
+{
+ return true;
+}
+
+
+
+UnoPageControl::UnoPageControl( const uno::Reference< uno::XComponentContext >& rxContext ) : ControlContainerBase(rxContext)
+{
+ maComponentInfos.nWidth = 280;
+ maComponentInfos.nHeight = 400;
+}
+
+UnoPageControl::~UnoPageControl()
+{
+}
+
+OUString UnoPageControl::GetComponentServiceName() const
+{
+ return "tabpage";
+}
+
+
+// ------------- UnoPageModel -----------------
+
+UnoPageModel::UnoPageModel( const Reference< XComponentContext >& rxContext ) : ControlModelContainerBase( rxContext )
+{
+ ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
+ ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_ENABLED );
+ ImplRegisterProperty( BASEPROPERTY_ENABLEVISIBLE );
+
+ ImplRegisterProperty( BASEPROPERTY_FONTDESCRIPTOR );
+ ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
+ ImplRegisterProperty( BASEPROPERTY_HELPURL );
+ ImplRegisterProperty( BASEPROPERTY_TITLE );
+ ImplRegisterProperty( BASEPROPERTY_SIZEABLE );
+ ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
+ ImplRegisterProperty( BASEPROPERTY_USERFORMCONTAINEES );
+// ImplRegisterProperty( BASEPROPERTY_DIALOGSOURCEURL );
+
+ Any aBool;
+ aBool <<= true;
+ ImplRegisterProperty( BASEPROPERTY_MOVEABLE, aBool );
+ ImplRegisterProperty( BASEPROPERTY_CLOSEABLE, aBool );
+ //ImplRegisterProperty( BASEPROPERTY_TABSTOP, aBool );
+
+ uno::Reference< XNameContainer > xNameCont = new SimpleNamedThingContainer< XControlModel >;
+ ImplRegisterProperty( BASEPROPERTY_USERFORMCONTAINEES, uno::Any( xNameCont ) );
+}
+
+UnoPageModel::~UnoPageModel()
+{
+}
+
+rtl::Reference<UnoControlModel> UnoPageModel::Clone() const
+{
+ // clone the container itself
+ rtl::Reference<UnoPageModel> pClone = new UnoPageModel( *this );
+ Clone_Impl( *pClone );
+ return pClone;
+}
+
+OUString UnoPageModel::getServiceName()
+{
+ return "com.sun.star.awt.UnoPageModel";
+}
+
+uno::Any UnoPageModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
+ {
+ return uno::Any( OUString( "com.sun.star.awt.UnoControlPage" ) );
+ }
+ return ControlModelContainerBase::ImplGetDefaultValue( nPropId );
+}
+
+::cppu::IPropertyArrayHelper& UnoPageModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+// beans::XMultiPropertySet
+uno::Reference< beans::XPropertySetInfo > UnoPageModel::getPropertySetInfo( )
+{
+ static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+
+sal_Bool SAL_CALL UnoPageModel::getGroupControl( )
+{
+ return false;
+}
+
+// Frame control
+
+
+
+UnoFrameControl::UnoFrameControl( const uno::Reference< uno::XComponentContext >& rxContext ) : ControlContainerBase(rxContext)
+{
+ maComponentInfos.nWidth = 280;
+ maComponentInfos.nHeight = 400;
+}
+
+UnoFrameControl::~UnoFrameControl()
+{
+}
+
+OUString UnoFrameControl::GetComponentServiceName() const
+{
+ return "frame";
+}
+
+void UnoFrameControl::ImplSetPosSize( Reference< XControl >& rxCtrl )
+{
+ bool bOwnCtrl = false;
+ OUString sTitle;
+ if ( rxCtrl.get() == Reference<XControl>( this ).get() )
+ bOwnCtrl = true;
+ Reference< XPropertySet > xProps( getModel(), UNO_QUERY );
+ //xProps->getPropertyValue( GetPropertyName( BASEPROPERTY_TITLE ) ) >>= sTitle;
+ xProps->getPropertyValue( GetPropertyName( BASEPROPERTY_LABEL ) ) >>= sTitle;
+
+ ControlContainerBase::ImplSetPosSize( rxCtrl );
+ Reference < XWindow > xW( rxCtrl, UNO_QUERY );
+ if ( bOwnCtrl || !xW.is() || sTitle.isEmpty() )
+ return;
+
+ awt::Rectangle aSizePos = xW->getPosSize();
+
+ sal_Int32 nX = aSizePos.X, nY = aSizePos.Y, nWidth = aSizePos.Width, nHeight = aSizePos.Height;
+ // Retrieve the values set by the base class
+ OutputDevice*pOutDev = Application::GetDefaultDevice();
+ if ( pOutDev )
+ {
+ // Adjust Y based on height of Title
+ ::tools::Rectangle aRect = pOutDev->GetTextRect( {}, sTitle );
+ nY = nY + ( aRect.GetHeight() / 2 );
+ }
+ else
+ {
+ Reference< XWindowPeer > xPeer = ImplGetCompatiblePeer();
+ Reference< XDevice > xD( xPeer, UNO_QUERY );
+
+ SimpleFontMetric aFM;
+ FontDescriptor aFD;
+ Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_FONTDESCRIPTOR ) );
+
+ aVal >>= aFD;
+ if ( !aFD.StyleName.isEmpty() )
+ {
+ Reference< XFont > xFont = xD->getFont( aFD );
+ aFM = xFont->getFontMetric();
+ }
+ else
+ {
+ Reference< XGraphics > xG = xD->createGraphics();
+ aFM = xG->getFontMetric();
+ }
+
+ sal_Int16 nH = aFM.Ascent + aFM.Descent;
+ // offset y based on height of font ( not sure if my guess at the correct calculation is correct here )
+ nY = nY + ( nH / 8); // how do I test this
+ }
+ xW->setPosSize( nX, nY, nWidth, nHeight, PosSize::POSSIZE );
+}
+
+// ------------- UnoFrameModel -----------------
+
+UnoFrameModel::UnoFrameModel( const Reference< XComponentContext >& rxContext ) : ControlModelContainerBase( rxContext )
+{
+ ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
+ ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_ENABLED );
+ ImplRegisterProperty( BASEPROPERTY_ENABLEVISIBLE );
+ ImplRegisterProperty( BASEPROPERTY_FONTDESCRIPTOR );
+ ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
+ ImplRegisterProperty( BASEPROPERTY_HELPURL );
+ ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
+ ImplRegisterProperty( BASEPROPERTY_LABEL );
+ ImplRegisterProperty( BASEPROPERTY_WRITING_MODE );
+ ImplRegisterProperty( BASEPROPERTY_CONTEXT_WRITING_MODE );
+ ImplRegisterProperty( BASEPROPERTY_USERFORMCONTAINEES );
+ ImplRegisterProperty( BASEPROPERTY_HSCROLL );
+ ImplRegisterProperty( BASEPROPERTY_VSCROLL );
+ ImplRegisterProperty( BASEPROPERTY_SCROLLWIDTH );
+ ImplRegisterProperty( BASEPROPERTY_SCROLLHEIGHT );
+ ImplRegisterProperty( BASEPROPERTY_SCROLLTOP );
+ ImplRegisterProperty( BASEPROPERTY_SCROLLLEFT );
+
+
+ uno::Reference< XNameContainer > xNameCont = new SimpleNamedThingContainer< XControlModel >;
+ ImplRegisterProperty( BASEPROPERTY_USERFORMCONTAINEES, uno::Any( xNameCont ) );
+}
+
+UnoFrameModel::~UnoFrameModel()
+{
+}
+
+rtl::Reference<UnoControlModel> UnoFrameModel::Clone() const
+{
+ // clone the container itself
+ rtl::Reference<UnoFrameModel> pClone = new UnoFrameModel( *this );
+ Clone_Impl( *pClone );
+ return pClone;
+}
+
+OUString UnoFrameModel::getServiceName()
+{
+ return "com.sun.star.awt.UnoFrameModel";
+}
+
+uno::Any UnoFrameModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ switch ( nPropId )
+ {
+ case BASEPROPERTY_DEFAULTCONTROL:
+ {
+ return uno::Any( OUString( "com.sun.star.awt.UnoControlFrame" ) );
+ }
+ case BASEPROPERTY_SCROLLWIDTH:
+ case BASEPROPERTY_SCROLLHEIGHT:
+ case BASEPROPERTY_SCROLLTOP:
+ case BASEPROPERTY_SCROLLLEFT:
+ return uno::Any( sal_Int32(0) );
+ case BASEPROPERTY_USERFORMCONTAINEES:
+ {
+ uno::Reference< XNameContainer > xNameCont = new SimpleNamedThingContainer< XControlModel >;
+ return Any( xNameCont );
+ }
+ }
+ return ControlModelContainerBase::ImplGetDefaultValue( nPropId );
+}
+
+::cppu::IPropertyArrayHelper& UnoFrameModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+// beans::XMultiPropertySet
+uno::Reference< beans::XPropertySetInfo > UnoFrameModel::getPropertySetInfo( )
+{
+ static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlDialogModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new OGeometryControlModel<UnoControlDialogModel>(context));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoDialogControl_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoDialogControl(context));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoMultiPageControl_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoMultiPageControl(context));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoMultiPageModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoMultiPageModel(context));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoPageControl_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoPageControl(context));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoPageModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoPageModel(context));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoFrameControl_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoFrameControl(context));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoFrameModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoFrameModel(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/eventcontainer.cxx b/toolkit/source/controls/eventcontainer.cxx
new file mode 100644
index 000000000..1b57e984d
--- /dev/null
+++ b/toolkit/source/controls/eventcontainer.cxx
@@ -0,0 +1,179 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <cppuhelper/factory.hxx>
+
+#include <controls/eventcontainer.hxx>
+#include <com/sun/star/script/ScriptEventDescriptor.hpp>
+
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::container;
+using namespace com::sun::star::registry;
+using namespace com::sun::star::script;
+using namespace cppu;
+
+namespace toolkit
+{
+
+// Methods XElementAccess
+Type ScriptEventContainer::getElementType()
+{
+ return mType;
+}
+
+sal_Bool ScriptEventContainer::hasElements()
+{
+ return !mHashMap.empty();
+}
+
+// Methods XNameAccess
+Any ScriptEventContainer::getByName( const OUString& aName )
+{
+ NameContainerNameMap::iterator aIt = mHashMap.find( aName );
+ if( aIt == mHashMap.end() )
+ {
+ throw NoSuchElementException();
+ }
+ sal_Int32 iHashResult = (*aIt).second;
+ Any aRetAny = mValues[ iHashResult ];
+ return aRetAny;
+}
+
+Sequence< OUString > ScriptEventContainer::getElementNames()
+{
+ return mNames;
+}
+
+sal_Bool ScriptEventContainer::hasByName( const OUString& aName )
+{
+ NameContainerNameMap::iterator aIt = mHashMap.find( aName );
+ bool bRet = ( aIt != mHashMap.end() );
+ return bRet;
+}
+
+
+// Methods XNameReplace
+void ScriptEventContainer::replaceByName( const OUString& aName, const Any& aElement )
+{
+ const Type& aAnyType = aElement.getValueType();
+ if( mType != aAnyType )
+ throw IllegalArgumentException();
+
+ NameContainerNameMap::iterator aIt = mHashMap.find( aName );
+ if( aIt == mHashMap.end() )
+ {
+ throw NoSuchElementException();
+ }
+ sal_Int32 iHashResult = (*aIt).second;
+ Any aOldElement = mValues[ iHashResult ];
+ mValues[ iHashResult ] = aElement;
+
+ // Fire event
+ ContainerEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.Element = aElement;
+ aEvent.ReplacedElement = aOldElement;
+ aEvent.Accessor <<= aName;
+ maContainerListeners.elementReplaced( aEvent );
+}
+
+
+// Methods XNameContainer
+void ScriptEventContainer::insertByName( const OUString& aName, const Any& aElement )
+{
+ const Type& aAnyType = aElement.getValueType();
+ if( mType != aAnyType )
+ throw IllegalArgumentException();
+
+ NameContainerNameMap::iterator aIt = mHashMap.find( aName );
+ if( aIt != mHashMap.end() )
+ {
+ throw ElementExistException();
+ }
+
+ sal_Int32 nCount = mNames.getLength();
+ mNames.realloc( nCount + 1 );
+ mValues.resize( nCount + 1 );
+ mNames.getArray()[ nCount ] = aName;
+ mValues[ nCount ] = aElement;
+ mHashMap[ aName ] = nCount;
+
+ // Fire event
+ ContainerEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.Element = aElement;
+ aEvent.Accessor <<= aName;
+ maContainerListeners.elementInserted( aEvent );
+}
+
+void ScriptEventContainer::removeByName( const OUString& Name )
+{
+ NameContainerNameMap::iterator aIt = mHashMap.find( Name );
+ if( aIt == mHashMap.end() )
+ {
+ throw NoSuchElementException();
+ }
+
+ sal_Int32 iHashResult = (*aIt).second;
+ Any aOldElement = mValues[ iHashResult ];
+
+ // Fire event
+ ContainerEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.Element = aOldElement;
+ aEvent.Accessor <<= Name;
+ maContainerListeners.elementRemoved( aEvent );
+
+ mHashMap.erase( aIt );
+ sal_Int32 iLast = mNames.getLength() - 1;
+ if( iLast != iHashResult )
+ {
+ OUString* pNames = mNames.getArray();
+ pNames[ iHashResult ] = pNames[ iLast ];
+ mValues[ iHashResult ] = mValues[ iLast ];
+ mHashMap[ pNames[ iHashResult ] ] = iHashResult;
+ }
+ mNames.realloc( iLast );
+ mValues.resize( iLast );
+}
+
+// Methods XContainer
+void ScriptEventContainer::addContainerListener( const css::uno::Reference< css::container::XContainerListener >& l )
+{
+ maContainerListeners.addInterface( l );
+}
+
+void ScriptEventContainer::removeContainerListener( const css::uno::Reference< css::container::XContainerListener >& l )
+{
+ maContainerListeners.removeInterface( l );
+}
+
+
+ScriptEventContainer::ScriptEventContainer()
+ : mType( cppu::UnoType<ScriptEventDescriptor>::get() ),
+ maContainerListeners( *this )
+{
+}
+
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/filectrl.cxx b/toolkit/source/controls/filectrl.cxx
new file mode 100644
index 000000000..68fa61a02
--- /dev/null
+++ b/toolkit/source/controls/filectrl.cxx
@@ -0,0 +1,244 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <controls/filectrl.hxx>
+
+#include <com/sun/star/ui/dialogs/FilePicker.hpp>
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+#include <comphelper/processfactory.hxx>
+#include <osl/file.h>
+#include <svl/svlresid.hxx>
+#include <svl/svl.hrc>
+#include <tools/diagnose_ex.h>
+#include <tools/urlobj.hxx>
+#include <vcl/toolkit/edit.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::ui;
+
+
+FileControl::FileControl( vcl::Window* pParent, WinBits nStyle ) :
+ Window( pParent, nStyle|WB_DIALOGCONTROL ),
+ maEdit( VclPtr<Edit>::Create(this, (nStyle&(~WB_BORDER))|WB_NOTABSTOP) ),
+ maButton( VclPtr<PushButton>::Create( this, (nStyle&(~WB_BORDER))|WB_NOLIGHTBORDER|WB_NOPOINTERFOCUS|WB_NOTABSTOP ) ),
+ maButtonText( SvlResId(STR_FILECTRL_BUTTONTEXT) ),
+ mnInternalFlags( FileControlMode_Internal::ORIGINALBUTTONTEXT )
+{
+ maButton->SetClickHdl( LINK( this, FileControl, ButtonHdl ) );
+
+ maButton->Show();
+ maEdit->Show();
+
+ SetCompoundControl( true );
+
+ SetStyle( ImplInitStyle( GetStyle() ) );
+}
+
+
+WinBits FileControl::ImplInitStyle( WinBits nStyle )
+{
+ if ( !( nStyle & WB_NOTABSTOP ) )
+ {
+ maEdit->SetStyle( (maEdit->GetStyle()|WB_TABSTOP)&(~WB_NOTABSTOP) );
+ maButton->SetStyle( (maButton->GetStyle()|WB_TABSTOP)&(~WB_NOTABSTOP) );
+ }
+ else
+ {
+ maEdit->SetStyle( (maEdit->GetStyle()|WB_NOTABSTOP)&(~WB_TABSTOP) );
+ maButton->SetStyle( (maButton->GetStyle()|WB_NOTABSTOP)&(~WB_TABSTOP) );
+ }
+
+ const WinBits nAlignmentStyle = ( WB_TOP | WB_VCENTER | WB_BOTTOM );
+ maEdit->SetStyle( ( maEdit->GetStyle() & ~nAlignmentStyle ) | ( nStyle & nAlignmentStyle ) );
+
+ if ( !(nStyle & WB_NOGROUP) )
+ nStyle |= WB_GROUP;
+
+ if ( !(nStyle & WB_NOBORDER ) )
+ nStyle |= WB_BORDER;
+
+ nStyle &= ~WB_TABSTOP;
+
+ return nStyle;
+}
+
+
+FileControl::~FileControl()
+{
+ disposeOnce();
+}
+
+void FileControl::dispose()
+{
+ maEdit.disposeAndClear();
+ maButton.disposeAndClear();
+ Window::dispose();
+}
+
+void FileControl::SetText( const OUString& rStr )
+{
+ maEdit->SetText( rStr );
+}
+
+
+OUString FileControl::GetText() const
+{
+ return maEdit->GetText();
+}
+
+
+void FileControl::StateChanged( StateChangedType nType )
+{
+ if ( nType == StateChangedType::Enable )
+ {
+ maEdit->Enable( IsEnabled() );
+ maButton->Enable( IsEnabled() );
+ }
+ else if ( nType == StateChangedType::Zoom )
+ {
+ GetEdit().SetZoom( GetZoom() );
+ GetButton().SetZoom( GetZoom() );
+ }
+ else if ( nType == StateChangedType::Style )
+ {
+ SetStyle( ImplInitStyle( GetStyle() ) );
+ }
+ else if ( nType == StateChangedType::ControlFont )
+ {
+ GetEdit().SetControlFont( GetControlFont() );
+ // Only use height of the button, as in HTML
+ // always Courier is used
+ vcl::Font aFont = GetButton().GetControlFont();
+ aFont.SetFontSize( GetControlFont().GetFontSize() );
+ GetButton().SetControlFont( aFont );
+ }
+ else if ( nType == StateChangedType::ControlForeground )
+ {
+ GetEdit().SetControlForeground( GetControlForeground() );
+ GetButton().SetControlForeground( GetControlForeground() );
+ }
+ else if ( nType == StateChangedType::ControlBackground )
+ {
+ GetEdit().SetControlBackground( GetControlBackground() );
+ GetButton().SetControlBackground( GetControlBackground() );
+ }
+ Window::StateChanged( nType );
+}
+
+
+void FileControl::Resize()
+{
+ static const tools::Long ButtonBorder = 10;
+
+ if( mnInternalFlags & FileControlMode_Internal::INRESIZE )
+ return;
+ mnInternalFlags |= FileControlMode_Internal::INRESIZE;//InResize = sal_True
+
+ Size aOutSz = GetOutputSizePixel();
+ tools::Long nButtonTextWidth = maButton->GetTextWidth( maButtonText );
+ if ( !(mnInternalFlags & FileControlMode_Internal::ORIGINALBUTTONTEXT) ||
+ ( nButtonTextWidth < aOutSz.Width()/3 ) )
+ {
+ maButton->SetText( maButtonText );
+ }
+ else
+ {
+ OUString aSmallText( "..." );
+ maButton->SetText( aSmallText );
+ nButtonTextWidth = maButton->GetTextWidth( aSmallText );
+ }
+
+ tools::Long nButtonWidth = nButtonTextWidth+ButtonBorder;
+ maEdit->setPosSizePixel( 0, 0, aOutSz.Width()-nButtonWidth, aOutSz.Height() );
+ maButton->setPosSizePixel( aOutSz.Width()-nButtonWidth, 0, nButtonWidth, aOutSz.Height() );
+
+ mnInternalFlags &= ~FileControlMode_Internal::INRESIZE; //InResize = sal_False
+}
+
+
+void FileControl::GetFocus()
+{
+ if (!maEdit || maEdit->isDisposed())
+ return;
+ maEdit->GrabFocus();
+}
+
+void FileControl::SetEditModifyHdl( const Link<Edit&,void>& rLink )
+{
+ if (!maEdit || maEdit->isDisposed())
+ return;
+ maEdit->SetModifyHdl(rLink);
+}
+
+void FileControl::Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags )
+{
+ WinBits nOldEditStyle = GetEdit().GetStyle();
+ if ( GetStyle() & WB_BORDER )
+ GetEdit().SetStyle( nOldEditStyle|WB_BORDER );
+ Size aOrigSize(GetEdit().GetSizePixel());
+ GetEdit().SetSizePixel(GetSizePixel());
+ GetEdit().Draw( pDev, rPos, nFlags );
+ GetEdit().SetSizePixel(aOrigSize);
+ if ( GetStyle() & WB_BORDER )
+ GetEdit().SetStyle( nOldEditStyle );
+}
+
+IMPL_LINK_NOARG(FileControl, ButtonHdl, Button*, void)
+{
+ try
+ {
+ Reference< XComponentContext > xContext = comphelper::getProcessComponentContext();
+ Reference < dialogs::XFilePicker3 > xFilePicker = dialogs::FilePicker::createWithMode( xContext, dialogs::TemplateDescription::FILEOPEN_SIMPLE );
+ // transform the system notation text into a file URL
+ OUString sSystemNotation = GetText(), sFileURL;
+ oslFileError nError = osl_getFileURLFromSystemPath( sSystemNotation.pData, &sFileURL.pData );
+ if ( nError == osl_File_E_INVAL )
+ sFileURL = GetText(); // #97709# Maybe URL is already a file URL...
+
+ //#90430# Check if URL is really a file URL
+ OUString aTmp;
+ if ( osl_getSystemPathFromFileURL( sFileURL.pData, &aTmp.pData ) == osl_File_E_None )
+ {
+ // initially set this directory
+ xFilePicker->setDisplayDirectory( sFileURL );
+ }
+
+ if ( xFilePicker->execute() )
+ {
+ Sequence < OUString > aPathSeq = xFilePicker->getSelectedFiles();
+
+ if ( aPathSeq.hasElements() )
+ {
+ OUString aNewText = aPathSeq[0];
+ INetURLObject aObj( aNewText );
+ if ( aObj.GetProtocol() == INetProtocol::File )
+ aNewText = aObj.PathToFileName();
+ SetText( aNewText );
+ maEdit->GetModifyHdl().Call( *maEdit );
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "toolkit", "FileControl::ImplBrowseFile: caught an exception while executing the file picker!" );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/formattedcontrol.cxx b/toolkit/source/controls/formattedcontrol.cxx
new file mode 100644
index 000000000..6bf71b5c5
--- /dev/null
+++ b/toolkit/source/controls/formattedcontrol.cxx
@@ -0,0 +1,476 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <controls/formattedcontrol.hxx>
+#include <toolkit/helper/property.hxx>
+
+#include <com/sun/star/awt/XVclWindowPeer.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/util/NumberFormatter.hpp>
+#include <com/sun/star/util/NumberFormatsSupplier.hpp>
+
+#include <tools/diagnose_ex.h>
+#include <comphelper/processfactory.hxx>
+#include <osl/diagnose.h>
+
+#include <helper/unopropertyarrayhelper.hxx>
+#include <mutex>
+
+namespace toolkit
+{
+
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::awt;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::util;
+
+
+ namespace
+ {
+
+ std::mutex& getDefaultFormatsMutex()
+ {
+ static std::mutex s_aDefaultFormatsMutex;
+ return s_aDefaultFormatsMutex;
+ }
+
+ Reference< XNumberFormatsSupplier > s_xDefaultFormats;
+ bool s_bTriedCreation = false;
+ oslInterlockedCount s_refCount(0);
+
+ const Reference< XNumberFormatsSupplier >& lcl_getDefaultFormats_throw()
+ {
+ std::scoped_lock aGuard( getDefaultFormatsMutex() );
+
+ if ( !s_xDefaultFormats.is() && !s_bTriedCreation )
+ {
+ s_bTriedCreation = true;
+ s_xDefaultFormats = NumberFormatsSupplier::createWithDefaultLocale( ::comphelper::getProcessComponentContext() );
+ }
+ if ( !s_xDefaultFormats.is() )
+ throw RuntimeException();
+
+ return s_xDefaultFormats;
+ }
+
+ void lcl_registerDefaultFormatsClient()
+ {
+ osl_atomic_increment( &s_refCount );
+ }
+
+ void lcl_revokeDefaultFormatsClient()
+ {
+ Reference< XNumberFormatsSupplier > xReleasePotentialLastReference;
+ {
+ std::scoped_lock aGuard( getDefaultFormatsMutex() );
+ if ( 0 != osl_atomic_decrement( &s_refCount ) )
+ return;
+
+ xReleasePotentialLastReference = std::move(s_xDefaultFormats);
+ s_bTriedCreation = false;
+ }
+ xReleasePotentialLastReference.clear();
+ }
+ }
+
+
+ // = UnoControlFormattedFieldModel
+
+
+ UnoControlFormattedFieldModel::UnoControlFormattedFieldModel( const Reference< XComponentContext >& rxContext )
+ :UnoControlModel( rxContext )
+ ,m_bRevokedAsClient( false )
+ ,m_bSettingValueAndText( false )
+ {
+ ImplRegisterProperty( BASEPROPERTY_ALIGN );
+ ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_BORDER );
+ ImplRegisterProperty( BASEPROPERTY_BORDERCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
+ ImplRegisterProperty( BASEPROPERTY_EFFECTIVE_DEFAULT );
+ ImplRegisterProperty( BASEPROPERTY_EFFECTIVE_VALUE );
+ ImplRegisterProperty( BASEPROPERTY_EFFECTIVE_MAX );
+ ImplRegisterProperty( BASEPROPERTY_EFFECTIVE_MIN );
+ ImplRegisterProperty( BASEPROPERTY_ENABLED );
+ ImplRegisterProperty( BASEPROPERTY_ENABLEVISIBLE );
+ ImplRegisterProperty( BASEPROPERTY_FONTDESCRIPTOR );
+ ImplRegisterProperty( BASEPROPERTY_FORMATKEY );
+ ImplRegisterProperty( BASEPROPERTY_FORMATSSUPPLIER );
+ ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
+ ImplRegisterProperty( BASEPROPERTY_HELPURL );
+ ImplRegisterProperty( BASEPROPERTY_MAXTEXTLEN );
+ ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
+ ImplRegisterProperty( BASEPROPERTY_REPEAT );
+ ImplRegisterProperty( BASEPROPERTY_REPEAT_DELAY );
+ ImplRegisterProperty( BASEPROPERTY_READONLY );
+ ImplRegisterProperty( BASEPROPERTY_SPIN );
+ ImplRegisterProperty( BASEPROPERTY_STRICTFORMAT );
+ ImplRegisterProperty( BASEPROPERTY_TABSTOP );
+ ImplRegisterProperty( BASEPROPERTY_TEXT );
+ ImplRegisterProperty( BASEPROPERTY_TEXTCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_HIDEINACTIVESELECTION );
+ ImplRegisterProperty( BASEPROPERTY_ENFORCE_FORMAT );
+ ImplRegisterProperty( BASEPROPERTY_VERTICALALIGN );
+ ImplRegisterProperty( BASEPROPERTY_WRITING_MODE );
+ ImplRegisterProperty( BASEPROPERTY_CONTEXT_WRITING_MODE );
+ ImplRegisterProperty( BASEPROPERTY_MOUSE_WHEEL_BEHAVIOUR );
+
+ Any aTreatAsNumber;
+ aTreatAsNumber <<= true;
+ ImplRegisterProperty( BASEPROPERTY_TREATASNUMBER, aTreatAsNumber );
+
+ lcl_registerDefaultFormatsClient();
+ }
+
+
+ UnoControlFormattedFieldModel::~UnoControlFormattedFieldModel()
+ {
+ }
+
+
+ OUString UnoControlFormattedFieldModel::getServiceName()
+ {
+ return "stardiv.vcl.controlmodel.FormattedField";
+ }
+
+
+ void SAL_CALL UnoControlFormattedFieldModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue )
+ {
+ UnoControlModel::setFastPropertyValue_NoBroadcast( nHandle, rValue );
+
+ switch ( nHandle )
+ {
+ case BASEPROPERTY_EFFECTIVE_VALUE:
+ if ( !m_bSettingValueAndText )
+ impl_updateTextFromValue_nothrow();
+ break;
+ case BASEPROPERTY_FORMATSSUPPLIER:
+ impl_updateCachedFormatter_nothrow();
+ impl_updateTextFromValue_nothrow();
+ break;
+ case BASEPROPERTY_FORMATKEY:
+ impl_updateCachedFormatKey_nothrow();
+ impl_updateTextFromValue_nothrow();
+ break;
+ }
+ }
+
+
+ void UnoControlFormattedFieldModel::impl_updateTextFromValue_nothrow()
+ {
+ if ( !m_xCachedFormatter.is() )
+ impl_updateCachedFormatter_nothrow();
+ if ( !m_xCachedFormatter.is() )
+ return;
+
+ try
+ {
+ Any aEffectiveValue;
+ getFastPropertyValue( aEffectiveValue, BASEPROPERTY_EFFECTIVE_VALUE );
+
+ OUString sStringValue;
+ if ( !( aEffectiveValue >>= sStringValue ) )
+ {
+ double nDoubleValue(0);
+ if ( aEffectiveValue >>= nDoubleValue )
+ {
+ sal_Int32 nFormatKey( 0 );
+ if ( m_aCachedFormat.hasValue() )
+ m_aCachedFormat >>= nFormatKey;
+ sStringValue = m_xCachedFormatter->convertNumberToString( nFormatKey, nDoubleValue );
+ }
+ }
+
+ Reference< XPropertySet > xThis( *this, UNO_QUERY );
+ xThis->setPropertyValue( GetPropertyName( BASEPROPERTY_TEXT ), Any( sStringValue ) );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+ }
+
+
+ void UnoControlFormattedFieldModel::impl_updateCachedFormatter_nothrow()
+ {
+ Any aFormatsSupplier;
+ getFastPropertyValue( aFormatsSupplier, BASEPROPERTY_FORMATSSUPPLIER );
+ try
+ {
+ Reference< XNumberFormatsSupplier > xSupplier( aFormatsSupplier, UNO_QUERY );
+ if ( !xSupplier.is() )
+ xSupplier = lcl_getDefaultFormats_throw();
+
+ if ( !m_xCachedFormatter.is() )
+ {
+ m_xCachedFormatter.set(
+ NumberFormatter::create(::comphelper::getProcessComponentContext()),
+ UNO_QUERY_THROW
+ );
+ }
+ m_xCachedFormatter->attachNumberFormatsSupplier( xSupplier );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+ }
+
+
+ void UnoControlFormattedFieldModel::impl_updateCachedFormatKey_nothrow()
+ {
+ Any aFormatKey;
+ getFastPropertyValue( aFormatKey, BASEPROPERTY_FORMATKEY );
+ m_aCachedFormat = aFormatKey;
+ }
+
+
+ void UnoControlFormattedFieldModel::dispose( )
+ {
+ UnoControlModel::dispose();
+
+ ::osl::MutexGuard aGuard( GetMutex() );
+ if ( !m_bRevokedAsClient )
+ {
+ lcl_revokeDefaultFormatsClient();
+ m_bRevokedAsClient = true;
+ }
+ }
+
+
+ void UnoControlFormattedFieldModel::ImplNormalizePropertySequence( const sal_Int32 _nCount, sal_Int32* _pHandles,
+ Any* _pValues, sal_Int32* _pValidHandles ) const
+ {
+ ImplEnsureHandleOrder( _nCount, _pHandles, _pValues, BASEPROPERTY_EFFECTIVE_VALUE, BASEPROPERTY_TEXT );
+
+ UnoControlModel::ImplNormalizePropertySequence( _nCount, _pHandles, _pValues, _pValidHandles );
+ }
+
+
+ namespace
+ {
+ class ResetFlagOnExit
+ {
+ private:
+ bool& m_rFlag;
+
+ public:
+ explicit ResetFlagOnExit( bool& _rFlag )
+ :m_rFlag( _rFlag )
+ {
+ }
+ ~ResetFlagOnExit()
+ {
+ m_rFlag = false;
+ }
+ };
+ }
+
+
+ void SAL_CALL UnoControlFormattedFieldModel::setPropertyValues( const Sequence< OUString >& _rPropertyNames, const Sequence< Any >& _rValues )
+ {
+ bool bSettingValue = false;
+ bool bSettingText = false;
+ for ( auto const & propertyName : _rPropertyNames )
+ {
+ if ( BASEPROPERTY_EFFECTIVE_VALUE == GetPropertyId( propertyName ) )
+ bSettingValue = true;
+
+ if ( BASEPROPERTY_TEXT == GetPropertyId( propertyName ) )
+ bSettingText = true;
+ }
+
+ m_bSettingValueAndText = ( bSettingValue && bSettingText );
+ ResetFlagOnExit aResetFlag( m_bSettingValueAndText );
+ UnoControlModel::setPropertyValues( _rPropertyNames, _rValues );
+ }
+
+
+ sal_Bool UnoControlFormattedFieldModel::convertFastPropertyValue(
+ Any& rConvertedValue, Any& rOldValue, sal_Int32 nPropId,
+ const Any& rValue )
+ {
+ if ( BASEPROPERTY_EFFECTIVE_DEFAULT == nPropId && rValue.hasValue() )
+ {
+ double dVal = 0;
+ bool bStreamed = (rValue >>= dVal);
+ if ( bStreamed )
+ {
+ rConvertedValue <<= dVal;
+ }
+ else
+ {
+ sal_Int32 nVal = 0;
+ bStreamed = (rValue >>= nVal);
+ if ( bStreamed )
+ {
+ rConvertedValue <<= static_cast<double>(nVal);
+ }
+ else
+ {
+ OUString sVal;
+ bStreamed = (rValue >>= sVal);
+ if ( bStreamed )
+ {
+ rConvertedValue <<= sVal;
+ }
+ }
+ }
+
+ if ( bStreamed )
+ {
+ getFastPropertyValue( rOldValue, nPropId );
+ return !CompareProperties( rConvertedValue, rOldValue );
+ }
+
+ throw IllegalArgumentException(
+ ("Unable to convert the given value for the property "
+ + GetPropertyName(static_cast<sal_uInt16>(nPropId))
+ + " (double, integer, or string expected)."),
+ static_cast< XPropertySet* >(this),
+ 1);
+ }
+
+ return UnoControlModel::convertFastPropertyValue( rConvertedValue, rOldValue, nPropId, rValue );
+ }
+
+
+ Any UnoControlFormattedFieldModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+ {
+ Any aReturn;
+ switch (nPropId)
+ {
+ case BASEPROPERTY_DEFAULTCONTROL: aReturn <<= OUString("stardiv.vcl.control.FormattedField"); break;
+
+ case BASEPROPERTY_TREATASNUMBER: aReturn <<= true; break;
+
+ case BASEPROPERTY_EFFECTIVE_DEFAULT:
+ case BASEPROPERTY_EFFECTIVE_VALUE:
+ case BASEPROPERTY_EFFECTIVE_MAX:
+ case BASEPROPERTY_EFFECTIVE_MIN:
+ case BASEPROPERTY_FORMATKEY:
+ case BASEPROPERTY_FORMATSSUPPLIER:
+ // (void)
+ break;
+
+ default : aReturn = UnoControlModel::ImplGetDefaultValue( nPropId ); break;
+ }
+
+ return aReturn;
+ }
+
+
+ ::cppu::IPropertyArrayHelper& UnoControlFormattedFieldModel::getInfoHelper()
+ {
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+ }
+
+ // beans::XMultiPropertySet
+
+ Reference< XPropertySetInfo > UnoControlFormattedFieldModel::getPropertySetInfo( )
+ {
+ static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+ }
+
+ OUString UnoControlFormattedFieldModel::getImplementationName()
+ {
+ return "stardiv.Toolkit.UnoControlFormattedFieldModel";
+ }
+
+ css::uno::Sequence<OUString>
+ UnoControlFormattedFieldModel::getSupportedServiceNames()
+ {
+ auto s(UnoControlModel::getSupportedServiceNames());
+ s.realloc(s.getLength() + 2);
+ auto ps = s.getArray();
+ ps[s.getLength() - 2] = "com.sun.star.awt.UnoControlFormattedFieldModel";
+ ps[s.getLength() - 1] = "stardiv.vcl.controlmodel.FormattedField";
+ return s;
+ }
+
+ // = UnoFormattedFieldControl
+
+
+ UnoFormattedFieldControl::UnoFormattedFieldControl()
+ {
+ }
+
+
+ OUString UnoFormattedFieldControl::GetComponentServiceName() const
+ {
+ return "FormattedField";
+ }
+
+
+ void UnoFormattedFieldControl::textChanged(const TextEvent& e)
+ {
+ Reference< XVclWindowPeer > xPeer(getPeer(), UNO_QUERY);
+ OSL_ENSURE(xPeer.is(), "UnoFormattedFieldControl::textChanged : what kind of peer do I have ?");
+
+ Sequence< OUString > aNames{ GetPropertyName( BASEPROPERTY_EFFECTIVE_VALUE ),
+ GetPropertyName( BASEPROPERTY_TEXT ) };
+
+ Sequence< Any > aValues{ xPeer->getProperty( aNames[0] ),
+ xPeer->getProperty( aNames[1] ) };
+
+ ImplSetPropertyValues( aNames, aValues, false );
+
+ if ( GetTextListeners().getLength() )
+ GetTextListeners().textChanged( e );
+ }
+
+ OUString UnoFormattedFieldControl::getImplementationName()
+ {
+ return "stardiv.Toolkit.UnoFormattedFieldControl";
+ }
+
+ css::uno::Sequence<OUString>
+ UnoFormattedFieldControl::getSupportedServiceNames()
+ {
+ auto s(UnoEditControl::getSupportedServiceNames());
+ s.realloc(s.getLength() + 2);
+ auto ps = s.getArray();
+ ps[s.getLength() - 2] = "com.sun.star.awt.UnoControlFormattedField";
+ ps[s.getLength() - 1] = "stardiv.vcl.control.FormattedField";
+ return s;
+ }
+} // namespace toolkit
+
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlFormattedFieldModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new toolkit::UnoControlFormattedFieldModel(context));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoFormattedFieldControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new toolkit::UnoFormattedFieldControl());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/geometrycontrolmodel.cxx b/toolkit/source/controls/geometrycontrolmodel.cxx
new file mode 100644
index 000000000..c201d9b15
--- /dev/null
+++ b/toolkit/source/controls/geometrycontrolmodel.cxx
@@ -0,0 +1,608 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <controls/geometrycontrolmodel.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/resource/XStringResourceResolver.hpp>
+#include <osl/diagnose.h>
+#include <comphelper/sequence.hxx>
+#include <controls/eventcontainer.hxx>
+#include <toolkit/helper/property.hxx>
+#include <algorithm>
+#include <functional>
+
+
+#define GCM_PROPERTY_ID_POS_X 1
+#define GCM_PROPERTY_ID_POS_Y 2
+#define GCM_PROPERTY_ID_WIDTH 3
+#define GCM_PROPERTY_ID_HEIGHT 4
+#define GCM_PROPERTY_ID_NAME 5
+#define GCM_PROPERTY_ID_TABINDEX 6
+#define GCM_PROPERTY_ID_STEP 7
+#define GCM_PROPERTY_ID_TAG 8
+#define GCM_PROPERTY_ID_RESOURCERESOLVER 9
+
+constexpr OUStringLiteral GCM_PROPERTY_POS_X = u"PositionX";
+constexpr OUStringLiteral GCM_PROPERTY_POS_Y = u"PositionY";
+constexpr OUStringLiteral GCM_PROPERTY_WIDTH = u"Width";
+constexpr OUStringLiteral GCM_PROPERTY_HEIGHT = u"Height";
+constexpr OUStringLiteral GCM_PROPERTY_NAME = u"Name";
+constexpr OUStringLiteral GCM_PROPERTY_TABINDEX = u"TabIndex";
+constexpr OUStringLiteral GCM_PROPERTY_STEP = u"Step";
+constexpr OUStringLiteral GCM_PROPERTY_TAG = u"Tag";
+constexpr OUStringLiteral GCM_PROPERTY_RESOURCERESOLVER = u"ResourceResolver";
+
+#define DEFAULT_ATTRIBS() PropertyAttribute::BOUND | PropertyAttribute::TRANSIENT
+
+
+// namespace toolkit
+// {
+
+
+ using namespace ::com::sun::star;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::util;
+ using namespace ::com::sun::star::container;
+ using namespace ::comphelper;
+
+
+ //= OGeometryControlModel_Base
+
+
+ OGeometryControlModel_Base::OGeometryControlModel_Base(css::uno::XAggregation* _pAggregateInstance)
+ :OPropertySetAggregationHelper( m_aBHelper )
+ ,OPropertyContainer( m_aBHelper )
+ ,OGCM_Base( m_aMutex )
+ ,m_nPosX(0)
+ ,m_nPosY(0)
+ ,m_nWidth(0)
+ ,m_nHeight(0)
+ ,m_nTabIndex(-1)
+ ,m_nStep(0)
+ ,m_bCloneable(false)
+ {
+ OSL_ENSURE(nullptr != _pAggregateInstance, "OGeometryControlModel_Base::OGeometryControlModel_Base: invalid aggregate!");
+
+ osl_atomic_increment(&m_refCount);
+ {
+ m_xAggregate = _pAggregateInstance;
+
+ { // check if the aggregate is clonable
+ Reference< XCloneable > xCloneAccess(m_xAggregate, UNO_QUERY);
+ m_bCloneable = xCloneAccess.is();
+ }
+
+ setAggregation(m_xAggregate);
+ m_xAggregate->setDelegator(static_cast< XWeak* >(this));
+ }
+ osl_atomic_decrement(&m_refCount);
+
+ registerProperties();
+ }
+
+
+ OGeometryControlModel_Base::OGeometryControlModel_Base(Reference< XCloneable >& _rxAggregateInstance)
+ :OPropertySetAggregationHelper( m_aBHelper )
+ ,OPropertyContainer( m_aBHelper )
+ ,OGCM_Base( m_aMutex )
+ ,m_nPosX(0)
+ ,m_nPosY(0)
+ ,m_nWidth(0)
+ ,m_nHeight(0)
+ ,m_nTabIndex(-1)
+ ,m_nStep(0)
+ ,m_bCloneable(_rxAggregateInstance.is())
+ {
+ osl_atomic_increment(&m_refCount);
+ {
+ {
+ // ensure that the temporary gets destructed NOW
+ m_xAggregate.set(_rxAggregateInstance, UNO_QUERY);
+ }
+ OSL_ENSURE(m_xAggregate.is(), "OGeometryControlModel_Base::OGeometryControlModel_Base: invalid object given!");
+
+ // now the aggregate has a ref count of 2, but before setting the delegator it must be 1
+ _rxAggregateInstance.clear();
+ // now it should be the 1 we need here ...
+
+ setAggregation(m_xAggregate);
+ m_xAggregate->setDelegator(static_cast< XWeak* >(this));
+ }
+ osl_atomic_decrement(&m_refCount);
+
+ registerProperties();
+ }
+
+
+ Sequence< Type > SAL_CALL OGeometryControlModel_Base::getTypes( )
+ {
+ // our own types
+ Sequence< Type > aTypes = ::comphelper::concatSequences(
+ OPropertySetAggregationHelper::getTypes(),
+ getBaseTypes(),
+ OGCM_Base::getTypes()
+ );
+
+ if ( m_xAggregate.is() )
+ {
+ // retrieve the types of the aggregate
+ Reference< XTypeProvider > xAggregateTypeProv;
+ m_xAggregate->queryAggregation( cppu::UnoType<decltype(xAggregateTypeProv)>::get() ) >>= xAggregateTypeProv;
+ OSL_ENSURE( xAggregateTypeProv.is(), "OGeometryControlModel_Base::getTypes: aggregate should be a type provider!" );
+ Sequence< Type > aAggTypes;
+ if ( xAggregateTypeProv.is() )
+ aAggTypes = xAggregateTypeProv->getTypes();
+
+ // concat the sequences
+ sal_Int32 nOldSize = aTypes.getLength();
+ aTypes.realloc( nOldSize + aAggTypes.getLength() );
+ ::std::copy(
+ std::cbegin(aAggTypes),
+ std::cend(aAggTypes),
+ aTypes.getArray() + nOldSize
+ );
+ }
+
+ return aTypes;
+ }
+
+
+ void OGeometryControlModel_Base::registerProperties()
+ {
+ // register our members for the property handling of the OPropertyContainer
+ registerProperty(GCM_PROPERTY_POS_X, GCM_PROPERTY_ID_POS_X, DEFAULT_ATTRIBS(), &m_nPosX, cppu::UnoType<decltype(m_nPosX)>::get());
+ registerProperty(GCM_PROPERTY_POS_Y, GCM_PROPERTY_ID_POS_Y, DEFAULT_ATTRIBS(), &m_nPosY, cppu::UnoType<decltype(m_nPosY)>::get());
+ registerProperty(GCM_PROPERTY_WIDTH, GCM_PROPERTY_ID_WIDTH, DEFAULT_ATTRIBS(), &m_nWidth, cppu::UnoType<decltype(m_nWidth)>::get());
+ registerProperty(GCM_PROPERTY_HEIGHT, GCM_PROPERTY_ID_HEIGHT, DEFAULT_ATTRIBS(), &m_nHeight, cppu::UnoType<decltype(m_nHeight)>::get());
+ registerProperty(GCM_PROPERTY_NAME, GCM_PROPERTY_ID_NAME, DEFAULT_ATTRIBS(), &m_aName, cppu::UnoType<decltype(m_aName)>::get());
+ registerProperty(GCM_PROPERTY_TABINDEX, GCM_PROPERTY_ID_TABINDEX, DEFAULT_ATTRIBS(), &m_nTabIndex, cppu::UnoType<decltype(m_nTabIndex)>::get());
+ registerProperty(GCM_PROPERTY_STEP, GCM_PROPERTY_ID_STEP, DEFAULT_ATTRIBS(), &m_nStep, cppu::UnoType<decltype(m_nStep)>::get());
+ registerProperty(GCM_PROPERTY_TAG, GCM_PROPERTY_ID_TAG, DEFAULT_ATTRIBS(), &m_aTag, cppu::UnoType<decltype(m_aTag)>::get());
+ registerProperty(GCM_PROPERTY_RESOURCERESOLVER, GCM_PROPERTY_ID_RESOURCERESOLVER, DEFAULT_ATTRIBS(), &m_xStrResolver, cppu::UnoType<decltype(m_xStrResolver)>::get());
+ }
+
+
+ css::uno::Any OGeometryControlModel_Base::ImplGetDefaultValueByHandle(sal_Int32 nHandle)
+ {
+ css::uno::Any aDefault;
+
+ switch ( nHandle )
+ {
+ case GCM_PROPERTY_ID_POS_X: aDefault <<= sal_Int32(0); break;
+ case GCM_PROPERTY_ID_POS_Y: aDefault <<= sal_Int32(0); break;
+ case GCM_PROPERTY_ID_WIDTH: aDefault <<= sal_Int32(0); break;
+ case GCM_PROPERTY_ID_HEIGHT: aDefault <<= sal_Int32(0); break;
+ case GCM_PROPERTY_ID_NAME: aDefault <<= OUString(); break;
+ case GCM_PROPERTY_ID_TABINDEX: aDefault <<= sal_Int16(-1); break;
+ case GCM_PROPERTY_ID_STEP: aDefault <<= sal_Int32(0); break;
+ case GCM_PROPERTY_ID_TAG: aDefault <<= OUString(); break;
+ case GCM_PROPERTY_ID_RESOURCERESOLVER: aDefault <<= Reference< resource::XStringResourceResolver >(); break;
+ default: OSL_FAIL( "ImplGetDefaultValueByHandle - unknown Property" );
+ }
+
+ return aDefault;
+ }
+
+
+ css::uno::Any OGeometryControlModel_Base::ImplGetPropertyValueByHandle(sal_Int32 nHandle) const
+ {
+ css::uno::Any aValue;
+
+ switch ( nHandle )
+ {
+ case GCM_PROPERTY_ID_POS_X: aValue <<= m_nPosX; break;
+ case GCM_PROPERTY_ID_POS_Y: aValue <<= m_nPosY; break;
+ case GCM_PROPERTY_ID_WIDTH: aValue <<= m_nWidth; break;
+ case GCM_PROPERTY_ID_HEIGHT: aValue <<= m_nHeight; break;
+ case GCM_PROPERTY_ID_NAME: aValue <<= m_aName; break;
+ case GCM_PROPERTY_ID_TABINDEX: aValue <<= m_nTabIndex; break;
+ case GCM_PROPERTY_ID_STEP: aValue <<= m_nStep; break;
+ case GCM_PROPERTY_ID_TAG: aValue <<= m_aTag; break;
+ case GCM_PROPERTY_ID_RESOURCERESOLVER: aValue <<= m_xStrResolver; break;
+ default: OSL_FAIL( "ImplGetPropertyValueByHandle - unknown Property" );
+ }
+
+ return aValue;
+ }
+
+
+ void OGeometryControlModel_Base::ImplSetPropertyValueByHandle(sal_Int32 nHandle, const css::uno::Any& aValue)
+ {
+ switch ( nHandle )
+ {
+ case GCM_PROPERTY_ID_POS_X: aValue >>= m_nPosX; break;
+ case GCM_PROPERTY_ID_POS_Y: aValue >>= m_nPosY; break;
+ case GCM_PROPERTY_ID_WIDTH: aValue >>= m_nWidth; break;
+ case GCM_PROPERTY_ID_HEIGHT: aValue >>= m_nHeight; break;
+ case GCM_PROPERTY_ID_NAME: aValue >>= m_aName; break;
+ case GCM_PROPERTY_ID_TABINDEX: aValue >>= m_nTabIndex; break;
+ case GCM_PROPERTY_ID_STEP: aValue >>= m_nStep; break;
+ case GCM_PROPERTY_ID_TAG: aValue >>= m_aTag; break;
+ case GCM_PROPERTY_ID_RESOURCERESOLVER: aValue >>= m_xStrResolver; break;
+ default: OSL_FAIL( "ImplSetPropertyValueByHandle - unknown Property" );
+ }
+ }
+
+
+ Any SAL_CALL OGeometryControlModel_Base::queryAggregation( const Type& _rType )
+ {
+ Any aReturn;
+ if (_rType.equals(cppu::UnoType<XCloneable>::get()) && !m_bCloneable)
+ // somebody is asking for the XCloneable interface, but our aggregate does not support it
+ // -> outta here
+ // (need this extra check, cause OGCM_Base::queryAggregation would return this interface
+ // in every case)
+ return aReturn;
+
+ aReturn = OGCM_Base::queryAggregation(_rType);
+ // the basic interfaces (XInterface, XAggregation etc)
+
+ if (!aReturn.hasValue())
+ aReturn = OPropertySetAggregationHelper::queryInterface(_rType);
+ // the property set related interfaces
+
+ if (!aReturn.hasValue() && m_xAggregate.is())
+ aReturn = m_xAggregate->queryAggregation(_rType);
+ // the interfaces our aggregate can provide
+
+ return aReturn;
+ }
+
+
+ Any SAL_CALL OGeometryControlModel_Base::queryInterface( const Type& _rType )
+ {
+ return OGCM_Base::queryInterface(_rType);
+ }
+
+
+ void SAL_CALL OGeometryControlModel_Base::acquire( ) noexcept
+ {
+ OGCM_Base::acquire();
+ }
+
+
+ void SAL_CALL OGeometryControlModel_Base::release( ) noexcept
+ {
+ OGCM_Base::release();
+ }
+
+
+ void OGeometryControlModel_Base::releaseAggregation()
+ {
+ // release the aggregate (_before_ clearing m_xAggregate)
+ if (m_xAggregate.is())
+ m_xAggregate->setDelegator(nullptr);
+ setAggregation(nullptr);
+ }
+
+
+ OGeometryControlModel_Base::~OGeometryControlModel_Base()
+ {
+ releaseAggregation();
+ }
+
+
+ sal_Bool SAL_CALL OGeometryControlModel_Base::convertFastPropertyValue(Any& _rConvertedValue, Any& _rOldValue,
+ sal_Int32 _nHandle, const Any& _rValue)
+ {
+ return OPropertyContainer::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue);
+ }
+
+
+ void SAL_CALL OGeometryControlModel_Base::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue)
+ {
+ OPropertyContainer::setFastPropertyValue_NoBroadcast(_nHandle, _rValue);
+ }
+
+
+ void SAL_CALL OGeometryControlModel_Base::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const
+ {
+ OPropertyArrayAggregationHelper& rPH = static_cast<OPropertyArrayAggregationHelper&>(const_cast<OGeometryControlModel_Base*>(this)->getInfoHelper());
+ OUString sPropName;
+ sal_Int32 nOriginalHandle = -1;
+
+ if (rPH.fillAggregatePropertyInfoByHandle(&sPropName, &nOriginalHandle, _nHandle))
+ OPropertySetAggregationHelper::getFastPropertyValue(_rValue, _nHandle);
+ else
+ OPropertyContainer::getFastPropertyValue(_rValue, _nHandle);
+ }
+
+
+ css::beans::PropertyState OGeometryControlModel_Base::getPropertyStateByHandle(sal_Int32 nHandle)
+ {
+ css::uno::Any aValue = ImplGetPropertyValueByHandle( nHandle );
+ css::uno::Any aDefault = ImplGetDefaultValueByHandle( nHandle );
+
+ return CompareProperties( aValue, aDefault ) ? css::beans::PropertyState_DEFAULT_VALUE : css::beans::PropertyState_DIRECT_VALUE;
+ }
+
+
+ void OGeometryControlModel_Base::setPropertyToDefaultByHandle(sal_Int32 nHandle)
+ {
+ ImplSetPropertyValueByHandle( nHandle , ImplGetDefaultValueByHandle( nHandle ) );
+ }
+
+
+ css::uno::Any OGeometryControlModel_Base::getPropertyDefaultByHandle( sal_Int32 nHandle ) const
+ {
+ return ImplGetDefaultValueByHandle( nHandle );
+ }
+
+
+ Reference< XPropertySetInfo> SAL_CALL OGeometryControlModel_Base::getPropertySetInfo()
+ {
+ return OPropertySetAggregationHelper::createPropertySetInfo(getInfoHelper());
+ }
+
+
+ Reference< XCloneable > SAL_CALL OGeometryControlModel_Base::createClone( )
+ {
+ OSL_ENSURE(m_bCloneable, "OGeometryControlModel_Base::createClone: invalid call!");
+ if (!m_bCloneable)
+ return Reference< XCloneable >();
+
+ // let the aggregate create its own clone
+ // the interface
+ Reference< XCloneable > xCloneAccess;
+ m_xAggregate->queryAggregation(cppu::UnoType<decltype(xCloneAccess)>::get()) >>= xCloneAccess;
+ OSL_ENSURE(xCloneAccess.is(), "OGeometryControlModel_Base::createClone: suspicious aggregate!");
+ if (!xCloneAccess.is())
+ return Reference< XCloneable >();
+ // the aggregate's clone
+ Reference< XCloneable > xAggregateClone = xCloneAccess->createClone();
+ OSL_ENSURE(xAggregateClone.is(), "OGeometryControlModel_Base::createClone: suspicious return of the aggregate!");
+
+ // create a new wrapper aggregating this return value
+ rtl::Reference<OGeometryControlModel_Base> pOwnClone = createClone_Impl(xAggregateClone);
+ OSL_ENSURE(pOwnClone, "OGeometryControlModel_Base::createClone: invalid derivee behaviour!");
+ OSL_ENSURE(!xAggregateClone.is(), "OGeometryControlModel_Base::createClone: invalid ctor behaviour!");
+ // should have been reset
+
+ // set properties
+ pOwnClone->m_nPosX = m_nPosX;
+ pOwnClone->m_nPosY = m_nPosY;
+ pOwnClone->m_nWidth = m_nWidth;
+ pOwnClone->m_nHeight = m_nHeight;
+ pOwnClone->m_aName = m_aName;
+ pOwnClone->m_nTabIndex = m_nTabIndex;
+ pOwnClone->m_nStep = m_nStep;
+ pOwnClone->m_aTag = m_aTag;
+
+
+ // Clone event container
+ Reference< css::script::XScriptEventsSupplier > xEventsSupplier =
+ static_cast< css::script::XScriptEventsSupplier* >( this );
+
+ if( xEventsSupplier.is() )
+ {
+ Reference< XNameContainer > xEventCont = xEventsSupplier->getEvents();
+ Reference< XNameContainer > xCloneEventCont = pOwnClone->getEvents();
+
+ const css::uno::Sequence< OUString > aNames =
+ xEventCont->getElementNames();
+
+ for( const OUString& aName : aNames )
+ {
+ css::uno::Any aElement = xEventCont->getByName( aName );
+ xCloneEventCont->insertByName( aName, aElement );
+ }
+ }
+
+ return pOwnClone;
+ }
+
+
+ Reference< XNameContainer > SAL_CALL OGeometryControlModel_Base::getEvents()
+ {
+ if( !mxEventContainer.is() )
+ mxEventContainer = new toolkit::ScriptEventContainer();
+ return mxEventContainer;
+ }
+
+
+ void SAL_CALL OGeometryControlModel_Base::disposing()
+ {
+ OGCM_Base::disposing();
+ OPropertySetAggregationHelper::disposing();
+
+ Reference<XComponent> xComp;
+ if ( query_aggregation( m_xAggregate, xComp ) )
+ xComp->dispose();
+ }
+
+
+ //= OCommonGeometryControlModel
+
+
+ typedef std::unordered_map< OUString, sal_Int32 > HashMapString2Int;
+ typedef std::vector< css::uno::Sequence< css::beans::Property > > PropSeqArray;
+ typedef std::vector< ::std::vector< sal_Int32 > > IntArrayArray;
+
+ // for creating class-unique PropertySetInfo's, we need some info:
+ namespace { HashMapString2Int gServiceSpecifierMap; }
+ // this one maps from a String, which is the service specifier for our
+ // aggregate, to a unique id
+
+ namespace { PropSeqArray gAggregateProperties; }
+ // this one contains the properties which belong to all the unique ids
+ // in ServiceSpecifierMap
+
+ namespace { IntArrayArray gAmbiguousPropertyIds; }
+ // the ids of the properties which we as well as our aggregate supply
+ // For such props, we let our base class handle them, and whenever such
+ // a prop is set, we forward this to our aggregate.
+
+ // With this, we can ensure that two instances of this class share the
+ // same PropertySetInfo if and only if both aggregates have the same
+ // service specifier.
+
+
+ OCommonGeometryControlModel::OCommonGeometryControlModel( Reference< XCloneable >& _rxAgg, const OUString& _rServiceSpecifier )
+ :OGeometryControlModel_Base( _rxAgg )
+ ,m_sServiceSpecifier( _rServiceSpecifier )
+ ,m_nPropertyMapId( 0 )
+ {
+ Reference< XPropertySetInfo > xPI;
+ if ( m_xAggregateSet.is() )
+ xPI = m_xAggregateSet->getPropertySetInfo();
+ if ( !xPI.is() )
+ {
+ releaseAggregation();
+ throw IllegalArgumentException();
+ }
+
+ HashMapString2Int::iterator aPropMapIdPos = gServiceSpecifierMap.find( m_sServiceSpecifier );
+ if ( gServiceSpecifierMap.end() == aPropMapIdPos )
+ {
+ m_nPropertyMapId = gAggregateProperties.size();
+ gAggregateProperties.push_back( xPI->getProperties() );
+ gAmbiguousPropertyIds.emplace_back( );
+
+ gServiceSpecifierMap[ m_sServiceSpecifier ] = m_nPropertyMapId;
+ }
+ else
+ m_nPropertyMapId = aPropMapIdPos->second;
+ }
+
+ namespace {
+
+ struct PropertyNameLess
+ {
+ bool operator()( const Property& _rLHS, const Property& _rRHS )
+ {
+ return _rLHS.Name < _rRHS.Name;
+ }
+ };
+
+
+ struct PropertyNameEqual
+ {
+ const OUString& m_rCompare;
+ explicit PropertyNameEqual( const OUString& _rCompare ) : m_rCompare( _rCompare ) { }
+
+ bool operator()( const Property& _rLHS )
+ {
+ return _rLHS.Name == m_rCompare;
+ }
+ };
+
+ }
+
+ ::cppu::IPropertyArrayHelper* OCommonGeometryControlModel::createArrayHelper( sal_Int32 _nId ) const
+ {
+ OSL_ENSURE( _nId == m_nPropertyMapId, "OCommonGeometryControlModel::createArrayHelper: invalid argument!" );
+ OSL_ENSURE( _nId < static_cast<sal_Int32>(gAggregateProperties.size()), "OCommonGeometryControlModel::createArrayHelper: invalid status info (1)!" );
+ OSL_ENSURE( _nId < static_cast<sal_Int32>(gAmbiguousPropertyIds.size()), "OCommonGeometryControlModel::createArrayHelper: invalid status info (2)!" );
+
+ // our own properties
+ Sequence< Property > aProps;
+ OPropertyContainer::describeProperties( aProps );
+
+ // the aggregate properties
+ Sequence< Property > aAggregateProps = gAggregateProperties[ _nId ];
+
+ // look for duplicates, and remember them
+ IntArrayArray::value_type& rDuplicateIds = gAmbiguousPropertyIds[ _nId ];
+ // for this, sort the aggregate properties
+ auto [begin, end] = asNonConstRange(aAggregateProps);
+ ::std::sort(
+ begin,
+ end,
+ PropertyNameLess()
+ );
+
+ // now loop through our own props
+ for ( const Property& rProp : std::as_const(aProps) )
+ {
+ // look for the current property in the properties of our aggregate
+ const Property* pAggPropPos = ::std::find_if( std::cbegin(aAggregateProps), std::cend(aAggregateProps), PropertyNameEqual( rProp.Name ) );
+ if ( pAggPropPos != std::cend(aAggregateProps) )
+ { // found a duplicate
+ // -> remove from the aggregate property sequence
+ ::comphelper::removeElementAt( aAggregateProps, pAggPropPos - std::cbegin(aAggregateProps) );
+
+ // and additionally, remember the id of this property
+ rDuplicateIds.push_back( rProp.Handle );
+ }
+ }
+
+ // now, finally, sort the duplicates
+ ::std::sort( rDuplicateIds.begin(), rDuplicateIds.end(), ::std::less< sal_Int32 >() );
+
+ return new OPropertyArrayAggregationHelper(aProps, aAggregateProps);
+ }
+
+
+ ::cppu::IPropertyArrayHelper& SAL_CALL OCommonGeometryControlModel::getInfoHelper()
+ {
+ return *getArrayHelper( m_nPropertyMapId );
+ }
+
+
+ rtl::Reference<OGeometryControlModel_Base> OCommonGeometryControlModel::createClone_Impl( Reference< XCloneable >& _rxAggregateInstance )
+ {
+ return new OCommonGeometryControlModel( _rxAggregateInstance, m_sServiceSpecifier );
+ }
+
+ Sequence< sal_Int8 > SAL_CALL OCommonGeometryControlModel::getImplementationId( )
+ {
+ return css::uno::Sequence<sal_Int8>();
+ }
+
+ namespace {
+
+ struct Int32Equal
+ {
+ sal_Int32 m_nCompare;
+ explicit Int32Equal( sal_Int32 _nCompare ) : m_nCompare( _nCompare ) { }
+
+ bool operator()( sal_Int32 _nLHS )
+ {
+ return _nLHS == m_nCompare;
+ }
+ };
+
+ }
+
+ void SAL_CALL OCommonGeometryControlModel::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue )
+ {
+ OGeometryControlModel_Base::setFastPropertyValue_NoBroadcast( _nHandle, _rValue );
+
+ // look if this id is one we recognized as duplicate
+ IntArrayArray::value_type& rDuplicateIds = gAmbiguousPropertyIds[ m_nPropertyMapId ];
+
+ if ( std::any_of(rDuplicateIds.begin(), rDuplicateIds.end(), Int32Equal( _nHandle )) )
+ {
+ // yes, it is such a property
+ OUString sPropName;
+ sal_Int16 nAttributes(0);
+ static_cast< OPropertyArrayAggregationHelper* >( getArrayHelper( m_nPropertyMapId ) )->fillPropertyMembersByHandle( &sPropName, &nAttributes, _nHandle );
+
+ if ( m_xAggregateSet.is() && !sPropName.isEmpty() )
+ m_xAggregateSet->setPropertyValue( sPropName, _rValue );
+ }
+ }
+
+
+// } // namespace toolkit
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/grid/defaultgridcolumnmodel.cxx b/toolkit/source/controls/grid/defaultgridcolumnmodel.cxx
new file mode 100644
index 000000000..ad17d15ea
--- /dev/null
+++ b/toolkit/source/controls/grid/defaultgridcolumnmodel.cxx
@@ -0,0 +1,389 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "gridcolumn.hxx"
+
+#include <com/sun/star/awt/grid/XGridColumnModel.hpp>
+#include <com/sun/star/awt/grid/XGridColumn.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <comphelper/sequence.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <comphelper/componentguard.hxx>
+#include <comphelper/interfacecontainer3.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <o3tl/safeint.hxx>
+#include <rtl/ref.hxx>
+#include <sal/log.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <vector>
+
+using namespace css::awt;
+using namespace css::awt::grid;
+using namespace css::container;
+using namespace css::lang;
+using namespace css::uno;
+using namespace toolkit;
+
+namespace {
+
+typedef ::cppu::WeakComponentImplHelper < css::awt::grid::XGridColumnModel
+ , css::lang::XServiceInfo
+ > DefaultGridColumnModel_Base;
+
+class DefaultGridColumnModel :public ::cppu::BaseMutex
+ ,public DefaultGridColumnModel_Base
+{
+public:
+ DefaultGridColumnModel();
+ DefaultGridColumnModel( DefaultGridColumnModel const & i_copySource );
+
+ // XGridColumnModel
+ virtual ::sal_Int32 SAL_CALL getColumnCount() override;
+ virtual css::uno::Reference< css::awt::grid::XGridColumn > SAL_CALL createColumn( ) override;
+ virtual ::sal_Int32 SAL_CALL addColumn(const css::uno::Reference< css::awt::grid::XGridColumn > & column) override;
+ virtual void SAL_CALL removeColumn( ::sal_Int32 i_columnIndex ) override;
+ virtual css::uno::Sequence< css::uno::Reference< css::awt::grid::XGridColumn > > SAL_CALL getColumns() override;
+ virtual css::uno::Reference< css::awt::grid::XGridColumn > SAL_CALL getColumn(::sal_Int32 index) override;
+ virtual void SAL_CALL setDefaultColumns(sal_Int32 rowElements) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // XContainer
+ virtual void SAL_CALL addContainerListener( const css::uno::Reference< css::container::XContainerListener >& xListener ) override;
+ virtual void SAL_CALL removeContainerListener( const css::uno::Reference< css::container::XContainerListener >& xListener ) override;
+
+ // XCloneable
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone( ) override;
+
+ // OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+private:
+ typedef ::std::vector< css::uno::Reference< css::awt::grid::XGridColumn > > Columns;
+
+ ::comphelper::OInterfaceContainerHelper3<XContainerListener> m_aContainerListeners;
+ Columns m_aColumns;
+};
+
+ DefaultGridColumnModel::DefaultGridColumnModel()
+ :DefaultGridColumnModel_Base( m_aMutex )
+ ,m_aContainerListeners( m_aMutex )
+ {
+ }
+
+ DefaultGridColumnModel::DefaultGridColumnModel( DefaultGridColumnModel const & i_copySource )
+ :cppu::BaseMutex()
+ ,DefaultGridColumnModel_Base( m_aMutex )
+ ,m_aContainerListeners( m_aMutex )
+ {
+ Columns aColumns;
+ aColumns.reserve( i_copySource.m_aColumns.size() );
+ try
+ {
+ for ( Columns::const_iterator col = i_copySource.m_aColumns.begin();
+ col != i_copySource.m_aColumns.end();
+ ++col
+ )
+ {
+ Reference< css::util::XCloneable > const xCloneable( *col, UNO_QUERY_THROW );
+ Reference< XGridColumn > const xClone( xCloneable->createClone(), UNO_QUERY_THROW );
+
+ GridColumn* const pGridColumn = comphelper::getFromUnoTunnel<GridColumn>( xClone );
+ if ( pGridColumn == nullptr )
+ throw RuntimeException( "invalid clone source implementation", *this );
+ // that's indeed a RuntimeException, not an IllegalArgumentException or some such:
+ // a DefaultGridColumnModel implementation whose columns are not GridColumn implementations
+ // is borked.
+ pGridColumn->setIndex( col - i_copySource.m_aColumns.begin() );
+
+ aColumns.push_back( xClone );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+ if ( aColumns.size() == i_copySource.m_aColumns.size() )
+ m_aColumns.swap( aColumns );
+ }
+
+ ::sal_Int32 SAL_CALL DefaultGridColumnModel::getColumnCount()
+ {
+ return m_aColumns.size();
+ }
+
+
+ Reference< XGridColumn > SAL_CALL DefaultGridColumnModel::createColumn( )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+ return new GridColumn();
+ }
+
+
+ ::sal_Int32 SAL_CALL DefaultGridColumnModel::addColumn( const Reference< XGridColumn > & i_column )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ GridColumn* const pGridColumn = comphelper::getFromUnoTunnel<GridColumn>( i_column );
+ if ( pGridColumn == nullptr )
+ throw css::lang::IllegalArgumentException( "invalid column implementation", *this, 1 );
+
+ m_aColumns.push_back( i_column );
+ sal_Int32 index = m_aColumns.size() - 1;
+ pGridColumn->setIndex( index );
+
+ // fire insertion notifications
+ ContainerEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.Accessor <<= index;
+ aEvent.Element <<= i_column;
+
+ aGuard.clear();
+ m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvent );
+
+ return index;
+ }
+
+
+ void SAL_CALL DefaultGridColumnModel::removeColumn( ::sal_Int32 i_columnIndex )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ if ( ( i_columnIndex < 0 ) || ( o3tl::make_unsigned( i_columnIndex ) >= m_aColumns.size() ) )
+ throw css::lang::IndexOutOfBoundsException( OUString(), *this );
+
+ Columns::iterator const pos = m_aColumns.begin() + i_columnIndex;
+ Reference< XGridColumn > const xColumn( *pos );
+ m_aColumns.erase( pos );
+
+ // update indexes of all subsequent columns
+ sal_Int32 columnIndex( i_columnIndex );
+ for ( Columns::iterator updatePos = m_aColumns.begin() + columnIndex;
+ updatePos != m_aColumns.end();
+ ++updatePos, ++columnIndex
+ )
+ {
+ GridColumn* pColumnImpl = comphelper::getFromUnoTunnel<GridColumn>( *updatePos );
+ if ( !pColumnImpl )
+ {
+ SAL_WARN( "toolkit.controls", "DefaultGridColumnModel::removeColumn: invalid column implementation!" );
+ continue;
+ }
+
+ pColumnImpl->setIndex( columnIndex );
+ }
+
+ // fire removal notifications
+ ContainerEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.Accessor <<= i_columnIndex;
+ aEvent.Element <<= xColumn;
+
+ aGuard.clear();
+ m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvent );
+
+ // dispose the removed column
+ try
+ {
+ xColumn->dispose();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+ }
+
+
+ Sequence< Reference< XGridColumn > > SAL_CALL DefaultGridColumnModel::getColumns()
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+ return ::comphelper::containerToSequence( m_aColumns );
+ }
+
+
+ Reference< XGridColumn > SAL_CALL DefaultGridColumnModel::getColumn(::sal_Int32 index)
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ if ( index >=0 && o3tl::make_unsigned(index) < m_aColumns.size())
+ return m_aColumns[index];
+
+ throw css::lang::IndexOutOfBoundsException();
+ }
+
+
+ void SAL_CALL DefaultGridColumnModel::setDefaultColumns(sal_Int32 rowElements)
+ {
+ ::std::vector< ContainerEvent > aRemovedColumns;
+ ::std::vector< ContainerEvent > aInsertedColumns;
+
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ // remove existing columns
+ while ( !m_aColumns.empty() )
+ {
+ const size_t lastColIndex = m_aColumns.size() - 1;
+
+ ContainerEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.Accessor <<= sal_Int32( lastColIndex );
+ aEvent.Element <<= m_aColumns[ lastColIndex ];
+ aRemovedColumns.push_back( aEvent );
+
+ m_aColumns.erase( m_aColumns.begin() + lastColIndex );
+ }
+
+ // add new columns
+ for ( sal_Int32 i=0; i<rowElements; ++i )
+ {
+ ::rtl::Reference< GridColumn > const pGridColumn = new GridColumn();
+ Reference< XGridColumn > const xColumn( pGridColumn );
+ OUString colTitle = "Column " + OUString::number( i + 1 );
+ pGridColumn->setTitle( colTitle );
+ pGridColumn->setColumnWidth( 80 /* APPFONT */ );
+ pGridColumn->setFlexibility( 1 );
+ pGridColumn->setResizeable( true );
+ pGridColumn->setDataColumnIndex( i );
+
+ ContainerEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.Accessor <<= i;
+ aEvent.Element <<= xColumn;
+ aInsertedColumns.push_back( aEvent );
+
+ m_aColumns.push_back( xColumn );
+ pGridColumn->setIndex( i );
+ }
+ }
+
+ // fire removal notifications
+ for (const auto& rEvent : aRemovedColumns)
+ {
+ m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, rEvent );
+ }
+
+ // fire insertion notifications
+ for (const auto& rEvent : aInsertedColumns)
+ {
+ m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, rEvent );
+ }
+
+ // dispose removed columns
+ for (const auto& rEvent : aRemovedColumns)
+ {
+ try
+ {
+ const Reference< XComponent > xColComp( rEvent.Element, UNO_QUERY_THROW );
+ xColComp->dispose();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+ }
+ }
+
+
+ OUString SAL_CALL DefaultGridColumnModel::getImplementationName( )
+ {
+ return "stardiv.Toolkit.DefaultGridColumnModel";
+ }
+
+ sal_Bool SAL_CALL DefaultGridColumnModel::supportsService( const OUString& i_serviceName )
+ {
+ return cppu::supportsService(this, i_serviceName);
+ }
+
+ Sequence< OUString > SAL_CALL DefaultGridColumnModel::getSupportedServiceNames( )
+ {
+ return { "com.sun.star.awt.grid.DefaultGridColumnModel" };
+ }
+
+
+ void SAL_CALL DefaultGridColumnModel::addContainerListener( const Reference< XContainerListener >& i_listener )
+ {
+ if ( i_listener.is() )
+ m_aContainerListeners.addInterface( i_listener );
+ }
+
+
+ void SAL_CALL DefaultGridColumnModel::removeContainerListener( const Reference< XContainerListener >& i_listener )
+ {
+ if ( i_listener.is() )
+ m_aContainerListeners.removeInterface( i_listener );
+ }
+
+
+ void SAL_CALL DefaultGridColumnModel::disposing()
+ {
+ DefaultGridColumnModel_Base::disposing();
+
+ EventObject aEvent( *this );
+ m_aContainerListeners.disposeAndClear( aEvent );
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ // remove, dispose and clear columns
+ while ( !m_aColumns.empty() )
+ {
+ try
+ {
+ const Reference< XComponent > xColComponent( m_aColumns[ 0 ], UNO_QUERY_THROW );
+ xColComponent->dispose();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+
+ m_aColumns.erase( m_aColumns.begin() );
+ }
+
+ Columns().swap(m_aColumns);
+ }
+
+
+ Reference< css::util::XCloneable > SAL_CALL DefaultGridColumnModel::createClone( )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+ return new DefaultGridColumnModel( *this );
+ }
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_DefaultGridColumnModel_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new DefaultGridColumnModel());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/grid/defaultgriddatamodel.cxx b/toolkit/source/controls/grid/defaultgriddatamodel.cxx
new file mode 100644
index 000000000..2e5f4e305
--- /dev/null
+++ b/toolkit/source/controls/grid/defaultgriddatamodel.cxx
@@ -0,0 +1,505 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/awt/grid/XMutableGridDataModel.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <comphelper/componentguard.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <o3tl/safeint.hxx>
+
+#include <algorithm>
+#include <vector>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::awt::grid;
+using namespace ::com::sun::star::lang;
+
+namespace {
+
+typedef ::cppu::WeakComponentImplHelper < XMutableGridDataModel
+ , XServiceInfo
+ > DefaultGridDataModel_Base;
+
+class DefaultGridDataModel :public ::cppu::BaseMutex
+ ,public DefaultGridDataModel_Base
+{
+public:
+ DefaultGridDataModel();
+ DefaultGridDataModel( DefaultGridDataModel const & i_copySource );
+
+ // XMutableGridDataModel
+ virtual void SAL_CALL addRow( const Any& i_heading, const css::uno::Sequence< css::uno::Any >& Data ) override;
+ virtual void SAL_CALL addRows( const css::uno::Sequence< css::uno::Any>& Headings, const css::uno::Sequence< css::uno::Sequence< css::uno::Any > >& Data ) override;
+ virtual void SAL_CALL insertRow( ::sal_Int32 i_index, const css::uno::Any& i_heading, const css::uno::Sequence< css::uno::Any >& Data ) override;
+ virtual void SAL_CALL insertRows( ::sal_Int32 i_index, const css::uno::Sequence< css::uno::Any>& Headings, const css::uno::Sequence< css::uno::Sequence< css::uno::Any > >& Data ) override;
+ virtual void SAL_CALL removeRow( ::sal_Int32 RowIndex ) override;
+ virtual void SAL_CALL removeAllRows( ) override;
+ virtual void SAL_CALL updateCellData( ::sal_Int32 ColumnIndex, ::sal_Int32 RowIndex, const css::uno::Any& Value ) override;
+ virtual void SAL_CALL updateRowData( const css::uno::Sequence< ::sal_Int32 >& ColumnIndexes, ::sal_Int32 RowIndex, const css::uno::Sequence< css::uno::Any >& Values ) override;
+ virtual void SAL_CALL updateRowHeading( ::sal_Int32 RowIndex, const css::uno::Any& Heading ) override;
+ virtual void SAL_CALL updateCellToolTip( ::sal_Int32 ColumnIndex, ::sal_Int32 RowIndex, const css::uno::Any& Value ) override;
+ virtual void SAL_CALL updateRowToolTip( ::sal_Int32 RowIndex, const css::uno::Any& Value ) override;
+ virtual void SAL_CALL addGridDataListener( const css::uno::Reference< css::awt::grid::XGridDataListener >& Listener ) override;
+ virtual void SAL_CALL removeGridDataListener( const css::uno::Reference< css::awt::grid::XGridDataListener >& Listener ) override;
+
+ // XGridDataModel
+ virtual ::sal_Int32 SAL_CALL getRowCount() override;
+ virtual ::sal_Int32 SAL_CALL getColumnCount() override;
+ virtual css::uno::Any SAL_CALL getCellData( ::sal_Int32 Column, ::sal_Int32 Row ) override;
+ virtual css::uno::Any SAL_CALL getCellToolTip( ::sal_Int32 Column, ::sal_Int32 Row ) override;
+ virtual css::uno::Any SAL_CALL getRowHeading( ::sal_Int32 RowIndex ) override;
+ virtual css::uno::Sequence< css::uno::Any > SAL_CALL getRowData( ::sal_Int32 RowIndex ) override;
+
+ // OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+ // XCloneable
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone( ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+private:
+ typedef ::std::pair< Any, Any > CellData;
+ typedef ::std::vector< CellData > RowData;
+ typedef ::std::vector< RowData > GridData;
+
+ void broadcast(
+ GridDataEvent const & i_event,
+ void ( SAL_CALL css::awt::grid::XGridDataListener::*i_listenerMethod )( css::awt::grid::GridDataEvent const & ),
+ ::comphelper::ComponentGuard & i_instanceLock
+ );
+
+ void impl_insertRow( sal_Int32 const i_position, Any const & i_heading, Sequence< Any > const & i_rowData, sal_Int32 const i_assumedColCount = -1 );
+
+ ::sal_Int32 impl_getRowCount_nolck() const { return sal_Int32( m_aData.size() ); }
+
+ CellData const & impl_getCellData_throw( sal_Int32 const i_columnIndex, sal_Int32 const i_rowIndex ) const;
+ CellData& impl_getCellDataAccess_throw( sal_Int32 const i_columnIndex, sal_Int32 const i_rowIndex );
+ RowData& impl_getRowDataAccess_throw( sal_Int32 const i_rowIndex, size_t const i_requiredColumnCount );
+
+ GridData m_aData;
+ ::std::vector< css::uno::Any > m_aRowHeaders;
+ sal_Int32 m_nColumnCount;
+};
+
+ DefaultGridDataModel::DefaultGridDataModel()
+ :DefaultGridDataModel_Base( m_aMutex )
+ ,m_nColumnCount(0)
+ {
+ }
+
+
+ DefaultGridDataModel::DefaultGridDataModel( DefaultGridDataModel const & i_copySource )
+ :cppu::BaseMutex()
+ ,DefaultGridDataModel_Base( m_aMutex )
+ ,m_aData( i_copySource.m_aData )
+ ,m_aRowHeaders( i_copySource.m_aRowHeaders )
+ ,m_nColumnCount( i_copySource.m_nColumnCount )
+ {
+ }
+
+ void DefaultGridDataModel::broadcast( GridDataEvent const & i_event,
+ void ( SAL_CALL XGridDataListener::*i_listenerMethod )( GridDataEvent const & ), ::comphelper::ComponentGuard & i_instanceLock )
+ {
+ ::cppu::OInterfaceContainerHelper* pListeners = rBHelper.getContainer( cppu::UnoType<XGridDataListener>::get() );
+ if ( !pListeners )
+ return;
+
+ i_instanceLock.clear();
+ pListeners->notifyEach( i_listenerMethod, i_event );
+ }
+
+
+ ::sal_Int32 SAL_CALL DefaultGridDataModel::getRowCount()
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+ return impl_getRowCount_nolck();
+ }
+
+
+ ::sal_Int32 SAL_CALL DefaultGridDataModel::getColumnCount()
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+ return m_nColumnCount;
+ }
+
+
+ DefaultGridDataModel::CellData const & DefaultGridDataModel::impl_getCellData_throw( sal_Int32 const i_column, sal_Int32 const i_row ) const
+ {
+ if ( ( i_row < 0 ) || ( o3tl::make_unsigned( i_row ) > m_aData.size() )
+ || ( i_column < 0 ) || ( i_column > m_nColumnCount )
+ )
+ throw IndexOutOfBoundsException( OUString(), *const_cast< DefaultGridDataModel* >( this ) );
+
+ RowData const & rRow( m_aData[ i_row ] );
+ if ( o3tl::make_unsigned( i_column ) < rRow.size() )
+ return rRow[ i_column ];
+
+ static CellData s_aEmpty;
+ return s_aEmpty;
+ }
+
+
+ DefaultGridDataModel::RowData& DefaultGridDataModel::impl_getRowDataAccess_throw( sal_Int32 const i_rowIndex, size_t const i_requiredColumnCount )
+ {
+ OSL_ENSURE( i_requiredColumnCount <= o3tl::make_unsigned( m_nColumnCount ), "DefaultGridDataModel::impl_getRowDataAccess_throw: invalid column count!" );
+ if ( ( i_rowIndex < 0 ) || ( o3tl::make_unsigned( i_rowIndex ) >= m_aData.size() ) )
+ throw IndexOutOfBoundsException( OUString(), *this );
+
+ RowData& rRowData( m_aData[ i_rowIndex ] );
+ if ( rRowData.size() < i_requiredColumnCount )
+ rRowData.resize( i_requiredColumnCount );
+ return rRowData;
+ }
+
+
+ DefaultGridDataModel::CellData& DefaultGridDataModel::impl_getCellDataAccess_throw( sal_Int32 const i_columnIndex, sal_Int32 const i_rowIndex )
+ {
+ if ( ( i_columnIndex < 0 ) || ( i_columnIndex >= m_nColumnCount ) )
+ throw IndexOutOfBoundsException( OUString(), *this );
+
+ RowData& rRowData( impl_getRowDataAccess_throw( i_rowIndex, size_t( i_columnIndex + 1 ) ) );
+ return rRowData[ i_columnIndex ];
+ }
+
+
+ Any SAL_CALL DefaultGridDataModel::getCellData( ::sal_Int32 i_column, ::sal_Int32 i_row )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+ return impl_getCellData_throw( i_column, i_row ).first;
+ }
+
+
+ Any SAL_CALL DefaultGridDataModel::getCellToolTip( ::sal_Int32 i_column, ::sal_Int32 i_row )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+ return impl_getCellData_throw( i_column, i_row ).second;
+ }
+
+
+ Any SAL_CALL DefaultGridDataModel::getRowHeading( ::sal_Int32 i_row )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ if ( ( i_row < 0 ) || ( o3tl::make_unsigned( i_row ) >= m_aRowHeaders.size() ) )
+ throw IndexOutOfBoundsException( OUString(), *this );
+
+ return m_aRowHeaders[ i_row ];
+ }
+
+
+ Sequence< Any > SAL_CALL DefaultGridDataModel::getRowData( ::sal_Int32 i_rowIndex )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ Sequence< Any > resultData( m_nColumnCount );
+ RowData& rRowData = impl_getRowDataAccess_throw( i_rowIndex, m_nColumnCount );
+
+ ::std::transform( rRowData.begin(), rRowData.end(), resultData.getArray(),
+ [] ( const CellData& rCellData )
+ { return rCellData.first; });
+ return resultData;
+ }
+
+
+ void DefaultGridDataModel::impl_insertRow( sal_Int32 const i_position, Any const & i_heading, Sequence< Any > const & i_rowData, sal_Int32 const i_assumedColCount )
+ {
+ OSL_PRECOND( ( i_assumedColCount <= 0 ) || ( i_assumedColCount >= i_rowData.getLength() ),
+ "DefaultGridDataModel::impl_insertRow: invalid column count!" );
+
+ // insert heading
+ m_aRowHeaders.insert( m_aRowHeaders.begin() + i_position, i_heading );
+
+ // create new data row
+ RowData newRow( i_assumedColCount > 0 ? i_assumedColCount : i_rowData.getLength() );
+ RowData::iterator cellData = newRow.begin();
+ for ( const Any& rData : i_rowData )
+ {
+ cellData->first = rData;
+ ++cellData;
+ }
+
+ // insert data row
+ m_aData.insert( m_aData.begin() + i_position, newRow );
+ }
+
+
+ void SAL_CALL DefaultGridDataModel::addRow( const Any& i_heading, const Sequence< Any >& i_data )
+ {
+ insertRow( getRowCount(), i_heading, i_data );
+ }
+
+
+ void SAL_CALL DefaultGridDataModel::addRows( const Sequence< Any >& i_headings, const Sequence< Sequence< Any > >& i_data )
+ {
+ insertRows( getRowCount(), i_headings, i_data );
+ }
+
+
+ void SAL_CALL DefaultGridDataModel::insertRow( ::sal_Int32 i_index, const Any& i_heading, const Sequence< Any >& i_data )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ if ( ( i_index < 0 ) || ( i_index > impl_getRowCount_nolck() ) )
+ throw IndexOutOfBoundsException( OUString(), *this );
+
+ // actually insert the row
+ impl_insertRow( i_index, i_heading, i_data );
+
+ // update column count
+ sal_Int32 const columnCount = i_data.getLength();
+ if ( columnCount > m_nColumnCount )
+ m_nColumnCount = columnCount;
+
+ broadcast(
+ GridDataEvent( *this, -1, -1, i_index, i_index ),
+ &XGridDataListener::rowsInserted,
+ aGuard
+ );
+ }
+
+
+ void SAL_CALL DefaultGridDataModel::insertRows( ::sal_Int32 i_index, const Sequence< Any>& i_headings, const Sequence< Sequence< Any > >& i_data )
+ {
+ if ( i_headings.getLength() != i_data.getLength() )
+ throw IllegalArgumentException( OUString(), *this, -1 );
+
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ if ( ( i_index < 0 ) || ( i_index > impl_getRowCount_nolck() ) )
+ throw IndexOutOfBoundsException( OUString(), *this );
+
+ sal_Int32 const rowCount = i_headings.getLength();
+ if ( rowCount == 0 )
+ return;
+
+ // determine max col count in the new data
+ auto pData = std::max_element(i_data.begin(), i_data.end(),
+ [](const Sequence< Any >& a, const Sequence< Any >& b) { return a.getLength() < b.getLength(); });
+ sal_Int32 maxColCount = pData->getLength();
+
+ if ( maxColCount < m_nColumnCount )
+ maxColCount = m_nColumnCount;
+
+ for ( sal_Int32 row=0; row<rowCount; ++row )
+ {
+ impl_insertRow( i_index + row, i_headings[row], i_data[row], maxColCount );
+ }
+
+ if ( maxColCount > m_nColumnCount )
+ m_nColumnCount = maxColCount;
+
+ broadcast(
+ GridDataEvent( *this, -1, -1, i_index, i_index + rowCount - 1 ),
+ &XGridDataListener::rowsInserted,
+ aGuard
+ );
+ }
+
+
+ void SAL_CALL DefaultGridDataModel::removeRow( ::sal_Int32 i_rowIndex )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ if ( ( i_rowIndex < 0 ) || ( o3tl::make_unsigned( i_rowIndex ) >= m_aData.size() ) )
+ throw IndexOutOfBoundsException( OUString(), *this );
+
+ m_aRowHeaders.erase( m_aRowHeaders.begin() + i_rowIndex );
+ m_aData.erase( m_aData.begin() + i_rowIndex );
+
+ broadcast(
+ GridDataEvent( *this, -1, -1, i_rowIndex, i_rowIndex ),
+ &XGridDataListener::rowsRemoved,
+ aGuard
+ );
+ }
+
+
+ void SAL_CALL DefaultGridDataModel::removeAllRows( )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ m_aRowHeaders.clear();
+ m_aData.clear();
+
+ broadcast(
+ GridDataEvent( *this, -1, -1, -1, -1 ),
+ &XGridDataListener::rowsRemoved,
+ aGuard
+ );
+ }
+
+
+ void SAL_CALL DefaultGridDataModel::updateCellData( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex, const Any& i_value )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ impl_getCellDataAccess_throw( i_columnIndex, i_rowIndex ).first = i_value;
+
+ broadcast(
+ GridDataEvent( *this, i_columnIndex, i_columnIndex, i_rowIndex, i_rowIndex ),
+ &XGridDataListener::dataChanged,
+ aGuard
+ );
+ }
+
+
+ void SAL_CALL DefaultGridDataModel::updateRowData( const Sequence< ::sal_Int32 >& i_columnIndexes, ::sal_Int32 i_rowIndex, const Sequence< Any >& i_values )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ if ( ( i_rowIndex < 0 ) || ( o3tl::make_unsigned( i_rowIndex ) >= m_aData.size() ) )
+ throw IndexOutOfBoundsException( OUString(), *this );
+
+ if ( i_columnIndexes.getLength() != i_values.getLength() )
+ throw IllegalArgumentException( OUString(), *this, 1 );
+
+ sal_Int32 const columnCount = i_columnIndexes.getLength();
+ if ( columnCount == 0 )
+ return;
+
+ for ( sal_Int32 const columnIndex : i_columnIndexes )
+ {
+ if ( ( columnIndex < 0 ) || ( columnIndex > m_nColumnCount ) )
+ throw IndexOutOfBoundsException( OUString(), *this );
+ }
+
+ RowData& rDataRow = m_aData[ i_rowIndex ];
+ for ( sal_Int32 col = 0; col < columnCount; ++col )
+ {
+ sal_Int32 const columnIndex = i_columnIndexes[ col ];
+ if ( o3tl::make_unsigned( columnIndex ) >= rDataRow.size() )
+ rDataRow.resize( columnIndex + 1 );
+
+ rDataRow[ columnIndex ].first = i_values[ col ];
+ }
+
+ auto aPair = ::std::minmax_element( i_columnIndexes.begin(), i_columnIndexes.end() );
+ sal_Int32 const firstAffectedColumn = *aPair.first;
+ sal_Int32 const lastAffectedColumn = *aPair.second;
+ broadcast(
+ GridDataEvent( *this, firstAffectedColumn, lastAffectedColumn, i_rowIndex, i_rowIndex ),
+ &XGridDataListener::dataChanged,
+ aGuard
+ );
+ }
+
+
+ void SAL_CALL DefaultGridDataModel::updateRowHeading( ::sal_Int32 i_rowIndex, const Any& i_heading )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ if ( ( i_rowIndex < 0 ) || ( o3tl::make_unsigned( i_rowIndex ) >= m_aRowHeaders.size() ) )
+ throw IndexOutOfBoundsException( OUString(), *this );
+
+ m_aRowHeaders[ i_rowIndex ] = i_heading;
+
+ broadcast(
+ GridDataEvent( *this, -1, -1, i_rowIndex, i_rowIndex ),
+ &XGridDataListener::rowHeadingChanged,
+ aGuard
+ );
+ }
+
+
+ void SAL_CALL DefaultGridDataModel::updateCellToolTip( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex, const Any& i_value )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+ impl_getCellDataAccess_throw( i_columnIndex, i_rowIndex ).second = i_value;
+ }
+
+
+ void SAL_CALL DefaultGridDataModel::updateRowToolTip( ::sal_Int32 i_rowIndex, const Any& i_value )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ RowData& rRowData = impl_getRowDataAccess_throw( i_rowIndex, m_nColumnCount );
+ for ( auto& rCell : rRowData )
+ rCell.second = i_value;
+ }
+
+
+ void SAL_CALL DefaultGridDataModel::addGridDataListener( const Reference< grid::XGridDataListener >& i_listener )
+ {
+ rBHelper.addListener( cppu::UnoType<XGridDataListener>::get(), i_listener );
+ }
+
+
+ void SAL_CALL DefaultGridDataModel::removeGridDataListener( const Reference< grid::XGridDataListener >& i_listener )
+ {
+ rBHelper.removeListener( cppu::UnoType<XGridDataListener>::get(), i_listener );
+ }
+
+
+ void SAL_CALL DefaultGridDataModel::disposing()
+ {
+ css::lang::EventObject aEvent;
+ aEvent.Source.set( *this );
+ rBHelper.aLC.disposeAndClear( aEvent );
+
+ ::osl::MutexGuard aGuard( m_aMutex );
+ GridData().swap(m_aData);
+ std::vector<Any>().swap(m_aRowHeaders);
+ m_nColumnCount = 0;
+ }
+
+
+ OUString SAL_CALL DefaultGridDataModel::getImplementationName( )
+ {
+ return "stardiv.Toolkit.DefaultGridDataModel";
+ }
+
+ sal_Bool SAL_CALL DefaultGridDataModel::supportsService( const OUString& ServiceName )
+ {
+ return cppu::supportsService(this, ServiceName);
+ }
+
+ Sequence< OUString > SAL_CALL DefaultGridDataModel::getSupportedServiceNames( )
+ {
+ return { "com.sun.star.awt.grid.DefaultGridDataModel" };
+ }
+
+
+ Reference< css::util::XCloneable > SAL_CALL DefaultGridDataModel::createClone( )
+ {
+ return new DefaultGridDataModel( *this );
+ }
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_DefaultGridDataModel_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new DefaultGridDataModel());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/grid/gridcolumn.cxx b/toolkit/source/controls/grid/gridcolumn.cxx
new file mode 100644
index 000000000..11a03e647
--- /dev/null
+++ b/toolkit/source/controls/grid/gridcolumn.cxx
@@ -0,0 +1,300 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "gridcolumn.hxx"
+
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <comphelper/servicehelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+namespace toolkit
+{
+ using namespace ::com::sun::star;
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::awt;
+ using namespace ::com::sun::star::awt::grid;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::util;
+ using namespace ::com::sun::star::style;
+
+
+ //= DefaultGridColumnModel
+
+
+ GridColumn::GridColumn()
+ :m_nIndex(-1)
+ ,m_nDataColumnIndex(-1)
+ ,m_nColumnWidth(4)
+ ,m_nMaxWidth(0)
+ ,m_nMinWidth(0)
+ ,m_nFlexibility(1)
+ ,m_bResizeable(true)
+ ,m_eHorizontalAlign( HorizontalAlignment_LEFT )
+ {
+ }
+
+
+ GridColumn::GridColumn( GridColumn const & i_copySource )
+ :m_aIdentifier( i_copySource.m_aIdentifier )
+ ,m_nIndex( -1 )
+ ,m_nDataColumnIndex( i_copySource.m_nDataColumnIndex )
+ ,m_nColumnWidth( i_copySource.m_nColumnWidth )
+ ,m_nMaxWidth( i_copySource.m_nMaxWidth )
+ ,m_nMinWidth( i_copySource.m_nMinWidth )
+ ,m_nFlexibility( i_copySource.m_nFlexibility )
+ ,m_bResizeable( i_copySource.m_bResizeable )
+ ,m_sTitle( i_copySource.m_sTitle )
+ ,m_sHelpText( i_copySource.m_sHelpText )
+ ,m_eHorizontalAlign( i_copySource.m_eHorizontalAlign )
+ {
+ }
+
+
+ GridColumn::~GridColumn()
+ {
+ }
+
+
+ void GridColumn::broadcast_changed( char const * const i_asciiAttributeName, const Any& i_oldValue, const Any& i_newValue,
+ std::unique_lock<std::mutex>& i_Guard )
+ {
+ Reference< XInterface > const xSource( static_cast< ::cppu::OWeakObject* >( this ) );
+ GridColumnEvent const aEvent(
+ xSource, OUString::createFromAscii( i_asciiAttributeName ),
+ i_oldValue, i_newValue, m_nIndex
+ );
+
+ maGridColumnListeners.notifyEach( i_Guard, &XGridColumnListener::columnChanged, aEvent );
+ }
+
+
+ css::uno::Any SAL_CALL GridColumn::getIdentifier()
+ {
+ std::unique_lock aGuard( m_aMutex );
+ return m_aIdentifier;
+ }
+
+
+ void SAL_CALL GridColumn::setIdentifier(const css::uno::Any & value)
+ {
+ std::unique_lock aGuard( m_aMutex );
+ m_aIdentifier = value;
+ }
+
+
+ ::sal_Int32 SAL_CALL GridColumn::getColumnWidth()
+ {
+ std::unique_lock aGuard( m_aMutex );
+ return m_nColumnWidth;
+ }
+
+
+ void SAL_CALL GridColumn::setColumnWidth(::sal_Int32 value)
+ {
+ impl_set( m_nColumnWidth, value, "ColumnWidth" );
+ }
+
+
+ ::sal_Int32 SAL_CALL GridColumn::getMaxWidth()
+ {
+ std::unique_lock aGuard( m_aMutex );
+ return m_nMaxWidth;
+ }
+
+
+ void SAL_CALL GridColumn::setMaxWidth(::sal_Int32 value)
+ {
+ impl_set( m_nMaxWidth, value, "MaxWidth" );
+ }
+
+
+ ::sal_Int32 SAL_CALL GridColumn::getMinWidth()
+ {
+ std::unique_lock aGuard( m_aMutex );
+ return m_nMinWidth;
+ }
+
+
+ void SAL_CALL GridColumn::setMinWidth(::sal_Int32 value)
+ {
+ impl_set( m_nMinWidth, value, "MinWidth" );
+ }
+
+
+ OUString SAL_CALL GridColumn::getTitle()
+ {
+ std::unique_lock aGuard( m_aMutex );
+ return m_sTitle;
+ }
+
+
+ void SAL_CALL GridColumn::setTitle(const OUString & value)
+ {
+ impl_set( m_sTitle, value, "Title" );
+ }
+
+
+ OUString SAL_CALL GridColumn::getHelpText()
+ {
+ std::unique_lock aGuard( m_aMutex );
+ return m_sHelpText;
+ }
+
+
+ void SAL_CALL GridColumn::setHelpText( const OUString & value )
+ {
+ impl_set( m_sHelpText, value, "HelpText" );
+ }
+
+
+ sal_Bool SAL_CALL GridColumn::getResizeable()
+ {
+ std::unique_lock aGuard( m_aMutex );
+ return m_bResizeable;
+ }
+
+
+ void SAL_CALL GridColumn::setResizeable(sal_Bool value)
+ {
+ impl_set( m_bResizeable, bool(value), "Resizeable" );
+ }
+
+
+ ::sal_Int32 SAL_CALL GridColumn::getFlexibility()
+ {
+ std::unique_lock aGuard( m_aMutex );
+ return m_nFlexibility;
+ }
+
+
+ void SAL_CALL GridColumn::setFlexibility( ::sal_Int32 i_value )
+ {
+ if ( i_value < 0 )
+ throw IllegalArgumentException( OUString(), *this, 1 );
+ impl_set( m_nFlexibility, i_value, "Flexibility" );
+ }
+
+
+ HorizontalAlignment SAL_CALL GridColumn::getHorizontalAlign()
+ {
+ std::unique_lock aGuard( m_aMutex );
+ return m_eHorizontalAlign;
+ }
+
+
+ void SAL_CALL GridColumn::setHorizontalAlign(HorizontalAlignment align)
+ {
+ impl_set( m_eHorizontalAlign, align, "HorizontalAlign" );
+ }
+
+
+ void SAL_CALL GridColumn::addGridColumnListener( const Reference< XGridColumnListener >& xListener )
+ {
+ std::unique_lock aGuard( m_aMutex );
+ maGridColumnListeners.addInterface( aGuard, xListener );
+ }
+
+
+ void SAL_CALL GridColumn::removeGridColumnListener( const Reference< XGridColumnListener >& xListener )
+ {
+ std::unique_lock aGuard( m_aMutex );
+ maGridColumnListeners.removeInterface( aGuard, xListener );
+ }
+
+
+ void GridColumn::disposing(std::unique_lock<std::mutex>&)
+ {
+ m_aIdentifier.clear();
+ m_sTitle.clear();
+ m_sHelpText.clear();
+ }
+
+
+ ::sal_Int32 SAL_CALL GridColumn::getIndex()
+ {
+ std::unique_lock aGuard( m_aMutex );
+ return m_nIndex;
+ }
+
+
+ void GridColumn::setIndex( sal_Int32 const i_index )
+ {
+ std::unique_lock aGuard( m_aMutex );
+ m_nIndex = i_index;
+ }
+
+
+ ::sal_Int32 SAL_CALL GridColumn::getDataColumnIndex()
+ {
+ std::unique_lock aGuard( m_aMutex );
+ return m_nDataColumnIndex;
+ }
+
+
+ void SAL_CALL GridColumn::setDataColumnIndex( ::sal_Int32 i_dataColumnIndex )
+ {
+ impl_set( m_nDataColumnIndex, i_dataColumnIndex, "DataColumnIndex" );
+ }
+
+
+ OUString SAL_CALL GridColumn::getImplementationName( )
+ {
+ return "org.openoffice.comp.toolkit.GridColumn";
+ }
+
+ sal_Bool SAL_CALL GridColumn::supportsService( const OUString& i_serviceName )
+ {
+ return cppu::supportsService(this, i_serviceName);
+ }
+
+ css::uno::Sequence< OUString > SAL_CALL GridColumn::getSupportedServiceNames( )
+ {
+ return { "com.sun.star.awt.grid.GridColumn" };
+ }
+
+
+ Reference< XCloneable > SAL_CALL GridColumn::createClone( )
+ {
+ return new GridColumn( *this );
+ }
+
+
+ sal_Int64 SAL_CALL GridColumn::getSomething( const Sequence< sal_Int8 >& i_identifier )
+ {
+ return comphelper::getSomethingImpl(i_identifier, this);
+ }
+
+
+ const Sequence< sal_Int8 > & GridColumn::getUnoTunnelId() noexcept
+ {
+ static const comphelper::UnoIdInit aId;
+ return aId.getSeq();
+ }
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+org_openoffice_comp_toolkit_GridColumn_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new toolkit::GridColumn());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/grid/gridcolumn.hxx b/toolkit/source/controls/grid/gridcolumn.hxx
new file mode 100644
index 000000000..8008c077d
--- /dev/null
+++ b/toolkit/source/controls/grid/gridcolumn.hxx
@@ -0,0 +1,128 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_TOOLKIT_SOURCE_CONTROLS_GRID_GRIDCOLUMN_HXX
+#define INCLUDED_TOOLKIT_SOURCE_CONTROLS_GRID_GRIDCOLUMN_HXX
+
+#include <com/sun/star/awt/grid/XGridColumn.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/style/HorizontalAlignment.hpp>
+
+#include <comphelper/compbase.hxx>
+#include <comphelper/interfacecontainer4.hxx>
+
+namespace toolkit
+{
+
+typedef comphelper::WeakComponentImplHelper < css::awt::grid::XGridColumn
+ , css::lang::XServiceInfo
+ , css::lang::XUnoTunnel
+ > GridColumn_Base;
+class GridColumn final : public GridColumn_Base
+{
+public:
+ GridColumn();
+ GridColumn( GridColumn const & i_copySource );
+ virtual ~GridColumn() override;
+
+ // css::awt::grid::XGridColumn
+ virtual css::uno::Any SAL_CALL getIdentifier() override;
+ virtual void SAL_CALL setIdentifier(const css::uno::Any & value) override;
+ virtual ::sal_Int32 SAL_CALL getColumnWidth() override;
+ virtual void SAL_CALL setColumnWidth(::sal_Int32 the_value) override;
+ virtual ::sal_Int32 SAL_CALL getMaxWidth() override;
+ virtual void SAL_CALL setMaxWidth(::sal_Int32 the_value) override;
+ virtual ::sal_Int32 SAL_CALL getMinWidth() override;
+ virtual void SAL_CALL setMinWidth(::sal_Int32 the_value) override;
+ virtual sal_Bool SAL_CALL getResizeable() override;
+ virtual void SAL_CALL setResizeable(sal_Bool the_value) override;
+ virtual ::sal_Int32 SAL_CALL getFlexibility() override;
+ virtual void SAL_CALL setFlexibility( ::sal_Int32 _flexibility ) override;
+ virtual OUString SAL_CALL getTitle() override;
+ virtual void SAL_CALL setTitle(const OUString & value) override;
+ virtual OUString SAL_CALL getHelpText() override;
+ virtual void SAL_CALL setHelpText(const OUString & value) override;
+ virtual ::sal_Int32 SAL_CALL getIndex() override;
+ virtual ::sal_Int32 SAL_CALL getDataColumnIndex() override;
+ virtual void SAL_CALL setDataColumnIndex( ::sal_Int32 i_dataColumnIndex ) override;
+ virtual css::style::HorizontalAlignment SAL_CALL getHorizontalAlign() override;
+ virtual void SAL_CALL setHorizontalAlign(css::style::HorizontalAlignment align) override;
+ virtual void SAL_CALL addGridColumnListener( const css::uno::Reference< css::awt::grid::XGridColumnListener >& xListener ) override;
+ virtual void SAL_CALL removeGridColumnListener( const css::uno::Reference< css::awt::grid::XGridColumnListener >& xListener ) override;
+
+ // OComponentHelper
+ virtual void disposing(std::unique_lock<std::mutex>&) override;
+
+ // XCloneable (base of XGridColumn)
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone( ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // XUnoTunnel and friends
+ virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& i_identifier ) override;
+ static const css::uno::Sequence< sal_Int8 > & getUnoTunnelId() noexcept;
+
+ // attribute access
+ void setIndex( sal_Int32 const i_index );
+
+private:
+ void broadcast_changed(
+ char const * const i_asciiAttributeName,
+ const css::uno::Any& i_oldValue,
+ const css::uno::Any& i_newValue,
+ std::unique_lock<std::mutex>& i_Guard
+ );
+
+ template< class TYPE >
+ void impl_set( TYPE & io_attribute, TYPE const & i_newValue, char const * i_attributeName )
+ {
+ std::unique_lock aGuard(m_aMutex);
+ if (m_bDisposed)
+ throw css::lang::DisposedException( OUString(), static_cast<cppu::OWeakObject*>(this) );
+ if ( io_attribute == i_newValue )
+ return;
+
+ TYPE const aOldValue( io_attribute );
+ io_attribute = i_newValue;
+ broadcast_changed( i_attributeName, css::uno::Any( aOldValue ), css::uno::Any( io_attribute ), aGuard );
+ }
+
+ css::uno::Any m_aIdentifier;
+ sal_Int32 m_nIndex;
+ sal_Int32 m_nDataColumnIndex;
+ sal_Int32 m_nColumnWidth;
+ sal_Int32 m_nMaxWidth;
+ sal_Int32 m_nMinWidth;
+ sal_Int32 m_nFlexibility;
+ bool m_bResizeable;
+ OUString m_sTitle;
+ OUString m_sHelpText;
+ css::style::HorizontalAlignment m_eHorizontalAlign;
+ comphelper::OInterfaceContainerHelper4<css::awt::grid::XGridColumnListener> maGridColumnListeners;
+};
+
+}
+
+#endif // INCLUDED_TOOLKIT_SOURCE_CONTROLS_GRID_GRIDCOLUMN_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/grid/gridcontrol.cxx b/toolkit/source/controls/grid/gridcontrol.cxx
new file mode 100644
index 000000000..4bf996c8e
--- /dev/null
+++ b/toolkit/source/controls/grid/gridcontrol.cxx
@@ -0,0 +1,460 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "gridcontrol.hxx"
+#include "grideventforwarder.hxx"
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/view/SelectionType.hpp>
+#include <com/sun/star/awt/grid/XGridControl.hpp>
+#include <com/sun/star/awt/grid/XGridDataModel.hpp>
+#include <com/sun/star/awt/grid/XGridRowSelection.hpp>
+#include <com/sun/star/awt/grid/XMutableGridDataModel.hpp>
+#include <com/sun/star/awt/grid/DefaultGridDataModel.hpp>
+#include <com/sun/star/awt/grid/SortableGridDataModel.hpp>
+#include <com/sun/star/awt/grid/DefaultGridColumnModel.hpp>
+#include <toolkit/helper/property.hxx>
+#include <tools/diagnose_ex.h>
+#include <toolkit/controls/unocontrolbase.hxx>
+#include <toolkit/controls/unocontrolmodel.hxx>
+#include <toolkit/helper/listenermultiplexer.hxx>
+
+#include <memory>
+
+#include <helper/unopropertyarrayhelper.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::awt::grid;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::view;
+using namespace ::com::sun::star::util;
+
+namespace toolkit {
+
+namespace
+{
+ Reference< XGridDataModel > lcl_getDefaultDataModel_throw( const Reference<XComponentContext> & i_context )
+ {
+ Reference< XMutableGridDataModel > const xDelegatorModel( DefaultGridDataModel::create( i_context ), UNO_SET_THROW );
+ Reference< XGridDataModel > const xDataModel( SortableGridDataModel::create( i_context, xDelegatorModel ), UNO_QUERY_THROW );
+ return xDataModel;
+ }
+
+ Reference< XGridColumnModel > lcl_getDefaultColumnModel_throw( const Reference<XComponentContext> & i_context )
+ {
+ Reference< XGridColumnModel > const xColumnModel = DefaultGridColumnModel::create( i_context );
+ return xColumnModel;
+ }
+}
+
+
+UnoGridModel::UnoGridModel( const css::uno::Reference< css::uno::XComponentContext >& rxContext )
+ :UnoControlModel( rxContext )
+{
+ ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_BORDER );
+ ImplRegisterProperty( BASEPROPERTY_BORDERCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
+ ImplRegisterProperty( BASEPROPERTY_ENABLED );
+ ImplRegisterProperty( BASEPROPERTY_FILLCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
+ ImplRegisterProperty( BASEPROPERTY_HELPURL );
+ ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
+ ImplRegisterProperty( BASEPROPERTY_SIZEABLE ); // resizable
+ ImplRegisterProperty( BASEPROPERTY_HSCROLL );
+ ImplRegisterProperty( BASEPROPERTY_VSCROLL );
+ ImplRegisterProperty( BASEPROPERTY_TABSTOP );
+ ImplRegisterProperty( BASEPROPERTY_GRID_SHOWROWHEADER );
+ ImplRegisterProperty( BASEPROPERTY_ROW_HEADER_WIDTH );
+ ImplRegisterProperty( BASEPROPERTY_GRID_SHOWCOLUMNHEADER );
+ ImplRegisterProperty( BASEPROPERTY_COLUMN_HEADER_HEIGHT );
+ ImplRegisterProperty( BASEPROPERTY_ROW_HEIGHT );
+ ImplRegisterProperty( BASEPROPERTY_GRID_DATAMODEL, Any( lcl_getDefaultDataModel_throw( m_xContext ) ) );
+ ImplRegisterProperty( BASEPROPERTY_GRID_COLUMNMODEL, Any( lcl_getDefaultColumnModel_throw( m_xContext ) ) );
+ ImplRegisterProperty( BASEPROPERTY_GRID_SELECTIONMODE );
+ ImplRegisterProperty( BASEPROPERTY_FONTRELIEF );
+ ImplRegisterProperty( BASEPROPERTY_FONTEMPHASISMARK );
+ ImplRegisterProperty( BASEPROPERTY_FONTDESCRIPTOR );
+ ImplRegisterProperty( BASEPROPERTY_TEXTCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_TEXTLINECOLOR );
+ ImplRegisterProperty( BASEPROPERTY_USE_GRID_LINES );
+ ImplRegisterProperty( BASEPROPERTY_GRID_LINE_COLOR );
+ ImplRegisterProperty( BASEPROPERTY_GRID_HEADER_BACKGROUND );
+ ImplRegisterProperty( BASEPROPERTY_GRID_HEADER_TEXT_COLOR );
+ ImplRegisterProperty( BASEPROPERTY_GRID_ROW_BACKGROUND_COLORS );
+ ImplRegisterProperty( BASEPROPERTY_ACTIVE_SEL_BACKGROUND_COLOR );
+ ImplRegisterProperty( BASEPROPERTY_INACTIVE_SEL_BACKGROUND_COLOR );
+ ImplRegisterProperty( BASEPROPERTY_ACTIVE_SEL_TEXT_COLOR );
+ ImplRegisterProperty( BASEPROPERTY_INACTIVE_SEL_TEXT_COLOR );
+ ImplRegisterProperty( BASEPROPERTY_VERTICALALIGN );
+}
+
+
+UnoGridModel::UnoGridModel( const UnoGridModel& rModel )
+ :UnoControlModel( rModel )
+{
+ osl_atomic_increment( &m_refCount );
+ {
+ Reference< XGridDataModel > xDataModel;
+ // clone the data model
+ const Reference< XFastPropertySet > xCloneSource( &const_cast< UnoGridModel& >( rModel ) );
+ try
+ {
+ const Reference< XCloneable > xCloneable( xCloneSource->getFastPropertyValue( BASEPROPERTY_GRID_DATAMODEL ), UNO_QUERY_THROW );
+ xDataModel.set( xCloneable->createClone(), UNO_QUERY_THROW );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+ if ( !xDataModel.is() )
+ xDataModel = lcl_getDefaultDataModel_throw( m_xContext );
+ UnoControlModel::setFastPropertyValue_NoBroadcast( BASEPROPERTY_GRID_DATAMODEL, Any( xDataModel ) );
+ // do *not* use setFastPropertyValue here: The UnoControlModel ctor made a simple copy of all property values,
+ // so before this call here, we share our data model with the own of the clone source. setFastPropertyValue,
+ // then, disposes the old data model - which means the data model which in fact belongs to the clone source.
+ // so, call the UnoControlModel's impl-method for setting the value.
+
+ // clone the column model
+ Reference< XGridColumnModel > xColumnModel;
+ try
+ {
+ const Reference< XCloneable > xCloneable( xCloneSource->getFastPropertyValue( BASEPROPERTY_GRID_COLUMNMODEL ), UNO_QUERY_THROW );
+ xColumnModel.set( xCloneable->createClone(), UNO_QUERY_THROW );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+ if ( !xColumnModel.is() )
+ xColumnModel = lcl_getDefaultColumnModel_throw( m_xContext );
+ UnoControlModel::setFastPropertyValue_NoBroadcast( BASEPROPERTY_GRID_COLUMNMODEL, Any( xColumnModel ) );
+ // same comment as above: do not use our own setPropertyValue here.
+ }
+ osl_atomic_decrement( &m_refCount );
+}
+
+
+rtl::Reference<UnoControlModel> UnoGridModel::Clone() const
+{
+ return new UnoGridModel( *this );
+}
+
+
+namespace
+{
+ void lcl_dispose_nothrow( const Any& i_component )
+ {
+ try
+ {
+ const Reference< XComponent > xComponent( i_component, UNO_QUERY_THROW );
+ xComponent->dispose();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+ }
+}
+
+
+void SAL_CALL UnoGridModel::dispose( )
+{
+ lcl_dispose_nothrow( getFastPropertyValue( BASEPROPERTY_GRID_COLUMNMODEL ) );
+ lcl_dispose_nothrow( getFastPropertyValue( BASEPROPERTY_GRID_DATAMODEL ) );
+
+ UnoControlModel::dispose();
+}
+
+
+void SAL_CALL UnoGridModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue )
+{
+ Any aOldSubModel;
+ if ( ( nHandle == BASEPROPERTY_GRID_COLUMNMODEL ) || ( nHandle == BASEPROPERTY_GRID_DATAMODEL ) )
+ {
+ aOldSubModel = getFastPropertyValue( nHandle );
+ if ( aOldSubModel == rValue )
+ {
+ OSL_ENSURE( false, "UnoGridModel::setFastPropertyValue_NoBroadcast: setting the same value, again!" );
+ // shouldn't this have been caught by convertFastPropertyValue?
+ aOldSubModel.clear();
+ }
+ }
+
+ UnoControlModel::setFastPropertyValue_NoBroadcast( nHandle, rValue );
+
+ if ( aOldSubModel.hasValue() )
+ lcl_dispose_nothrow( aOldSubModel );
+}
+
+
+OUString UnoGridModel::getServiceName()
+{
+ return "com.sun.star.awt.grid.UnoControlGridModel";
+}
+
+
+Any UnoGridModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ switch( nPropId )
+ {
+ case BASEPROPERTY_DEFAULTCONTROL:
+ return uno::Any( OUString("com.sun.star.awt.grid.UnoControlGrid") );
+ case BASEPROPERTY_GRID_SELECTIONMODE:
+ return uno::Any( SelectionType(1) );
+ case BASEPROPERTY_GRID_SHOWROWHEADER:
+ case BASEPROPERTY_USE_GRID_LINES:
+ return uno::Any( false );
+ case BASEPROPERTY_ROW_HEADER_WIDTH:
+ return uno::Any( sal_Int32( 10 ) );
+ case BASEPROPERTY_GRID_SHOWCOLUMNHEADER:
+ return uno::Any( true );
+ case BASEPROPERTY_COLUMN_HEADER_HEIGHT:
+ case BASEPROPERTY_ROW_HEIGHT:
+ case BASEPROPERTY_GRID_HEADER_BACKGROUND:
+ case BASEPROPERTY_GRID_HEADER_TEXT_COLOR:
+ case BASEPROPERTY_GRID_LINE_COLOR:
+ case BASEPROPERTY_GRID_ROW_BACKGROUND_COLORS:
+ case BASEPROPERTY_ACTIVE_SEL_BACKGROUND_COLOR:
+ case BASEPROPERTY_INACTIVE_SEL_BACKGROUND_COLOR:
+ case BASEPROPERTY_ACTIVE_SEL_TEXT_COLOR:
+ case BASEPROPERTY_INACTIVE_SEL_TEXT_COLOR:
+ return Any();
+ default:
+ return UnoControlModel::ImplGetDefaultValue( nPropId );
+ }
+
+}
+
+
+::cppu::IPropertyArrayHelper& UnoGridModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+
+// XMultiPropertySet
+Reference< XPropertySetInfo > UnoGridModel::getPropertySetInfo( )
+{
+ static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+
+//= UnoGridControl
+
+UnoGridControl::UnoGridControl()
+ :m_aSelectionListeners( *this )
+ ,m_pEventForwarder( new toolkit::GridEventForwarder( *this ) )
+{
+}
+
+
+UnoGridControl::~UnoGridControl()
+{
+}
+
+
+OUString UnoGridControl::GetComponentServiceName() const
+{
+ return "Grid";
+}
+
+
+void SAL_CALL UnoGridControl::dispose( )
+{
+ lang::EventObject aEvt;
+ aEvt.Source = static_cast<cppu::OWeakObject*>(this);
+ m_aSelectionListeners.disposeAndClear( aEvt );
+ UnoControl::dispose();
+}
+
+
+void SAL_CALL UnoGridControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer > & rParentPeer )
+{
+ UnoControlBase::createPeer( rxToolkit, rParentPeer );
+
+ const Reference< XGridRowSelection > xGrid( getPeer(), UNO_QUERY_THROW );
+ xGrid->addSelectionListener( &m_aSelectionListeners );
+}
+
+
+namespace
+{
+ void lcl_setEventForwarding( const Reference< XControlModel >& i_gridControlModel, const std::unique_ptr< toolkit::GridEventForwarder >& i_listener,
+ bool const i_add )
+ {
+ const Reference< XPropertySet > xModelProps( i_gridControlModel, UNO_QUERY );
+ if ( !xModelProps.is() )
+ return;
+
+ try
+ {
+ Reference< XContainer > const xColModel(
+ xModelProps->getPropertyValue("ColumnModel"),
+ UNO_QUERY_THROW );
+ if ( i_add )
+ xColModel->addContainerListener( i_listener.get() );
+ else
+ xColModel->removeContainerListener( i_listener.get() );
+
+ Reference< XGridDataModel > const xDataModel(
+ xModelProps->getPropertyValue("GridDataModel"),
+ UNO_QUERY_THROW
+ );
+ Reference< XMutableGridDataModel > const xMutableDataModel( xDataModel, UNO_QUERY );
+ if ( xMutableDataModel.is() )
+ {
+ if ( i_add )
+ xMutableDataModel->addGridDataListener( i_listener.get() );
+ else
+ xMutableDataModel->removeGridDataListener( i_listener.get() );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+ }
+}
+
+
+sal_Bool SAL_CALL UnoGridControl::setModel( const Reference< XControlModel >& i_model )
+{
+ lcl_setEventForwarding( getModel(), m_pEventForwarder, false );
+ if ( !UnoGridControl_Base::setModel( i_model ) )
+ return false;
+ lcl_setEventForwarding( getModel(), m_pEventForwarder, true );
+ return true;
+}
+
+
+::sal_Int32 UnoGridControl::getRowAtPoint(::sal_Int32 x, ::sal_Int32 y)
+{
+ Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
+ return xGrid->getRowAtPoint( x, y );
+}
+
+
+::sal_Int32 UnoGridControl::getColumnAtPoint(::sal_Int32 x, ::sal_Int32 y)
+{
+ Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
+ return xGrid->getColumnAtPoint( x, y );
+}
+
+
+::sal_Int32 SAL_CALL UnoGridControl::getCurrentColumn( )
+{
+ Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
+ return xGrid->getCurrentColumn();
+}
+
+
+::sal_Int32 SAL_CALL UnoGridControl::getCurrentRow( )
+{
+ Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
+ return xGrid->getCurrentRow();
+}
+
+
+void SAL_CALL UnoGridControl::goToCell( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex )
+{
+ Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
+ xGrid->goToCell( i_columnIndex, i_rowIndex );
+}
+
+
+void SAL_CALL UnoGridControl::selectRow( ::sal_Int32 i_rowIndex )
+{
+ Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->selectRow( i_rowIndex );
+}
+
+
+void SAL_CALL UnoGridControl::selectAllRows()
+{
+ Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->selectAllRows();
+}
+
+
+void SAL_CALL UnoGridControl::deselectRow( ::sal_Int32 i_rowIndex )
+{
+ Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->deselectRow( i_rowIndex );
+}
+
+
+void SAL_CALL UnoGridControl::deselectAllRows()
+{
+ Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->deselectAllRows();
+}
+
+
+css::uno::Sequence< ::sal_Int32 > SAL_CALL UnoGridControl::getSelectedRows()
+{
+ return Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->getSelectedRows();
+}
+
+
+sal_Bool SAL_CALL UnoGridControl::hasSelectedRows()
+{
+ return Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->hasSelectedRows();
+}
+
+
+sal_Bool SAL_CALL UnoGridControl::isRowSelected(::sal_Int32 index)
+{
+ return Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->isRowSelected( index );
+}
+
+
+void SAL_CALL UnoGridControl::addSelectionListener(const css::uno::Reference< css::awt::grid::XGridSelectionListener > & listener)
+{
+ m_aSelectionListeners.addInterface( listener );
+}
+
+
+void SAL_CALL UnoGridControl::removeSelectionListener(const css::uno::Reference< css::awt::grid::XGridSelectionListener > & listener)
+{
+ m_aSelectionListeners.removeInterface( listener );
+}
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_GridControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new toolkit::UnoGridControl());
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_GridControlModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new toolkit::UnoGridModel(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/grid/gridcontrol.hxx b/toolkit/source/controls/grid/gridcontrol.hxx
new file mode 100644
index 000000000..6b4f8152b
--- /dev/null
+++ b/toolkit/source/controls/grid/gridcontrol.hxx
@@ -0,0 +1,142 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_TOOLKIT_SOURCE_CONTROLS_GRID_GRIDCONTROL_HXX
+#define INCLUDED_TOOLKIT_SOURCE_CONTROLS_GRID_GRIDCONTROL_HXX
+
+#include <com/sun/star/awt/grid/XGridControl.hpp>
+#include <com/sun/star/awt/grid/XGridRowSelection.hpp>
+
+#include <toolkit/controls/unocontrolbase.hxx>
+#include <toolkit/controls/unocontrolmodel.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <toolkit/helper/listenermultiplexer.hxx>
+
+#include <memory>
+
+namespace toolkit
+{
+
+class GridEventForwarder;
+
+
+// = UnoGridModel
+
+class UnoGridModel : public UnoControlModel
+{
+protected:
+ css::uno::Any ImplGetDefaultValue( sal_uInt16 nPropId ) const override;
+ ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+public:
+ explicit UnoGridModel( const css::uno::Reference< css::uno::XComponentContext >& i_factory );
+ UnoGridModel( const UnoGridModel& rModel );
+
+ rtl::Reference<UnoControlModel> Clone() const override;
+
+ // css::lang::XComponent
+ void SAL_CALL dispose( ) override;
+
+ // css::beans::XMultiPropertySet
+ css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+
+ // css::io::XPersistObject
+ OUString SAL_CALL getServiceName() override;
+
+ // OPropertySetHelper
+ void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const css::uno::Any& rValue ) override;
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName() override
+ { return "stardiv.Toolkit.GridControlModel"; }
+
+ css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
+ {
+ auto s(UnoControlModel::getSupportedServiceNames());
+ s.realloc(s.getLength() + 1);
+ s.getArray()[s.getLength() - 1] = "com.sun.star.awt.grid.UnoControlGridModel";
+ return s;
+ }
+};
+
+
+// = UnoGridControl
+
+typedef ::cppu::ImplInheritanceHelper < UnoControlBase
+ , css::awt::grid::XGridControl
+ , css::awt::grid::XGridRowSelection
+ > UnoGridControl_Base;
+class UnoGridControl : public UnoGridControl_Base
+{
+public:
+ UnoGridControl();
+ OUString GetComponentServiceName() const override;
+
+ // css::lang::XComponent
+ void SAL_CALL dispose( ) override;
+
+ // css::awt::XControl
+ void SAL_CALL createPeer( const css::uno::Reference< css::awt::XToolkit >& Toolkit, const css::uno::Reference< css::awt::XWindowPeer >& Parent ) override;
+ sal_Bool SAL_CALL setModel( const css::uno::Reference< css::awt::XControlModel >& rxModel ) override;
+
+ // css::awt::grid::XGridControl
+ virtual ::sal_Int32 SAL_CALL getColumnAtPoint(::sal_Int32 x, ::sal_Int32 y) override;
+ virtual ::sal_Int32 SAL_CALL getRowAtPoint(::sal_Int32 x, ::sal_Int32 y) override;
+ virtual ::sal_Int32 SAL_CALL getCurrentColumn( ) override;
+ virtual ::sal_Int32 SAL_CALL getCurrentRow( ) override;
+ virtual void SAL_CALL goToCell( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex ) override;
+
+ // css::awt::grid::XGridRowSelection
+ virtual void SAL_CALL selectRow( ::sal_Int32 i_rowIndex ) override;
+ virtual void SAL_CALL selectAllRows() override;
+ virtual void SAL_CALL deselectRow( ::sal_Int32 i_rowIndex ) override;
+ virtual void SAL_CALL deselectAllRows() override;
+ virtual css::uno::Sequence< ::sal_Int32 > SAL_CALL getSelectedRows() override;
+ virtual sal_Bool SAL_CALL hasSelectedRows() override;
+ virtual sal_Bool SAL_CALL isRowSelected(::sal_Int32 index) override;
+ virtual void SAL_CALL addSelectionListener(const css::uno::Reference< css::awt::grid::XGridSelectionListener > & listener) override;
+ virtual void SAL_CALL removeSelectionListener(const css::uno::Reference< css::awt::grid::XGridSelectionListener > & listener) override;
+
+ // css::lang::XServiceInfo
+ OUString SAL_CALL getImplementationName() override
+ { return "stardiv.Toolkit.GridControl"; }
+
+ css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
+ {
+ auto s(UnoControlBase::getSupportedServiceNames());
+ s.realloc(s.getLength() + 1);
+ s.getArray()[s.getLength() - 1] = "com.sun.star.awt.grid.UnoControlGrid";
+ return s;
+ }
+
+ using UnoControl::getPeer;
+
+protected:
+ virtual ~UnoGridControl() override;
+
+private:
+ SelectionListenerMultiplexer m_aSelectionListeners;
+ std::unique_ptr< GridEventForwarder > m_pEventForwarder;
+};
+
+} // toolkit
+
+#endif // _TOOLKIT_TREE_CONTROL_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/grid/grideventforwarder.cxx b/toolkit/source/controls/grid/grideventforwarder.cxx
new file mode 100644
index 000000000..5baf5fdda
--- /dev/null
+++ b/toolkit/source/controls/grid/grideventforwarder.cxx
@@ -0,0 +1,128 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "grideventforwarder.hxx"
+#include "gridcontrol.hxx"
+
+
+namespace toolkit
+{
+
+
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::awt::grid::GridDataEvent;
+ using ::com::sun::star::container::ContainerEvent;
+ using ::com::sun::star::lang::EventObject;
+
+
+ //= GridEventForwarder
+
+
+ GridEventForwarder::GridEventForwarder( UnoGridControl& i_parent )
+ :m_parent( i_parent )
+ {
+ }
+
+
+ GridEventForwarder::~GridEventForwarder()
+ {
+ }
+
+
+ void SAL_CALL GridEventForwarder::acquire() noexcept
+ {
+ m_parent.acquire();
+ }
+
+
+ void SAL_CALL GridEventForwarder::release() noexcept
+ {
+ m_parent.release();
+ }
+
+
+ void SAL_CALL GridEventForwarder::rowsInserted( const GridDataEvent& i_event )
+ {
+ Reference< XGridDataListener > xPeer( m_parent.getPeer(), UNO_QUERY );
+ if ( xPeer.is() )
+ xPeer->rowsInserted( i_event );
+ }
+
+
+ void SAL_CALL GridEventForwarder::rowsRemoved( const GridDataEvent& i_event )
+ {
+ Reference< XGridDataListener > xPeer( m_parent.getPeer(), UNO_QUERY );
+ if ( xPeer.is() )
+ xPeer->rowsRemoved( i_event );
+ }
+
+
+ void SAL_CALL GridEventForwarder::dataChanged( const GridDataEvent& i_event )
+ {
+ Reference< XGridDataListener > xPeer( m_parent.getPeer(), UNO_QUERY );
+ if ( xPeer.is() )
+ xPeer->dataChanged( i_event );
+ }
+
+
+ void SAL_CALL GridEventForwarder::rowHeadingChanged( const GridDataEvent& i_event )
+ {
+ Reference< XGridDataListener > xPeer( m_parent.getPeer(), UNO_QUERY );
+ if ( xPeer.is() )
+ xPeer->rowHeadingChanged( i_event );
+ }
+
+
+ void SAL_CALL GridEventForwarder::elementInserted( const ContainerEvent& i_event )
+ {
+ Reference< XContainerListener > xPeer( m_parent.getPeer(), UNO_QUERY );
+ if ( xPeer.is() )
+ xPeer->elementInserted( i_event );
+ }
+
+
+ void SAL_CALL GridEventForwarder::elementRemoved( const ContainerEvent& i_event )
+ {
+ Reference< XContainerListener > xPeer( m_parent.getPeer(), UNO_QUERY );
+ if ( xPeer.is() )
+ xPeer->elementRemoved( i_event );
+ }
+
+
+ void SAL_CALL GridEventForwarder::elementReplaced( const ContainerEvent& i_event )
+ {
+ Reference< XContainerListener > xPeer( m_parent.getPeer(), UNO_QUERY );
+ if ( xPeer.is() )
+ xPeer->elementReplaced( i_event );
+ }
+
+
+ void SAL_CALL GridEventForwarder::disposing( const EventObject& i_event )
+ {
+ Reference< XEventListener > xPeer( m_parent.getPeer(), UNO_QUERY );
+ if ( xPeer.is() )
+ xPeer->disposing( i_event );
+ }
+
+
+} // namespace toolkit
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/grid/grideventforwarder.hxx b/toolkit/source/controls/grid/grideventforwarder.hxx
new file mode 100644
index 000000000..9578e62ee
--- /dev/null
+++ b/toolkit/source/controls/grid/grideventforwarder.hxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_TOOLKIT_SOURCE_CONTROLS_GRID_GRIDEVENTFORWARDER_HXX
+#define INCLUDED_TOOLKIT_SOURCE_CONTROLS_GRID_GRIDEVENTFORWARDER_HXX
+
+#include <com/sun/star/awt/grid/XGridDataListener.hpp>
+#include <com/sun/star/container/XContainerListener.hpp>
+
+#include <cppuhelper/implbase2.hxx>
+
+
+namespace toolkit
+{
+
+
+ class UnoGridControl;
+
+
+ //= GridEventForwarder
+
+ typedef ::cppu::ImplHelper2 < css::awt::grid::XGridDataListener
+ , css::container::XContainerListener
+ > GridEventForwarder_Base;
+
+ class GridEventForwarder : public GridEventForwarder_Base
+ {
+ public:
+ explicit GridEventForwarder( UnoGridControl& i_parent );
+ virtual ~GridEventForwarder();
+
+ public:
+ // XInterface
+ virtual void SAL_CALL acquire() noexcept override;
+ virtual void SAL_CALL release() noexcept override;
+
+ // XGridDataListener
+ virtual void SAL_CALL rowsInserted( const css::awt::grid::GridDataEvent& Event ) override;
+ virtual void SAL_CALL rowsRemoved( const css::awt::grid::GridDataEvent& Event ) override;
+ virtual void SAL_CALL dataChanged( const css::awt::grid::GridDataEvent& Event ) override;
+ virtual void SAL_CALL rowHeadingChanged( const css::awt::grid::GridDataEvent& Event ) override;
+
+ // XContainerListener
+ virtual void SAL_CALL elementInserted( const css::container::ContainerEvent& Event ) override;
+ virtual void SAL_CALL elementRemoved( const css::container::ContainerEvent& Event ) override;
+ virtual void SAL_CALL elementReplaced( const css::container::ContainerEvent& Event ) override;
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& i_event ) override;
+
+ private:
+ UnoGridControl& m_parent;
+ };
+
+
+} // namespace toolkit
+
+
+#endif // INCLUDED_TOOLKIT_SOURCE_CONTROLS_GRID_GRIDEVENTFORWARDER_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/grid/sortablegriddatamodel.cxx b/toolkit/source/controls/grid/sortablegriddatamodel.cxx
new file mode 100644
index 000000000..6269d727d
--- /dev/null
+++ b/toolkit/source/controls/grid/sortablegriddatamodel.cxx
@@ -0,0 +1,928 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include <com/sun/star/i18n/Collator.hpp>
+#include <com/sun/star/i18n/XCollator.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/NotInitializedException.hpp>
+#include <com/sun/star/ucb/AlreadyInitializedException.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/awt/grid/XGridDataListener.hpp>
+#include <com/sun/star/awt/grid/XSortableMutableGridDataModel.hpp>
+
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/implbase1.hxx>
+#include <comphelper/anycompare.hxx>
+#include <comphelper/componentguard.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <tools/diagnose_ex.h>
+#include <i18nlangtag/languagetag.hxx>
+#include <o3tl/safeint.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+
+using namespace css::awt;
+using namespace css::awt::grid;
+using namespace css::i18n;
+using namespace css::lang;
+using namespace css::ucb;
+using namespace css::uno;
+
+namespace {
+
+class SortableGridDataModel;
+class MethodGuard;
+
+typedef ::cppu::WeakComponentImplHelper < css::awt::grid::XSortableMutableGridDataModel
+ , css::lang::XServiceInfo
+ , css::lang::XInitialization
+ > SortableGridDataModel_Base;
+typedef ::cppu::ImplHelper1 < css::awt::grid::XGridDataListener
+ > SortableGridDataModel_PrivateBase;
+class SortableGridDataModel :public ::cppu::BaseMutex
+ ,public SortableGridDataModel_Base
+ ,public SortableGridDataModel_PrivateBase
+{
+public:
+ explicit SortableGridDataModel( const css::uno::Reference< css::uno::XComponentContext > & rxContext );
+ SortableGridDataModel( SortableGridDataModel const & i_copySource );
+
+ bool isInitialized() const { return m_isInitialized; }
+
+protected:
+ virtual ~SortableGridDataModel() override;
+
+public:
+ // XSortableGridData
+ virtual void SAL_CALL sortByColumn( ::sal_Int32 ColumnIndex, sal_Bool SortAscending ) override;
+ virtual void SAL_CALL removeColumnSort( ) override;
+ virtual css::beans::Pair< ::sal_Int32, sal_Bool > SAL_CALL getCurrentSortOrder( ) override;
+
+ // XMutableGridDataModel
+ virtual void SAL_CALL addRow( const css::uno::Any& Heading, const css::uno::Sequence< css::uno::Any >& Data ) override;
+ virtual void SAL_CALL addRows( const css::uno::Sequence< css::uno::Any >& Headings, const css::uno::Sequence< css::uno::Sequence< css::uno::Any > >& Data ) override;
+ virtual void SAL_CALL insertRow( ::sal_Int32 i_index, const css::uno::Any& i_heading, const css::uno::Sequence< css::uno::Any >& Data ) override;
+ virtual void SAL_CALL insertRows( ::sal_Int32 i_index, const css::uno::Sequence< css::uno::Any>& Headings, const css::uno::Sequence< css::uno::Sequence< css::uno::Any > >& Data ) override;
+ virtual void SAL_CALL removeRow( ::sal_Int32 RowIndex ) override;
+ virtual void SAL_CALL removeAllRows( ) override;
+ virtual void SAL_CALL updateCellData( ::sal_Int32 ColumnIndex, ::sal_Int32 RowIndex, const css::uno::Any& Value ) override;
+ virtual void SAL_CALL updateRowData( const css::uno::Sequence< ::sal_Int32 >& ColumnIndexes, ::sal_Int32 RowIndex, const css::uno::Sequence< css::uno::Any >& Values ) override;
+ virtual void SAL_CALL updateRowHeading( ::sal_Int32 RowIndex, const css::uno::Any& Heading ) override;
+ virtual void SAL_CALL updateCellToolTip( ::sal_Int32 ColumnIndex, ::sal_Int32 RowIndex, const css::uno::Any& Value ) override;
+ virtual void SAL_CALL updateRowToolTip( ::sal_Int32 RowIndex, const css::uno::Any& Value ) override;
+ virtual void SAL_CALL addGridDataListener( const css::uno::Reference< css::awt::grid::XGridDataListener >& Listener ) override;
+ virtual void SAL_CALL removeGridDataListener( const css::uno::Reference< css::awt::grid::XGridDataListener >& Listener ) override;
+
+ // XGridDataModel
+ virtual ::sal_Int32 SAL_CALL getRowCount() override;
+ virtual ::sal_Int32 SAL_CALL getColumnCount() override;
+ virtual css::uno::Any SAL_CALL getCellData( ::sal_Int32 Column, ::sal_Int32 RowIndex ) override;
+ virtual css::uno::Any SAL_CALL getCellToolTip( ::sal_Int32 Column, ::sal_Int32 RowIndex ) override;
+ virtual css::uno::Any SAL_CALL getRowHeading( ::sal_Int32 RowIndex ) override;
+ virtual css::uno::Sequence< css::uno::Any > SAL_CALL getRowData( ::sal_Int32 RowIndex ) override;
+
+ // OComponentHelper
+ virtual void SAL_CALL disposing() override;
+
+ // XCloneable
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone( ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
+
+ // XGridDataListener
+ virtual void SAL_CALL rowsInserted( const css::awt::grid::GridDataEvent& Event ) override;
+ virtual void SAL_CALL rowsRemoved( const css::awt::grid::GridDataEvent& Event ) override;
+ virtual void SAL_CALL dataChanged( const css::awt::grid::GridDataEvent& Event ) override;
+ virtual void SAL_CALL rowHeadingChanged( const css::awt::grid::GridDataEvent& Event ) override;
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& i_event ) override;
+
+ // XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override;
+ virtual void SAL_CALL acquire( ) noexcept final override;
+ virtual void SAL_CALL release( ) noexcept override;
+
+ // XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
+ virtual css::uno::Sequence< ::sal_Int8 > SAL_CALL getImplementationId( ) override;
+
+private:
+ /** translates the given public index into one to be passed to our delegator
+ @throws css::lang::IndexOutOfBoundsException
+ if the given index does not denote a valid row
+ */
+ ::sal_Int32 impl_getPrivateRowIndex_throw( ::sal_Int32 const i_publicRowIndex ) const;
+
+ /** translates the given private row index to a public one
+ */
+ ::sal_Int32 impl_getPublicRowIndex_nothrow( ::sal_Int32 const i_privateRowIndex ) const;
+
+ bool impl_isSorted_nothrow() const
+ {
+ return m_currentSortColumn >= 0;
+ }
+
+ /** rebuilds the index translation structure.
+
+ Neither <member>m_currentSortColumn</member> nor <member>m_sortAscending</member> are touched by this method.
+ Also, the given column index is not checked, this is the responsibility of the caller.
+ */
+ bool impl_reIndex_nothrow( ::sal_Int32 const i_columnIndex, bool const i_sortAscending );
+
+ /** translates the given event, obtained from our delegator, to a version which can be broadcasted to our own
+ clients.
+ */
+ css::awt::grid::GridDataEvent
+ impl_createPublicEvent( css::awt::grid::GridDataEvent const & i_originalEvent ) const;
+
+ /** broadcasts the given event to our registered XGridDataListeners
+ */
+ void impl_broadcast(
+ void ( SAL_CALL css::awt::grid::XGridDataListener::*i_listenerMethod )( const css::awt::grid::GridDataEvent & ),
+ css::awt::grid::GridDataEvent const & i_publicEvent,
+ MethodGuard& i_instanceLock
+ );
+
+ /** rebuilds our indexes, notifying row removal and row addition events
+
+ First, a rowsRemoved event is notified to our registered listeners. Then, the index translation tables are
+ rebuilt, and a rowsInserted event is notified.
+
+ Only to be called when we're sorted.
+ */
+ void impl_rebuildIndexesAndNotify( MethodGuard& i_instanceLock );
+
+ /** removes the current sorting, and notifies a change of all data
+ */
+ void impl_removeColumnSort( MethodGuard& i_instanceLock );
+
+ /** removes the current sorting, without any broadcast
+ */
+ void impl_removeColumnSort_noBroadcast();
+
+private:
+ css::uno::Reference< css::uno::XComponentContext > m_xContext;
+ bool m_isInitialized;
+ css::uno::Reference< css::awt::grid::XMutableGridDataModel > m_delegator;
+ css::uno::Reference< css::i18n::XCollator > m_collator;
+ ::sal_Int32 m_currentSortColumn;
+ bool m_sortAscending;
+ ::std::vector< ::sal_Int32 > m_publicToPrivateRowIndex;
+ ::std::vector< ::sal_Int32 > m_privateToPublicRowIndex;
+};
+
+class MethodGuard : public ::comphelper::ComponentGuard
+{
+public:
+ MethodGuard( SortableGridDataModel& i_component, ::cppu::OBroadcastHelper & i_broadcastHelper )
+ :comphelper::ComponentGuard( i_component, i_broadcastHelper )
+ {
+ if ( !i_component.isInitialized() )
+ throw css::lang::NotInitializedException( OUString(), i_component );
+ }
+};
+
+template< class STLCONTAINER >
+void lcl_clear( STLCONTAINER& i_container )
+{
+ STLCONTAINER().swap(i_container);
+}
+
+ SortableGridDataModel::SortableGridDataModel( Reference< XComponentContext > const & rxContext )
+ :SortableGridDataModel_Base( m_aMutex )
+ ,SortableGridDataModel_PrivateBase()
+ ,m_xContext( rxContext )
+ ,m_isInitialized( false )
+ ,m_delegator()
+ ,m_collator()
+ ,m_currentSortColumn( -1 )
+ ,m_sortAscending( true )
+ ,m_publicToPrivateRowIndex()
+ ,m_privateToPublicRowIndex()
+ {
+ }
+
+
+ SortableGridDataModel::SortableGridDataModel( SortableGridDataModel const & i_copySource )
+ :cppu::BaseMutex()
+ ,SortableGridDataModel_Base( m_aMutex )
+ ,SortableGridDataModel_PrivateBase()
+ ,m_xContext( i_copySource.m_xContext )
+ ,m_isInitialized( true )
+ ,m_delegator()
+ ,m_collator( i_copySource.m_collator )
+ ,m_currentSortColumn( i_copySource.m_currentSortColumn )
+ ,m_sortAscending( i_copySource.m_sortAscending )
+ ,m_publicToPrivateRowIndex( i_copySource.m_publicToPrivateRowIndex )
+ ,m_privateToPublicRowIndex( i_copySource.m_privateToPublicRowIndex )
+ {
+ ENSURE_OR_THROW( i_copySource.m_delegator.is(),
+ "not expected to be called for a disposed copy source!" );
+ m_delegator.set( i_copySource.m_delegator->createClone(), UNO_QUERY_THROW );
+ }
+
+
+ SortableGridDataModel::~SortableGridDataModel()
+ {
+ if ( !rBHelper.bDisposed )
+ {
+ acquire();
+ dispose();
+ }
+ }
+
+
+ Any SAL_CALL SortableGridDataModel::queryInterface( const Type& aType )
+ {
+ Any aReturn( SortableGridDataModel_Base::queryInterface( aType ) );
+ if ( !aReturn.hasValue() )
+ aReturn = SortableGridDataModel_PrivateBase::queryInterface( aType );
+ return aReturn;
+ }
+
+
+ void SAL_CALL SortableGridDataModel::acquire( ) noexcept
+ {
+ SortableGridDataModel_Base::acquire();
+ }
+
+
+ void SAL_CALL SortableGridDataModel::release( ) noexcept
+ {
+ SortableGridDataModel_Base::release();
+ }
+
+
+ Sequence< Type > SAL_CALL SortableGridDataModel::getTypes( )
+ {
+ return SortableGridDataModel_Base::getTypes();
+ // don't expose the types got via SortableGridDataModel_PrivateBase - they're private, after all
+ }
+
+
+ Sequence< ::sal_Int8 > SAL_CALL SortableGridDataModel::getImplementationId( )
+ {
+ return css::uno::Sequence<sal_Int8>();
+ }
+
+ Reference< XCollator > lcl_loadDefaultCollator_throw( const Reference<XComponentContext> & rxContext )
+ {
+ Reference< XCollator > const xCollator = Collator::create( rxContext );
+ xCollator->loadDefaultCollator( Application::GetSettings().GetLanguageTag().getLocale(), 0 );
+ return xCollator;
+ }
+
+ void SAL_CALL SortableGridDataModel::initialize( const Sequence< Any >& i_arguments )
+ {
+ ::comphelper::ComponentGuard aGuard( *this, rBHelper );
+
+ if ( m_delegator.is() )
+ throw AlreadyInitializedException( OUString(), *this );
+
+ Reference< XMutableGridDataModel > xDelegator;
+ Reference< XCollator > xCollator;
+ switch ( i_arguments.getLength() )
+ {
+ case 1: // SortableGridDataModel.create( XMutableGridDataModel )
+ xDelegator.set( i_arguments[0], UNO_QUERY );
+ xCollator = lcl_loadDefaultCollator_throw( m_xContext );
+ break;
+
+ case 2: // SortableGridDataModel.createWithCollator( XMutableGridDataModel, XCollator )
+ xDelegator.set( i_arguments[0], UNO_QUERY );
+ xCollator.set( i_arguments[1], UNO_QUERY );
+ if ( !xCollator.is() )
+ throw IllegalArgumentException( OUString(), *this, 2 );
+ break;
+ }
+ if ( !xDelegator.is() )
+ throw IllegalArgumentException( OUString(), *this, 1 );
+
+ m_delegator = xDelegator;
+ m_collator = xCollator;
+
+ m_delegator->addGridDataListener( this );
+
+ m_isInitialized = true;
+ }
+
+
+ GridDataEvent SortableGridDataModel::impl_createPublicEvent( GridDataEvent const & i_originalEvent ) const
+ {
+ GridDataEvent aEvent( i_originalEvent );
+ aEvent.Source = *const_cast< SortableGridDataModel* >( this );
+ aEvent.FirstRow = impl_getPublicRowIndex_nothrow( aEvent.FirstRow );
+ aEvent.LastRow = impl_getPublicRowIndex_nothrow( aEvent.LastRow );
+ return aEvent;
+ }
+
+
+ void SortableGridDataModel::impl_broadcast( void ( SAL_CALL XGridDataListener::*i_listenerMethod )( const GridDataEvent & ),
+ GridDataEvent const & i_publicEvent, MethodGuard& i_instanceLock )
+ {
+ ::cppu::OInterfaceContainerHelper* pListeners = rBHelper.getContainer( cppu::UnoType<XGridDataListener>::get() );
+ if ( pListeners == nullptr )
+ return;
+
+ i_instanceLock.clear();
+ pListeners->notifyEach( i_listenerMethod, i_publicEvent );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::rowsInserted( const GridDataEvent& i_event )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ if ( impl_isSorted_nothrow() )
+ {
+ // no infrastructure is in place currently to sort the new row to its proper location,
+ // so we remove the sorting here.
+ impl_removeColumnSort( aGuard );
+ aGuard.reset();
+ }
+
+ GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
+ impl_broadcast( &XGridDataListener::rowsInserted, aEvent, aGuard );
+ }
+
+ void lcl_decrementValuesGreaterThan( ::std::vector< ::sal_Int32 > & io_indexMap, sal_Int32 const i_threshold )
+ {
+ for ( auto& rIndex : io_indexMap )
+ {
+ if ( rIndex >= i_threshold )
+ --rIndex;
+ }
+ }
+
+ void SortableGridDataModel::impl_rebuildIndexesAndNotify( MethodGuard& i_instanceLock )
+ {
+ OSL_PRECOND( impl_isSorted_nothrow(), "SortableGridDataModel::impl_rebuildIndexesAndNotify: illegal call!" );
+
+ // clear the indexes
+ lcl_clear( m_publicToPrivateRowIndex );
+ lcl_clear( m_privateToPublicRowIndex );
+
+ // rebuild the index
+ if ( !impl_reIndex_nothrow( m_currentSortColumn, m_sortAscending ) )
+ {
+ impl_removeColumnSort( i_instanceLock );
+ return;
+ }
+
+ // broadcast an artificial event, saying that all rows have been removed
+ GridDataEvent const aRemovalEvent( *this, -1, -1, -1, -1 );
+ impl_broadcast( &XGridDataListener::rowsRemoved, aRemovalEvent, i_instanceLock );
+ i_instanceLock.reset();
+
+ // broadcast an artificial event, saying that n rows have been added
+ GridDataEvent const aAdditionEvent( *this, -1, -1, 0, m_delegator->getRowCount() - 1 );
+ impl_broadcast( &XGridDataListener::rowsInserted, aAdditionEvent, i_instanceLock );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::rowsRemoved( const GridDataEvent& i_event )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ // if the data is not sorted, broadcast the event unchanged
+ if ( !impl_isSorted_nothrow() )
+ {
+ GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
+ impl_broadcast( &XGridDataListener::rowsRemoved, aEvent, aGuard );
+ return;
+ }
+
+ // if all rows have been removed, also simply multiplex to own listeners
+ if ( i_event.FirstRow < 0 )
+ {
+ lcl_clear( m_publicToPrivateRowIndex );
+ lcl_clear( m_privateToPublicRowIndex );
+ GridDataEvent aEvent( i_event );
+ aEvent.Source = *this;
+ impl_broadcast( &XGridDataListener::rowsRemoved, aEvent, aGuard );
+ return;
+ }
+
+ bool needReIndex = false;
+ if ( i_event.FirstRow != i_event.LastRow )
+ {
+ OSL_ENSURE( false, "SortableGridDataModel::rowsRemoved: missing implementation - removal of multiple rows!" );
+ needReIndex = true;
+ }
+ else if ( o3tl::make_unsigned( i_event.FirstRow ) >= m_privateToPublicRowIndex.size() )
+ {
+ OSL_ENSURE( false, "SortableGridDataModel::rowsRemoved: inconsistent/wrong data!" );
+ needReIndex = true;
+ }
+
+ if ( needReIndex )
+ {
+ impl_rebuildIndexesAndNotify( aGuard );
+ return;
+ }
+
+ // build public event version
+ GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
+
+ // remove the entries from the index maps
+ sal_Int32 const privateIndex = i_event.FirstRow;
+ sal_Int32 const publicIndex = aEvent.FirstRow;
+
+ m_publicToPrivateRowIndex.erase( m_publicToPrivateRowIndex.begin() + publicIndex );
+ m_privateToPublicRowIndex.erase( m_privateToPublicRowIndex.begin() + privateIndex );
+
+ // adjust remaining entries in the index maps
+ lcl_decrementValuesGreaterThan( m_publicToPrivateRowIndex, privateIndex );
+ lcl_decrementValuesGreaterThan( m_privateToPublicRowIndex, publicIndex );
+
+ // broadcast the event
+ impl_broadcast( &XGridDataListener::rowsRemoved, aEvent, aGuard );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::dataChanged( const GridDataEvent& i_event )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
+ impl_broadcast( &XGridDataListener::dataChanged, aEvent, aGuard );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::rowHeadingChanged( const GridDataEvent& i_event )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ GridDataEvent const aEvent( impl_createPublicEvent( i_event ) );
+ impl_broadcast( &XGridDataListener::rowHeadingChanged, aEvent, aGuard );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::disposing( const EventObject& )
+ {
+ }
+
+ class CellDataLessComparison
+ {
+ public:
+ CellDataLessComparison(
+ ::std::vector< Any > const & i_data,
+ ::comphelper::IKeyPredicateLess const & i_predicate,
+ bool const i_sortAscending
+ )
+ :m_data( i_data )
+ ,m_predicate( i_predicate )
+ ,m_sortAscending( i_sortAscending )
+ {
+ }
+
+ bool operator()( sal_Int32 const i_lhs, sal_Int32 const i_rhs ) const
+ {
+ Any const & lhs = m_data[ i_lhs ];
+ Any const & rhs = m_data[ i_rhs ];
+ // <VOID/> is less than everything else
+ if ( !lhs.hasValue() )
+ return m_sortAscending;
+ if ( !rhs.hasValue() )
+ return !m_sortAscending;
+
+ // actually compare
+ if ( m_sortAscending )
+ return m_predicate.isLess( lhs, rhs );
+ else
+ return m_predicate.isLess( rhs, lhs );
+ }
+
+ private:
+ ::std::vector< Any > const & m_data;
+ ::comphelper::IKeyPredicateLess const & m_predicate;
+ bool const m_sortAscending;
+ };
+
+ bool SortableGridDataModel::impl_reIndex_nothrow( ::sal_Int32 const i_columnIndex, bool const i_sortAscending )
+ {
+ ::sal_Int32 const rowCount( getRowCount() );
+ ::std::vector< ::sal_Int32 > aPublicToPrivate( rowCount );
+
+ try
+ {
+ // build an unsorted translation table, and retrieve the unsorted data
+ ::std::vector< Any > aColumnData( rowCount );
+ Type dataType;
+ for ( ::sal_Int32 rowIndex = 0; rowIndex < rowCount; ++rowIndex )
+ {
+ aColumnData[ rowIndex ] = m_delegator->getCellData( i_columnIndex, rowIndex );
+ aPublicToPrivate[ rowIndex ] = rowIndex;
+
+ // determine the data types we assume for the complete column
+ if ( ( dataType.getTypeClass() == TypeClass_VOID ) && aColumnData[ rowIndex ].hasValue() )
+ dataType = aColumnData[ rowIndex ].getValueType();
+ }
+
+ // get predicate object
+ ::std::unique_ptr< ::comphelper::IKeyPredicateLess > const pPredicate( ::comphelper::getStandardLessPredicate( dataType, m_collator ) );
+ ENSURE_OR_RETURN_FALSE(
+ pPredicate, "SortableGridDataModel::impl_reIndex_nothrow: no sortable data found!");
+
+ // then sort
+ CellDataLessComparison const aComparator( aColumnData, *pPredicate, i_sortAscending );
+ ::std::sort( aPublicToPrivate.begin(), aPublicToPrivate.end(), aComparator );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ return false;
+ }
+
+ // also build the "private to public" mapping
+ ::std::vector< sal_Int32 > aPrivateToPublic( aPublicToPrivate.size() );
+ for ( size_t i=0; i<aPublicToPrivate.size(); ++i )
+ aPrivateToPublic[ aPublicToPrivate[i] ] = i;
+
+ m_publicToPrivateRowIndex.swap( aPublicToPrivate );
+ m_privateToPublicRowIndex.swap( aPrivateToPublic );
+
+ return true;
+ }
+
+
+ void SAL_CALL SortableGridDataModel::sortByColumn( ::sal_Int32 i_columnIndex, sal_Bool i_sortAscending )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ if ( ( i_columnIndex < 0 ) || ( i_columnIndex >= getColumnCount() ) )
+ throw IndexOutOfBoundsException( OUString(), *this );
+
+ if ( !impl_reIndex_nothrow( i_columnIndex, i_sortAscending ) )
+ return;
+
+ m_currentSortColumn = i_columnIndex;
+ m_sortAscending = i_sortAscending;
+
+ impl_broadcast(
+ &XGridDataListener::dataChanged,
+ GridDataEvent( *this, -1, -1, -1, -1 ),
+ aGuard
+ );
+ }
+
+
+ void SortableGridDataModel::impl_removeColumnSort_noBroadcast()
+ {
+ lcl_clear( m_publicToPrivateRowIndex );
+ lcl_clear( m_privateToPublicRowIndex );
+
+ m_currentSortColumn = -1;
+ m_sortAscending = true;
+ }
+
+
+ void SortableGridDataModel::impl_removeColumnSort( MethodGuard& i_instanceLock )
+ {
+ impl_removeColumnSort_noBroadcast();
+ impl_broadcast(
+ &XGridDataListener::dataChanged,
+ GridDataEvent( *this, -1, -1, -1, -1 ),
+ i_instanceLock
+ );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::removeColumnSort( )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+ impl_removeColumnSort( aGuard );
+ }
+
+
+ css::beans::Pair< ::sal_Int32, sal_Bool > SAL_CALL SortableGridDataModel::getCurrentSortOrder( )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ return css::beans::Pair< ::sal_Int32, sal_Bool >( m_currentSortColumn, m_sortAscending );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::addRow( const Any& i_heading, const Sequence< Any >& i_data )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ delegator->addRow( i_heading, i_data );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::addRows( const Sequence< Any >& i_headings, const Sequence< Sequence< Any > >& i_data )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ delegator->addRows( i_headings, i_data );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::insertRow( ::sal_Int32 i_index, const Any& i_heading, const Sequence< Any >& i_data )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ ::sal_Int32 const rowIndex = i_index == getRowCount() ? i_index : impl_getPrivateRowIndex_throw( i_index );
+ // note that |RowCount| is a valid index in this method, but not for impl_getPrivateRowIndex_throw
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ delegator->insertRow( rowIndex, i_heading, i_data );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::insertRows( ::sal_Int32 i_index, const Sequence< Any>& i_headings, const Sequence< Sequence< Any > >& i_data )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ ::sal_Int32 const rowIndex = i_index == getRowCount() ? i_index : impl_getPrivateRowIndex_throw( i_index );
+ // note that |RowCount| is a valid index in this method, but not for impl_getPrivateRowIndex_throw
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ delegator->insertRows( rowIndex, i_headings, i_data );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::removeRow( ::sal_Int32 i_rowIndex )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ delegator->removeRow( rowIndex );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::removeAllRows( )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ delegator->removeAllRows();
+ }
+
+
+ void SAL_CALL SortableGridDataModel::updateCellData( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex, const Any& i_value )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ delegator->updateCellData( i_columnIndex, rowIndex, i_value );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::updateRowData( const Sequence< ::sal_Int32 >& i_columnIndexes, ::sal_Int32 i_rowIndex, const Sequence< Any >& i_values )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ delegator->updateRowData( i_columnIndexes, rowIndex, i_values );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::updateRowHeading( ::sal_Int32 i_rowIndex, const Any& i_heading )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ delegator->updateRowHeading( rowIndex, i_heading );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::updateCellToolTip( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex, const Any& i_value )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ delegator->updateCellToolTip( i_columnIndex, rowIndex, i_value );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::updateRowToolTip( ::sal_Int32 i_rowIndex, const Any& i_value )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ delegator->updateRowToolTip( rowIndex, i_value );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::addGridDataListener( const Reference< XGridDataListener >& i_listener )
+ {
+ rBHelper.addListener( cppu::UnoType<XGridDataListener>::get(), i_listener );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::removeGridDataListener( const Reference< XGridDataListener >& i_listener )
+ {
+ rBHelper.removeListener( cppu::UnoType<XGridDataListener>::get(), i_listener );
+ }
+
+
+ ::sal_Int32 SAL_CALL SortableGridDataModel::getRowCount()
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ return delegator->getRowCount();
+ }
+
+
+ ::sal_Int32 SAL_CALL SortableGridDataModel::getColumnCount()
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ return delegator->getColumnCount();
+ }
+
+
+ Any SAL_CALL SortableGridDataModel::getCellData( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ return delegator->getCellData( i_columnIndex, rowIndex );
+ }
+
+
+ Any SAL_CALL SortableGridDataModel::getCellToolTip( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ return delegator->getCellToolTip( i_columnIndex, rowIndex );
+ }
+
+
+ Any SAL_CALL SortableGridDataModel::getRowHeading( ::sal_Int32 i_rowIndex )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ return delegator->getRowHeading( rowIndex );
+ }
+
+
+ Sequence< Any > SAL_CALL SortableGridDataModel::getRowData( ::sal_Int32 i_rowIndex )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ ::sal_Int32 const rowIndex = impl_getPrivateRowIndex_throw( i_rowIndex );
+
+ Reference< XMutableGridDataModel > const delegator( m_delegator );
+ aGuard.clear();
+ return delegator->getRowData( rowIndex );
+ }
+
+
+ void SAL_CALL SortableGridDataModel::disposing()
+ {
+ m_currentSortColumn = -1;
+
+ Reference< XComponent > const delegatorComponent( m_delegator );
+ m_delegator->removeGridDataListener( this );
+ m_delegator.clear();
+ delegatorComponent->dispose();
+
+ Reference< XComponent > const collatorComponent( m_collator, UNO_QUERY );
+ m_collator.clear();
+ if ( collatorComponent.is() )
+ collatorComponent->dispose();
+
+ lcl_clear( m_publicToPrivateRowIndex );
+ lcl_clear( m_privateToPublicRowIndex );
+ }
+
+
+ Reference< css::util::XCloneable > SAL_CALL SortableGridDataModel::createClone( )
+ {
+ MethodGuard aGuard( *this, rBHelper );
+
+ return new SortableGridDataModel( *this );
+ }
+
+
+ OUString SAL_CALL SortableGridDataModel::getImplementationName( )
+ {
+ return "org.openoffice.comp.toolkit.SortableGridDataModel";
+ }
+
+ sal_Bool SAL_CALL SortableGridDataModel::supportsService( const OUString& i_serviceName )
+ {
+ return cppu::supportsService(this, i_serviceName);
+ }
+
+ Sequence< OUString > SAL_CALL SortableGridDataModel::getSupportedServiceNames( )
+ {
+ return { "com.sun.star.awt.grid.SortableGridDataModel" };
+ }
+
+
+ ::sal_Int32 SortableGridDataModel::impl_getPrivateRowIndex_throw( ::sal_Int32 const i_publicRowIndex ) const
+ {
+ if ( ( i_publicRowIndex < 0 ) || ( i_publicRowIndex >= m_delegator->getRowCount() ) )
+ throw IndexOutOfBoundsException( OUString(), *const_cast< SortableGridDataModel* >( this ) );
+
+ if ( !impl_isSorted_nothrow() )
+ // no need to translate anything
+ return i_publicRowIndex;
+
+ ENSURE_OR_RETURN( o3tl::make_unsigned( i_publicRowIndex ) < m_publicToPrivateRowIndex.size(),
+ "SortableGridDataModel::impl_getPrivateRowIndex_throw: inconsistency!", i_publicRowIndex );
+ // obviously the translation table contains too few elements - it should have exactly |getRowCount()|
+ // elements
+
+ return m_publicToPrivateRowIndex[ i_publicRowIndex ];
+ }
+
+
+ ::sal_Int32 SortableGridDataModel::impl_getPublicRowIndex_nothrow( ::sal_Int32 const i_privateRowIndex ) const
+ {
+ if ( !impl_isSorted_nothrow() )
+ // no need to translate anything
+ return i_privateRowIndex;
+
+ if ( i_privateRowIndex < 0 )
+ return i_privateRowIndex;
+
+ ENSURE_OR_RETURN( o3tl::make_unsigned( i_privateRowIndex ) < m_privateToPublicRowIndex.size(),
+ "SortableGridDataModel::impl_getPublicRowIndex_nothrow: invalid index!", i_privateRowIndex );
+
+ return m_privateToPublicRowIndex[ i_privateRowIndex ];
+ }
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+org_openoffice_comp_toolkit_SortableGridDataModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new SortableGridDataModel(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/roadmapcontrol.cxx b/toolkit/source/controls/roadmapcontrol.cxx
new file mode 100644
index 000000000..2640dc6b5
--- /dev/null
+++ b/toolkit/source/controls/roadmapcontrol.cxx
@@ -0,0 +1,513 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <controls/roadmapcontrol.hxx>
+#include <controls/roadmapentry.hxx>
+#include <toolkit/helper/property.hxx>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <helper/unopropertyarrayhelper.hxx>
+
+namespace toolkit
+{
+
+
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::awt;
+ using namespace ::com::sun::star::lang;
+ using namespace ::com::sun::star::beans;
+ using namespace ::com::sun::star::container;
+
+
+// helper
+
+
+static void lcl_throwIllegalArgumentException( )
+{ // throwing is expensive (in terms of code size), thus we hope the compiler does not inline this...
+ throw IllegalArgumentException();
+}
+
+static void lcl_throwIndexOutOfBoundsException( )
+{ // throwing is expensive (in terms of code size), thus we hope the compiler does not inline this...
+ throw IndexOutOfBoundsException();
+}
+
+
+ // = UnoControlRoadmapModel
+
+
+ UnoControlRoadmapModel::UnoControlRoadmapModel( const Reference< XComponentContext >& i_factory )
+ :UnoControlRoadmapModel_Base( i_factory )
+ ,maContainerListeners( *this )
+ {
+ ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_BORDER );
+ ImplRegisterProperty( BASEPROPERTY_BORDERCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
+ ImplRegisterProperty( BASEPROPERTY_FONTDESCRIPTOR );
+ ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
+ ImplRegisterProperty( BASEPROPERTY_HELPURL );
+ ImplRegisterProperty( BASEPROPERTY_IMAGEURL );
+ ImplRegisterProperty( BASEPROPERTY_GRAPHIC );
+ ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
+ ImplRegisterProperty( BASEPROPERTY_COMPLETE );
+ ImplRegisterProperty( BASEPROPERTY_ACTIVATED );
+ ImplRegisterProperty( BASEPROPERTY_CURRENTITEMID );
+ ImplRegisterProperty( BASEPROPERTY_TABSTOP );
+ ImplRegisterProperty( BASEPROPERTY_TEXT );
+ }
+
+
+ OUString UnoControlRoadmapModel::getServiceName()
+ {
+ return "stardiv.vcl.controlmodel.Roadmap";
+ }
+
+ OUString UnoControlRoadmapModel::getImplementationName()
+ {
+ return "stardiv.Toolkit.UnoControlRoadmapModel";
+ }
+
+ css::uno::Sequence<OUString>
+ UnoControlRoadmapModel::getSupportedServiceNames()
+ {
+ auto s(UnoControlRoadmapModel_Base::getSupportedServiceNames());
+ s.realloc(s.getLength() + 2);
+ auto ps = s.getArray();
+ ps[s.getLength() - 2] = "com.sun.star.awt.UnoControlRoadmapModel";
+ ps[s.getLength() - 1] = "stardiv.vcl.controlmodel.Roadmap";
+ return s;
+ }
+
+ Any UnoControlRoadmapModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+ {
+ Any aReturn;
+ switch (nPropId)
+ {
+ case BASEPROPERTY_COMPLETE:
+ aReturn <<= true;
+ break;
+ case BASEPROPERTY_ACTIVATED:
+ aReturn <<= true;
+ break;
+ case BASEPROPERTY_CURRENTITEMID:
+ aReturn <<= sal_Int16(-1);
+ break;
+ case BASEPROPERTY_TEXT:
+ break;
+ case BASEPROPERTY_BORDER:
+ aReturn <<= sal_Int16(2); // No Border
+ break;
+ case BASEPROPERTY_DEFAULTCONTROL:
+ aReturn <<= OUString( "stardiv.vcl.control.Roadmap" );
+ break;
+ default : aReturn = UnoControlRoadmapModel_Base::ImplGetDefaultValue( nPropId ); break;
+ }
+
+ return aReturn;
+ }
+
+
+ Reference< XInterface > SAL_CALL UnoControlRoadmapModel::createInstance( )
+ {
+ rtl::Reference<ORoadmapEntry> pRoadmapItem = new ORoadmapEntry();
+ Reference< XInterface > xNewRoadmapItem = static_cast<cppu::OWeakObject*>(pRoadmapItem.get());
+ return xNewRoadmapItem;
+ }
+
+
+ Reference< XInterface > SAL_CALL UnoControlRoadmapModel::createInstanceWithArguments( const Sequence< Any >& /*aArguments*/ )
+ {
+ // Todo: implementation of the arguments handling
+ rtl::Reference<ORoadmapEntry> pRoadmapItem = new ORoadmapEntry();
+ Reference< XInterface > xNewRoadmapItem = static_cast<cppu::OWeakObject*>(pRoadmapItem.get());
+ return xNewRoadmapItem;
+ }
+
+
+ IMPLEMENT_FORWARD_XTYPEPROVIDER2( UnoControlRoadmapModel, UnoControlRoadmapModel_Base, UnoControlRoadmapModel_IBase )
+
+
+ css::uno::Any SAL_CALL UnoControlRoadmapModel::queryAggregation( const css::uno::Type & rType )
+ {
+ Any aRet = UnoControlRoadmapModel_Base::queryAggregation( rType );
+ if ( !aRet.hasValue() )
+ aRet = UnoControlRoadmapModel_IBase::queryInterface( rType );
+ return aRet;
+ }
+
+
+ ::cppu::IPropertyArrayHelper& UnoControlRoadmapModel::getInfoHelper()
+ {
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+ }
+
+
+ // beans::XMultiPropertySet
+
+ Reference< XPropertySetInfo > UnoControlRoadmapModel::getPropertySetInfo( )
+ {
+ static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+ }
+
+
+ sal_Int32 SAL_CALL UnoControlRoadmapModel::getCount()
+ {
+ return maRoadmapItems.size();
+ }
+
+ Any SAL_CALL UnoControlRoadmapModel::getByIndex( sal_Int32 Index )
+ {
+ if ((Index < 0) || ( o3tl::make_unsigned(Index) >= maRoadmapItems.size()))
+ lcl_throwIndexOutOfBoundsException( );
+ Any aAny( maRoadmapItems.at( Index ) );
+ return aAny;
+ }
+
+
+ void UnoControlRoadmapModel::MakeRMItemValidation( sal_Int32 Index, const Reference< XInterface >& xRoadmapItem )
+ {
+ if (( Index < 0 ) || (o3tl::make_unsigned(Index) > maRoadmapItems.size()) )
+ lcl_throwIndexOutOfBoundsException( );
+ if ( !xRoadmapItem.is() )
+ lcl_throwIllegalArgumentException();
+ Reference< XServiceInfo > xServiceInfo( xRoadmapItem, UNO_QUERY );
+ bool bIsRoadmapItem = xServiceInfo->supportsService("com.sun.star.awt.RoadmapItem");
+ if ( !bIsRoadmapItem )
+ lcl_throwIllegalArgumentException();
+ }
+
+
+ void UnoControlRoadmapModel::SetRMItemDefaultProperties( const Reference< XInterface >& xRoadmapItem)
+ {
+ Reference< XPropertySet > xPropertySet( xRoadmapItem, UNO_QUERY );
+ Reference< XPropertySet > xProps( xRoadmapItem, UNO_QUERY );
+ if ( xProps.is() )
+ {
+ sal_Int32 LocID = 0;
+ Any aValue = xPropertySet->getPropertyValue("ID");
+ aValue >>= LocID;
+ if (LocID < 0) // index may not be smaller than zero
+ {
+ xPropertySet->setPropertyValue("ID", Any(GetUniqueID()) );
+ }
+ }
+ }
+
+
+// The performance of this method could certainly be improved.
+// As long as only vectors with up to 10 elements are
+// involved it should be sufficient
+ sal_Int32 UnoControlRoadmapModel::GetUniqueID()
+ {
+ Any aAny;
+ bool bIncrement = true;
+ sal_Int32 CurID = 0;
+ sal_Int32 n_CurItemID = 0;
+ Reference< XInterface > CurRoadmapItem;
+ while ( bIncrement )
+ {
+ bIncrement = false;
+ for ( const auto& rRoadmapItem : maRoadmapItems )
+ {
+ CurRoadmapItem = rRoadmapItem;
+ Reference< XPropertySet > xPropertySet( CurRoadmapItem, UNO_QUERY );
+ aAny = xPropertySet->getPropertyValue("ID");
+ aAny >>= n_CurItemID;
+ if (n_CurItemID == CurID)
+ {
+ bIncrement = true;
+ CurID++;
+ break;
+ }
+ }
+ }
+ return CurID;
+ }
+
+
+ ContainerEvent UnoControlRoadmapModel::GetContainerEvent(sal_Int32 Index, const Reference< XInterface >& xRoadmapItem)
+ {
+ ContainerEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.Element <<= xRoadmapItem;
+ aEvent.Accessor <<= Index;
+ return aEvent;
+ }
+
+
+ sal_Int16 UnoControlRoadmapModel::GetCurrentItemID( const Reference< XPropertySet >& xPropertySet )
+ {
+ Any aAny = xPropertySet->getPropertyValue( GetPropertyName( BASEPROPERTY_CURRENTITEMID ) );
+ sal_Int16 n_CurrentItemID = 0;
+ aAny >>= n_CurrentItemID;
+ return n_CurrentItemID;
+ }
+
+
+ void SAL_CALL UnoControlRoadmapModel::insertByIndex( const sal_Int32 Index, const Any& Element)
+ {
+ if ( ( Index >= ( static_cast<sal_Int32>(maRoadmapItems.size()) + 1 ) ) || (Index < 0))
+ lcl_throwIndexOutOfBoundsException( );
+ Reference< XInterface > xRoadmapItem;
+ Element >>= xRoadmapItem;
+ MakeRMItemValidation( Index, xRoadmapItem);
+ SetRMItemDefaultProperties( xRoadmapItem );
+ maRoadmapItems.insert( maRoadmapItems.begin() + Index, xRoadmapItem);
+ ContainerEvent aEvent = GetContainerEvent(Index, xRoadmapItem);
+ maContainerListeners.elementInserted( aEvent );
+ Reference< XPropertySet > xPropertySet( this );
+ sal_Int16 n_CurrentItemID = GetCurrentItemID( xPropertySet );
+ if ( Index <= n_CurrentItemID )
+ {
+ Any aAny(static_cast<sal_Int16>( n_CurrentItemID + 1 ) );
+ xPropertySet->setPropertyValue( GetPropertyName( BASEPROPERTY_CURRENTITEMID ), aAny );
+ }
+ }
+
+
+ void SAL_CALL UnoControlRoadmapModel::removeByIndex( sal_Int32 Index)
+ {
+ if ((Index < 0) || ( o3tl::make_unsigned(Index) > maRoadmapItems.size()))
+ lcl_throwIndexOutOfBoundsException( );
+ Reference< XInterface > xRoadmapItem;
+ maRoadmapItems.erase( maRoadmapItems.begin() + Index );
+ ContainerEvent aEvent = GetContainerEvent(Index, xRoadmapItem);
+ maContainerListeners.elementRemoved( aEvent );
+ Reference< XPropertySet > xPropertySet( this );
+ sal_Int16 n_CurrentItemID = GetCurrentItemID( xPropertySet );
+ Any aAny;
+ if ( Index > n_CurrentItemID )
+ return;
+
+ if ( n_CurrentItemID >= static_cast<sal_Int32>(maRoadmapItems.size()) )
+ {
+ n_CurrentItemID = sal::static_int_cast< sal_Int16 >(
+ maRoadmapItems.size()-1);
+ if ( n_CurrentItemID < 0 )
+ return;
+ aAny <<= n_CurrentItemID;
+ }
+ else if (Index == n_CurrentItemID)
+ aAny <<= sal_Int16(-1);
+ else if( Index < n_CurrentItemID)
+ aAny <<= static_cast<sal_Int16>( n_CurrentItemID - 1 );
+ xPropertySet->setPropertyValue( GetPropertyName( BASEPROPERTY_CURRENTITEMID ), aAny );
+ }
+
+
+ void SAL_CALL UnoControlRoadmapModel::replaceByIndex( const sal_Int32 Index, const Any& Element)
+ {
+ Reference< XInterface > xRoadmapItem;
+ Element >>= xRoadmapItem;
+ MakeRMItemValidation( Index, xRoadmapItem);
+ SetRMItemDefaultProperties( xRoadmapItem );
+ maRoadmapItems.erase( maRoadmapItems.begin() + Index );
+ maRoadmapItems.insert( maRoadmapItems.begin() + Index, xRoadmapItem); //push_back( xRoadmapItem );
+ ContainerEvent aEvent = GetContainerEvent(Index, xRoadmapItem);
+ maContainerListeners.elementReplaced( aEvent );
+ }
+
+
+ Type SAL_CALL UnoControlRoadmapModel::getElementType()
+ {
+ Type aType = cppu::UnoType<XPropertySet>::get();
+ return aType;
+ }
+
+
+ sal_Bool SAL_CALL UnoControlRoadmapModel::hasElements()
+ {
+ return !maRoadmapItems.empty();
+ }
+
+
+ void SAL_CALL UnoControlRoadmapModel::addContainerListener( const css::uno::Reference< css::container::XContainerListener >& xListener )
+ {
+ maContainerListeners.addInterface( xListener );
+ }
+
+ void SAL_CALL UnoControlRoadmapModel::removeContainerListener( const css::uno::Reference< css::container::XContainerListener >& xListener )
+ {
+ maContainerListeners.removeInterface( xListener );
+ }
+
+
+ // = UnoRoadmapControl
+
+
+ UnoRoadmapControl::UnoRoadmapControl()
+ :maItemListeners( *this )
+ {
+ }
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( UnoRoadmapControl, UnoControlRoadmap_Base, UnoControlRoadmap_IBase )
+IMPLEMENT_FORWARD_XINTERFACE2( UnoRoadmapControl, UnoControlRoadmap_Base, UnoControlRoadmap_IBase )
+
+
+sal_Bool SAL_CALL UnoRoadmapControl::setModel(const Reference< XControlModel >& _rModel)
+ {
+ Reference< XContainer > xC( getModel(), UNO_QUERY );
+ if ( xC.is() )
+ xC->removeContainerListener( this );
+
+ bool bReturn = UnoControlBase::setModel( _rModel );
+
+ xC.set(getModel(), css::uno::UNO_QUERY);
+ if ( xC.is() )
+ xC->addContainerListener( this );
+
+ return bReturn;
+ }
+
+
+ OUString UnoRoadmapControl::GetComponentServiceName() const
+ {
+ return "Roadmap";
+ }
+
+
+ void UnoRoadmapControl::dispose()
+ {
+ EventObject aEvt;
+ aEvt.Source = static_cast<cppu::OWeakObject*>(this);
+ maItemListeners.disposeAndClear( aEvt );
+ UnoControl::dispose();
+ }
+
+
+void UnoRoadmapControl::elementInserted( const ContainerEvent& rEvent )
+{
+ Reference< XInterface > xRoadmapItem;
+ rEvent.Element >>= xRoadmapItem;
+ Reference< XPropertySet > xRoadmapPropertySet( xRoadmapItem, UNO_QUERY );
+ if ( xRoadmapPropertySet.is() )
+ xRoadmapPropertySet->addPropertyChangeListener( OUString(), this );
+
+ Reference< XContainerListener > xPeer(getPeer(), UNO_QUERY);
+ if ( xPeer.is() )
+ {
+ xPeer->elementInserted( rEvent );
+ Reference < XPropertySet > xPropertySet( xPeer, UNO_QUERY );
+ if ( xPropertySet.is() )
+ xPropertySet->addPropertyChangeListener( OUString(), this );
+ }
+}
+
+
+void UnoRoadmapControl::elementRemoved( const ContainerEvent& rEvent )
+{
+ Reference< XContainerListener > xPeer(getPeer(), UNO_QUERY);
+ if ( xPeer.is() )
+ xPeer->elementRemoved( rEvent );
+ Reference< XInterface > xRoadmapItem;
+ rEvent.Element >>= xRoadmapItem;
+ Reference< XPropertySet > xPropertySet( xRoadmapItem, UNO_QUERY );
+ if ( xPropertySet.is() )
+ xPropertySet->removePropertyChangeListener( OUString(), this );
+}
+
+
+void UnoRoadmapControl::elementReplaced( const ContainerEvent& rEvent )
+{
+ Reference< XContainerListener > xPeer(getPeer(), UNO_QUERY);
+ if ( xPeer.is() )
+ xPeer->elementReplaced( rEvent );
+}
+
+
+void SAL_CALL UnoRoadmapControl::itemStateChanged( const ItemEvent& rEvent )
+{
+ sal_Int16 CurItemIndex = sal::static_int_cast< sal_Int16 >(rEvent.ItemId);
+ Reference< XControlModel > xModel = getModel( );
+ Reference< XPropertySet > xPropertySet( xModel, UNO_QUERY );
+ xPropertySet->setPropertyValue( GetPropertyName( BASEPROPERTY_CURRENTITEMID ), Any(CurItemIndex) );
+ if ( maItemListeners.getLength() )
+ maItemListeners.itemStateChanged( rEvent );
+}
+
+
+void SAL_CALL UnoRoadmapControl::addItemListener( const Reference< XItemListener >& l )
+{
+ maItemListeners.addInterface( l );
+ if( getPeer().is() && maItemListeners.getLength() == 1 )
+ {
+ Reference < XItemEventBroadcaster > xRoadmap( getPeer(), UNO_QUERY );
+ xRoadmap->addItemListener( this );
+ }
+}
+
+
+void SAL_CALL UnoRoadmapControl::removeItemListener( const Reference< XItemListener >& l )
+{
+ if( getPeer().is() && maItemListeners.getLength() == 1 )
+ {
+ Reference < XItemEventBroadcaster > xRoadmap( getPeer(), UNO_QUERY );
+ xRoadmap->removeItemListener( this );
+ }
+
+ maItemListeners.removeInterface( l );
+}
+
+
+void SAL_CALL UnoRoadmapControl::propertyChange( const PropertyChangeEvent& evt )
+{
+ Reference< XPropertyChangeListener > xPeer(getPeer(), UNO_QUERY);
+ if ( xPeer.is() )
+ xPeer->propertyChange( evt );
+}
+
+OUString UnoRoadmapControl::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoRoadmapControl";
+}
+
+css::uno::Sequence<OUString> UnoRoadmapControl::getSupportedServiceNames()
+{
+ auto s(UnoControlBase::getSupportedServiceNames());
+ s.realloc(s.getLength() + 2);
+ auto ps = s.getArray();
+ ps[s.getLength() - 2] = "com.sun.star.awt.UnoControlRoadmap";
+ ps[s.getLength() - 1] = "stardiv.vcl.control.Roadmap";
+ return s;
+}
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlRoadmapModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new toolkit::UnoControlRoadmapModel(context));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoRoadmapControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new toolkit::UnoRoadmapControl());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/roadmapentry.cxx b/toolkit/source/controls/roadmapentry.cxx
new file mode 100644
index 000000000..3de60f707
--- /dev/null
+++ b/toolkit/source/controls/roadmapentry.cxx
@@ -0,0 +1,105 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <controls/roadmapentry.hxx>
+#include <rtl/ustring.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <cppuhelper/supportsservice.hxx>
+
+
+ORoadmapEntry::ORoadmapEntry() : OPropertyContainer( GetBroadcastHelper() )
+{
+ // registerProperty or registerMayBeVoidProperty or registerPropertyNoMember
+
+ registerProperty( "Label", RM_PROPERTY_ID_LABEL,
+ css::beans::PropertyAttribute::BOUND |
+ css::beans::PropertyAttribute::CONSTRAINED,
+ & m_sLabel, cppu::UnoType<decltype(m_sLabel)>::get() );
+ m_nID = -1;
+ registerProperty( "ID", RM_PROPERTY_ID_ID,
+ css::beans::PropertyAttribute::BOUND |
+ css::beans::PropertyAttribute::CONSTRAINED,
+ & m_nID, cppu::UnoType<decltype(m_nID)>::get() );
+ m_bEnabled = true;
+ registerProperty( "Enabled", RM_PROPERTY_ID_ENABLED,
+ css::beans::PropertyAttribute::BOUND |
+ css::beans::PropertyAttribute::MAYBEDEFAULT,
+ & m_bEnabled, cppu::UnoType<decltype(m_bEnabled)>::get() );
+
+ registerProperty( "Interactive", RM_PROPERTY_ID_INTERACTIVE,
+ css::beans::PropertyAttribute::BOUND |
+ css::beans::PropertyAttribute::MAYBEDEFAULT,
+ & m_bInteractive, cppu::UnoType<decltype(m_bInteractive)>::get() );
+
+
+ // Note that the list of registered properties has to be fixed: Different
+ // instances of this class have to register the same set of properties with
+ // the same attributes.
+
+ // This is because all instances of the class share the same PropertySetInfo
+ // which has been built from the registered property of _one_ instance.
+}
+
+
+IMPLEMENT_FORWARD_XINTERFACE2( ORoadmapEntry, ORoadmapEntry_Base, ::comphelper::OPropertyContainer );
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( ORoadmapEntry, ORoadmapEntry_Base, ::comphelper::OPropertyContainer );
+ // order matters:
+ // the first is the class name
+ // the second is the class which implements the ref-counting
+ // the third up to n-th (when using IMPLEMENT_FORWARD_*3 and so on) are other base classes
+ // whose XInterface and XTypeProvider implementations should be merged
+
+
+css::uno::Reference< css:: beans::XPropertySetInfo > SAL_CALL
+ ORoadmapEntry::getPropertySetInfo()
+{
+ return createPropertySetInfo( getInfoHelper() );
+}
+
+OUString SAL_CALL ORoadmapEntry::getImplementationName( )
+{
+ return "com.sun.star.comp.toolkit.RoadmapItem";
+}
+
+sal_Bool SAL_CALL ORoadmapEntry::supportsService( const OUString& ServiceName )
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL ORoadmapEntry::getSupportedServiceNames( )
+{
+ return { "com.sun.star.awt.RoadmapItem" };
+}
+
+::cppu::IPropertyArrayHelper& ORoadmapEntry::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+
+::cppu::IPropertyArrayHelper* ORoadmapEntry::createArrayHelper() const
+{
+ css::uno::Sequence< css::beans::Property > aProps;
+ // describes all properties which have been registered in the ctor
+ describeProperties( aProps );
+
+ return new ::cppu::OPropertyArrayHelper( aProps );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/spinningprogress.cxx b/toolkit/source/controls/spinningprogress.cxx
new file mode 100644
index 000000000..ccd295d1a
--- /dev/null
+++ b/toolkit/source/controls/spinningprogress.cxx
@@ -0,0 +1,132 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <controls/animatedimages.hxx>
+#include <tools/diagnose_ex.h>
+#include <vcl/toolkit/throbber.hxx>
+
+using namespace css;
+using namespace css::uno;
+
+namespace {
+
+typedef toolkit::AnimatedImagesControlModel SpinningProgressControlModel_Base;
+class SpinningProgressControlModel : public SpinningProgressControlModel_Base
+{
+public:
+ explicit SpinningProgressControlModel( css::uno::Reference< css::uno::XComponentContext > const & i_factory );
+
+ SpinningProgressControlModel(SpinningProgressControlModel const &) = default;
+ SpinningProgressControlModel(SpinningProgressControlModel &&) = default;
+ SpinningProgressControlModel & operator =(SpinningProgressControlModel const &) = delete; // due to SpinningProgressControlModel_Base
+ SpinningProgressControlModel & operator =(SpinningProgressControlModel &&) = delete; // due to SpinningProgressControlModel_Base
+
+ virtual rtl::Reference<UnoControlModel> Clone() const override;
+
+ // XPropertySet
+ css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+
+ // XPersistObject
+ OUString SAL_CALL getServiceName() override;
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName( ) override;
+ css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+protected:
+ virtual ~SpinningProgressControlModel() override;
+};
+
+ SpinningProgressControlModel::SpinningProgressControlModel( Reference< XComponentContext > const & i_factory )
+ :SpinningProgressControlModel_Base( i_factory )
+ {
+ // default image sets
+ osl_atomic_increment( &m_refCount );
+ {
+ try
+ {
+ Throbber::ImageSet aImageSets[] =
+ {
+ Throbber::ImageSet::N16px, Throbber::ImageSet::N32px, Throbber::ImageSet::N64px
+ };
+ for ( size_t i=0; i < SAL_N_ELEMENTS(aImageSets); ++i )
+ {
+ const ::std::vector< OUString > aDefaultURLs( Throbber::getDefaultImageURLs( aImageSets[i] ) );
+ const Sequence< OUString > aImageURLs( aDefaultURLs.data(), aDefaultURLs.size() );
+ insertImageSet( i, aImageURLs );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+ }
+ osl_atomic_decrement( &m_refCount );
+ }
+
+
+ SpinningProgressControlModel::~SpinningProgressControlModel()
+ {
+ }
+
+
+ rtl::Reference<UnoControlModel> SpinningProgressControlModel::Clone() const
+ {
+ return new SpinningProgressControlModel( *this );
+ }
+
+
+ Reference< beans::XPropertySetInfo > SAL_CALL SpinningProgressControlModel::getPropertySetInfo( )
+ {
+ static Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+ }
+
+
+ OUString SAL_CALL SpinningProgressControlModel::getServiceName()
+ {
+ return "com.sun.star.awt.SpinningProgressControlModel";
+ }
+
+
+ OUString SAL_CALL SpinningProgressControlModel::getImplementationName( )
+ {
+ return "org.openoffice.comp.toolkit.SpinningProgressControlModel";
+ }
+
+
+ Sequence< OUString > SAL_CALL SpinningProgressControlModel::getSupportedServiceNames()
+ {
+ return { "com.sun.star.awt.SpinningProgressControlModel",
+ "com.sun.star.awt.AnimatedImagesControlModel",
+ "com.sun.star.awt.UnoControlModel" };
+ }
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+org_openoffice_comp_toolkit_SpinningProgressControlModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new SpinningProgressControlModel(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/stdtabcontroller.cxx b/toolkit/source/controls/stdtabcontroller.cxx
new file mode 100644
index 000000000..c900d6d15
--- /dev/null
+++ b/toolkit/source/controls/stdtabcontroller.cxx
@@ -0,0 +1,415 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/awt/XVclContainerPeer.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+
+#include <controls/stdtabcontroller.hxx>
+#include <toolkit/awt/vclxwindow.hxx>
+#include <toolkit/helper/macros.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/queryinterface.hxx>
+
+#include <sal/log.hxx>
+#include <tools/debug.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <comphelper/sequence.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+
+
+
+StdTabController::StdTabController()
+{
+}
+
+StdTabController::~StdTabController()
+{
+}
+
+bool StdTabController::ImplCreateComponentSequence(
+ Sequence< Reference< XControl > >& rControls,
+ const Sequence< Reference< XControlModel > >& rModels,
+ Sequence< Reference< XWindow > >& rComponents,
+ Sequence< Any>* pTabStops,
+ bool bPeerComponent )
+{
+ // Get only the requested controls
+ sal_Int32 nModels = rModels.getLength();
+ if (nModels != rControls.getLength())
+ {
+ Sequence< Reference< XControl > > aSeq( nModels );
+ auto aSeqRange = asNonConstRange(aSeq);
+ Reference< XControl > xCurrentControl;
+
+ sal_Int32 nRealControls = 0;
+ for (const Reference< XControlModel >& rModel : rModels)
+ {
+ xCurrentControl = FindControl(rControls, rModel);
+ if (xCurrentControl.is())
+ aSeqRange[nRealControls++] = xCurrentControl;
+ }
+ aSeq.realloc(nRealControls);
+ rControls = aSeq;
+ }
+
+ // there may be less controls than models, but never more controls than models
+ assert(rControls.getLength() <= rModels.getLength());
+
+ sal_Int32 nCtrls = rControls.getLength();
+ rComponents.realloc( nCtrls );
+ Reference< XWindow > * pComps = rComponents.getArray();
+ Any* pTabs = nullptr;
+
+
+ if ( pTabStops )
+ {
+ *pTabStops = Sequence< Any>( nCtrls );
+ pTabs = pTabStops->getArray();
+ }
+
+ bool bOK = true;
+ for ( const Reference< XControl >& xCtrl : std::as_const(rControls) )
+ {
+ // Get the matching control for this model
+ if ( !xCtrl.is() )
+ {
+ SAL_WARN("toolkit", "Control not found" );
+ bOK = false;
+ break;
+ }
+
+ if (bPeerComponent)
+ pComps->set(xCtrl->getPeer(), UNO_QUERY);
+ else
+ pComps->set(xCtrl, UNO_QUERY);
+
+ // TabStop-Property
+ if ( pTabs )
+ {
+ // opt: Constant String for TabStop name
+ static constexpr OUStringLiteral aTabStopName = u"Tabstop";
+
+ Reference< XPropertySet > xPSet( xCtrl->getModel(), UNO_QUERY );
+ Reference< XPropertySetInfo > xInfo = xPSet->getPropertySetInfo();
+ if( xInfo->hasPropertyByName( aTabStopName ) )
+ *pTabs++ = xPSet->getPropertyValue( aTabStopName );
+ else
+ ++pTabs;
+ }
+
+ ++pComps;
+ }
+ return bOK;
+}
+
+void StdTabController::ImplActivateControl( bool bFirst ) const
+{
+ // HACK due to bug #53688#, map controls onto an interface if remote controls may occur
+ Sequence< Reference< XControl > > aCtrls = const_cast<StdTabController*>(this)->getControls();
+ const Reference< XControl > * pControls = aCtrls.getConstArray();
+ sal_uInt32 nCount = aCtrls.getLength();
+
+ for ( sal_uInt32 n = bFirst ? 0 : nCount; bFirst ? n < nCount : n != 0; )
+ {
+ sal_uInt32 nCtrl = bFirst ? n++ : --n;
+ DBG_ASSERT( pControls[nCtrl].is(), "Control not in Container!" );
+ if ( pControls[nCtrl].is() )
+ {
+ Reference< XWindowPeer > xCP = pControls[nCtrl]->getPeer();
+ if ( xCP.is() )
+ {
+ VCLXWindow* pC = comphelper::getFromUnoTunnel<VCLXWindow>( xCP );
+ if ( pC && pC->GetWindow() && ( pC->GetWindow()->GetStyle() & WB_TABSTOP ) )
+ {
+ pC->GetWindow()->GrabFocus();
+ break;
+ }
+ }
+ }
+ }
+}
+
+// XInterface
+Any StdTabController::queryAggregation( const Type & rType )
+{
+ Any aRet = ::cppu::queryInterface( rType,
+ static_cast< XTabController* >(this),
+ static_cast< XServiceInfo* >(this),
+ static_cast< XTypeProvider* >(this) );
+ return (aRet.hasValue() ? aRet : OWeakAggObject::queryAggregation( rType ));
+}
+
+IMPL_IMPLEMENTATION_ID( StdTabController )
+
+// XTypeProvider
+css::uno::Sequence< css::uno::Type > StdTabController::getTypes()
+{
+ static const css::uno::Sequence< css::uno::Type > aTypeList {
+ cppu::UnoType<css::lang::XTypeProvider>::get(),
+ cppu::UnoType<XTabController>::get(),
+ cppu::UnoType<XServiceInfo>::get()
+ };
+ return aTypeList;
+}
+
+void StdTabController::setModel( const Reference< XTabControllerModel >& Model )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ mxModel = Model;
+}
+
+Reference< XTabControllerModel > StdTabController::getModel( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ return mxModel;
+}
+
+void StdTabController::setContainer( const Reference< XControlContainer >& Container )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ mxControlContainer = Container;
+}
+
+Reference< XControlContainer > StdTabController::getContainer( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ return mxControlContainer;
+}
+
+Sequence< Reference< XControl > > StdTabController::getControls( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ Sequence< Reference< XControl > > aSeq;
+
+ if ( mxControlContainer.is() )
+ {
+ const Sequence< Reference< XControlModel > > aModels = mxModel->getControlModels();
+
+ Sequence< Reference< XControl > > xCtrls = mxControlContainer->getControls();
+
+ sal_Int32 nCtrls = aModels.getLength();
+ aSeq = Sequence< Reference< XControl > >( nCtrls );
+ std::transform(aModels.begin(), aModels.end(), aSeq.getArray(),
+ [&xCtrls](const Reference< XControlModel >& xCtrlModel) -> Reference< XControl > {
+ return FindControl( xCtrls, xCtrlModel ); });
+ }
+ return aSeq;
+}
+
+namespace {
+
+struct ComponentEntry
+{
+ css::awt::XWindow* pComponent;
+ ::Point aPos;
+};
+
+}
+
+void StdTabController::autoTabOrder( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ DBG_ASSERT( mxControlContainer.is(), "autoTabOrder: No ControlContainer!" );
+ if ( !mxControlContainer.is() )
+ return;
+
+ Sequence< Reference< XControlModel > > aSeq = mxModel->getControlModels();
+ Sequence< Reference< XWindow > > aCompSeq;
+
+ // This may return a TabController, which returns desired list of controls faster
+ Sequence< Reference< XControl > > aControls = getControls();
+
+ // #58317# Some Models may be missing from the Container. Plus there is a
+ // autoTabOrder call later on.
+ if( !ImplCreateComponentSequence( aControls, aSeq, aCompSeq, nullptr, false ) )
+ return;
+
+ sal_uInt32 nCtrls = aCompSeq.getLength();
+
+ // insert sort algorithm
+ std::vector< ComponentEntry > aCtrls;
+ aCtrls.reserve(nCtrls);
+ for ( const Reference< XWindow >& rComponent : std::as_const(aCompSeq) )
+ {
+ XWindow* pC = rComponent.get();
+ ComponentEntry newEntry;
+ newEntry.pComponent = pC;
+ awt::Rectangle aPosSize = pC->getPosSize();
+ newEntry.aPos.setX( aPosSize.X );
+ newEntry.aPos.setY( aPosSize.Y );
+
+ decltype(aCtrls)::size_type nPos;
+ for ( nPos = 0; nPos < aCtrls.size(); nPos++ )
+ {
+ ComponentEntry& rEntry = aCtrls[ nPos ];
+ if ( ( rEntry.aPos.Y() > newEntry.aPos.Y() ) ||
+ ( ( rEntry.aPos.Y() == newEntry.aPos.Y() ) && ( rEntry.aPos.X() > newEntry.aPos.X() ) ) )
+ break;
+ }
+ if ( nPos < aCtrls.size() ) {
+ aCtrls.insert( aCtrls.begin() + nPos, newEntry );
+ } else {
+ aCtrls.push_back( newEntry );
+ }
+ }
+
+ Sequence< Reference< XControlModel > > aNewSeq( nCtrls );
+ std::transform(aCtrls.begin(), aCtrls.end(), aNewSeq.getArray(),
+ [](const ComponentEntry& rEntry) -> Reference< XControlModel > {
+ Reference< XControl > xUC( rEntry.pComponent, UNO_QUERY );
+ return xUC->getModel();
+ });
+
+ mxModel->setControlModels( aNewSeq );
+}
+
+void StdTabController::activateTabOrder( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ // Activate tab order for the control container
+
+ Reference< XControl > xC( mxControlContainer, UNO_QUERY );
+ Reference< XVclContainerPeer > xVclContainerPeer;
+ if ( xC.is() )
+ xVclContainerPeer.set(xC->getPeer(), css::uno::UNO_QUERY);
+ if ( !xC.is() || !xVclContainerPeer.is() )
+ return;
+
+ // This may return a TabController, which returns desired list of controls faster
+ // (the dreaded UNO aggregation, retrieve the thing that we are part of)
+ Reference<XTabController> xTabController( static_cast<XTabController*>(this), UNO_QUERY );
+
+ // Get a flattened list of controls sequences
+ Sequence< Reference< XControlModel > > aModels = mxModel->getControlModels();
+ Sequence< Reference< XWindow > > aCompSeq;
+ Sequence< Any> aTabSeq;
+
+ // DG: For the sake of optimization, retrieve Controls from getControls(),
+ // this may sound counterproductive, but leads to performance improvements
+ // in practical scenarios (Forms)
+ Sequence< Reference< XControl > > aControls = xTabController->getControls();
+
+ // #58317# Some Models may be missing from the Container. Plus there is a
+ // autoTabOrder call later on.
+ if( !ImplCreateComponentSequence( aControls, aModels, aCompSeq, &aTabSeq, true ) )
+ return;
+
+ xVclContainerPeer->setTabOrder( aCompSeq, aTabSeq, mxModel->getGroupControl() );
+
+ OUString aName;
+ Sequence< Reference< XControlModel > > aThisGroupModels;
+ Sequence< Reference< XWindow > > aControlComponents;
+
+ sal_uInt32 nGroups = mxModel->getGroupCount();
+ for ( sal_uInt32 nG = 0; nG < nGroups; nG++ )
+ {
+ mxModel->getGroup( nG, aThisGroupModels, aName );
+
+ aControls = xTabController->getControls();
+ // ImplCreateComponentSequence has a really strange semantics regarding it's first parameter:
+ // upon method entry, it expects a super set of the controls which it returns
+ // this means we need to completely fill this sequence with all available controls before
+ // calling into ImplCreateComponentSequence
+
+ aControlComponents.realloc( 0 );
+
+ ImplCreateComponentSequence( aControls, aThisGroupModels, aControlComponents, nullptr, true );
+ xVclContainerPeer->setGroup( aControlComponents );
+ }
+}
+
+void StdTabController::activateFirst( )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() ); //TODO: necessary?
+
+ ImplActivateControl( true );
+}
+
+void StdTabController::activateLast( )
+{
+ SolarMutexGuard aSolarGuard;
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() ); //TODO: necessary?
+
+ ImplActivateControl( false );
+}
+
+OUString StdTabController::getImplementationName()
+{
+ return "stardiv.Toolkit.StdTabController";
+}
+
+sal_Bool StdTabController::supportsService(OUString const & ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+css::uno::Sequence<OUString> StdTabController::getSupportedServiceNames()
+{
+ return css::uno::Sequence<OUString>{
+ "com.sun.star.awt.TabController",
+ "stardiv.vcl.control.TabController"};
+}
+
+Reference< XControl > StdTabController::FindControl( Sequence< Reference< XControl > >& rCtrls,
+ const Reference< XControlModel > & rxCtrlModel )
+{
+ if (!rxCtrlModel.is())
+ throw lang::IllegalArgumentException("No valid XControlModel",
+ uno::Reference<uno::XInterface>(), 0);
+
+ auto pCtrl = std::find_if(std::cbegin(rCtrls), std::cend(rCtrls),
+ [&rxCtrlModel](const Reference< XControl >& rCtrl) {
+ Reference< XControlModel > xModel(rCtrl.is() ? rCtrl->getModel() : Reference< XControlModel > ());
+ return xModel.get() == rxCtrlModel.get();
+ });
+ if (pCtrl != std::cend(rCtrls))
+ {
+ auto n = static_cast<sal_Int32>(std::distance(std::cbegin(rCtrls), pCtrl));
+ Reference< XControl > xCtrl( *pCtrl );
+ ::comphelper::removeElementAt( rCtrls, n );
+ return xCtrl;
+ }
+ return Reference< XControl > ();
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_StdTabController_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new StdTabController());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/stdtabcontrollermodel.cxx b/toolkit/source/controls/stdtabcontrollermodel.cxx
new file mode 100644
index 000000000..43fd80f17
--- /dev/null
+++ b/toolkit/source/controls/stdtabcontrollermodel.cxx
@@ -0,0 +1,439 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/io/XMarkableStream.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <controls/stdtabcontrollermodel.hxx>
+#include <toolkit/helper/macros.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/queryinterface.hxx>
+
+#include <tools/debug.hxx>
+
+#define UNOCONTROL_STREAMVERSION short(2)
+
+
+
+UnoControlModelEntryList::UnoControlModelEntryList()
+{
+}
+
+UnoControlModelEntryList::~UnoControlModelEntryList()
+{
+ Reset();
+}
+
+void UnoControlModelEntryList::Reset()
+{
+ for ( size_t n = maList.size(); n; )
+ DestroyEntry( --n );
+}
+
+void UnoControlModelEntryList::DestroyEntry( size_t nEntry )
+{
+ UnoControlModelEntryListBase::iterator it = maList.begin();
+ ::std::advance( it, nEntry );
+
+ if ( (*it)->bGroup )
+ delete (*it)->pGroup;
+ else
+ delete (*it)->pxControl;
+
+ delete *it;
+ maList.erase( it );
+}
+
+size_t UnoControlModelEntryList::size() const {
+ return maList.size();
+}
+
+UnoControlModelEntry* UnoControlModelEntryList::operator[]( size_t i ) const {
+ return ( i < maList.size() ) ? maList[ i ] : nullptr;
+}
+
+void UnoControlModelEntryList::push_back( UnoControlModelEntry* item ) {
+ maList.push_back( item );
+}
+
+void UnoControlModelEntryList::insert( size_t i, UnoControlModelEntry* item ) {
+ if ( i < maList.size() ) {
+ UnoControlModelEntryListBase::iterator it = maList.begin();
+ ::std::advance( it, i );
+ maList.insert( it, item );
+ } else {
+ maList.push_back( item );
+ }
+}
+
+
+
+StdTabControllerModel::StdTabControllerModel()
+{
+ mbGroupControl = true;
+}
+
+StdTabControllerModel::~StdTabControllerModel()
+{
+}
+
+sal_uInt32 StdTabControllerModel::ImplGetControlCount( const UnoControlModelEntryList& rList ) const
+{
+ sal_uInt32 nCount = 0;
+ size_t nEntries = rList.size();
+ for ( size_t n = 0; n < nEntries; n++ )
+ {
+ UnoControlModelEntry* pEntry = rList[ n ];
+ if ( pEntry->bGroup )
+ nCount += ImplGetControlCount( *pEntry->pGroup );
+ else
+ nCount++;
+ }
+ return nCount;
+}
+
+void StdTabControllerModel::ImplGetControlModels( css::uno::Reference< css::awt::XControlModel > ** ppRefs, const UnoControlModelEntryList& rList ) const
+{
+ size_t nEntries = rList.size();
+ for ( size_t n = 0; n < nEntries; n++ )
+ {
+ UnoControlModelEntry* pEntry = rList[ n ];
+ if ( pEntry->bGroup )
+ ImplGetControlModels( ppRefs, *pEntry->pGroup );
+ else
+ {
+ **ppRefs = *pEntry->pxControl;
+ (*ppRefs)++;
+ }
+ }
+}
+
+void StdTabControllerModel::ImplSetControlModels( UnoControlModelEntryList& rList, const css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > >& Controls )
+{
+ for ( const css::uno::Reference< css::awt::XControlModel >& rRef : Controls )
+ {
+ UnoControlModelEntry* pNewEntry = new UnoControlModelEntry;
+ pNewEntry->bGroup = false;
+ pNewEntry->pxControl = new css::uno::Reference< css::awt::XControlModel > ;
+ *pNewEntry->pxControl = rRef;
+ rList.push_back( pNewEntry );
+ }
+}
+
+sal_uInt32 StdTabControllerModel::ImplGetControlPos( const css::uno::Reference< css::awt::XControlModel >& rCtrl, const UnoControlModelEntryList& rList )
+{
+ for ( size_t n = rList.size(); n; )
+ {
+ UnoControlModelEntry* pEntry = rList[ --n ];
+ if ( !pEntry->bGroup && ( *pEntry->pxControl == rCtrl ) )
+ return n;
+ }
+ return CONTROLPOS_NOTFOUND;
+}
+
+static void ImplWriteControls( const css::uno::Reference< css::io::XObjectOutputStream > & OutStream, const css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > >& rCtrls )
+{
+ css::uno::Reference< css::io::XMarkableStream > xMark( OutStream, css::uno::UNO_QUERY );
+ DBG_ASSERT( xMark.is(), "write: no XMarkableStream!" );
+
+ sal_uInt32 nStoredControls = 0;
+ sal_Int32 nDataBeginMark = xMark->createMark();
+
+ OutStream->writeLong( 0 ); // DataLen
+ OutStream->writeLong( 0 ); // nStoredControls
+
+ for ( const css::uno::Reference< css::awt::XControlModel >& xI : rCtrls )
+ {
+ css::uno::Reference< css::io::XPersistObject > xPO( xI, css::uno::UNO_QUERY );
+ DBG_ASSERT( xPO.is(), "write: Control doesn't support XPersistObject" );
+ if ( xPO.is() )
+ {
+ OutStream->writeObject( xPO );
+ nStoredControls++;
+ }
+ }
+ sal_Int32 nDataLen = xMark->offsetToMark( nDataBeginMark );
+ xMark->jumpToMark( nDataBeginMark );
+ OutStream->writeLong( nDataLen );
+ OutStream->writeLong( nStoredControls );
+ xMark->jumpToFurthest();
+ xMark->deleteMark(nDataBeginMark);
+}
+
+static css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > > ImplReadControls( const css::uno::Reference< css::io::XObjectInputStream > & InStream )
+{
+ css::uno::Reference< css::io::XMarkableStream > xMark( InStream, css::uno::UNO_QUERY );
+ DBG_ASSERT( xMark.is(), "write: no XMarkableStream!" );
+
+ sal_Int32 nDataBeginMark = xMark->createMark();
+
+ sal_Int32 nDataLen = InStream->readLong();
+ sal_uInt32 nCtrls = InStream->readLong();
+
+ css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > > aSeq( nCtrls );
+ for ( sal_uInt32 n = 0; n < nCtrls; n++ )
+ {
+ css::uno::Reference< css::io::XPersistObject > xObj = InStream->readObject();
+ css::uno::Reference< css::awt::XControlModel > xI( xObj, css::uno::UNO_QUERY );
+ aSeq.getArray()[n] = xI;
+ }
+
+ // Skip remainder if more data exists than this version recognizes
+ xMark->jumpToMark( nDataBeginMark );
+ InStream->skipBytes( nDataLen );
+ xMark->deleteMark(nDataBeginMark);
+ return aSeq;
+}
+
+
+// css::uno::XInterface
+css::uno::Any StdTabControllerModel::queryAggregation( const css::uno::Type & rType )
+{
+ css::uno::Any aRet = ::cppu::queryInterface( rType,
+ static_cast< css::awt::XTabControllerModel* >(this),
+ static_cast< css::lang::XServiceInfo* >(this),
+ static_cast< css::io::XPersistObject* >(this),
+ static_cast< css::lang::XTypeProvider* >(this) );
+ return (aRet.hasValue() ? aRet : OWeakAggObject::queryAggregation( rType ));
+}
+
+IMPL_IMPLEMENTATION_ID( StdTabControllerModel )
+
+// css::lang::XTypeProvider
+css::uno::Sequence< css::uno::Type > StdTabControllerModel::getTypes()
+{
+ static const css::uno::Sequence< css::uno::Type > aTypeList {
+ cppu::UnoType<css::lang::XTypeProvider>::get(),
+ cppu::UnoType<css::awt::XTabControllerModel>::get(),
+ cppu::UnoType<css::lang::XServiceInfo>::get(),
+ cppu::UnoType<css::io::XPersistObject>::get()
+ };
+ return aTypeList;
+}
+
+sal_Bool StdTabControllerModel::getGroupControl( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ return mbGroupControl;
+}
+
+void StdTabControllerModel::setGroupControl( sal_Bool GroupControl )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ mbGroupControl = GroupControl;
+}
+
+void StdTabControllerModel::setControlModels( const css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > >& Controls )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ maControls.Reset();
+ ImplSetControlModels( maControls, Controls );
+}
+
+css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > > StdTabControllerModel::getControlModels( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > > aSeq( ImplGetControlCount( maControls ) );
+ css::uno::Reference< css::awt::XControlModel > * pRefs = aSeq.getArray();
+ ImplGetControlModels( &pRefs, maControls );
+ return aSeq;
+}
+
+void StdTabControllerModel::setGroup( const css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > >& Group, const OUString& GroupName )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ // The controls might occur as a flat list and will be grouped.
+ // Nested groups are not possible.
+ // The first element of a group determines its position.
+ UnoControlModelEntry* pNewEntry = new UnoControlModelEntry;
+ pNewEntry->bGroup = true;
+ pNewEntry->pGroup = new UnoControlModelEntryList;
+ pNewEntry->pGroup->SetName( GroupName );
+ ImplSetControlModels( *pNewEntry->pGroup, Group );
+
+ bool bInserted = false;
+ size_t nElements = pNewEntry->pGroup->size();
+ for ( size_t n = 0; n < nElements; n++ )
+ {
+ UnoControlModelEntry* pEntry = (*pNewEntry->pGroup)[ n ];
+ if ( !pEntry->bGroup )
+ {
+ sal_uInt32 nPos = ImplGetControlPos( *pEntry->pxControl, maControls );
+ // At the beginning, all Controls should be in a flattened list
+ DBG_ASSERT( nPos != CONTROLPOS_NOTFOUND, "setGroup - Element not found" );
+ if ( nPos != CONTROLPOS_NOTFOUND )
+ {
+ maControls.DestroyEntry( nPos );
+ if ( !bInserted )
+ {
+ maControls.insert( nPos, pNewEntry );
+ bInserted = true;
+ }
+ }
+ }
+ }
+ if ( !bInserted )
+ maControls.push_back( pNewEntry );
+}
+
+sal_Int32 StdTabControllerModel::getGroupCount( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ // Start with only one group layer, even though Model and Impl-methods
+ // work recursively, this is not presented to the outside.
+
+ sal_Int32 nGroups = 0;
+ size_t nEntries = maControls.size();
+ for ( size_t n = 0; n < nEntries; n++ )
+ {
+ UnoControlModelEntry* pEntry = maControls[ n ];
+ if ( pEntry->bGroup )
+ nGroups++;
+ }
+ return nGroups;
+}
+
+void StdTabControllerModel::getGroup( sal_Int32 nGroup, css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > >& rGroup, OUString& rName )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > > aSeq;
+ sal_uInt32 nG = 0;
+ size_t nEntries = maControls.size();
+ for ( size_t n = 0; n < nEntries; n++ )
+ {
+ UnoControlModelEntry* pEntry = maControls[ n ];
+ if ( pEntry->bGroup )
+ {
+ if ( nG == static_cast<sal_uInt32>(nGroup) )
+ {
+ sal_uInt32 nCount = ImplGetControlCount( *pEntry->pGroup );
+ aSeq = css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > >( nCount );
+ css::uno::Reference< css::awt::XControlModel > * pRefs = aSeq.getArray();
+ ImplGetControlModels( &pRefs, *pEntry->pGroup );
+ rName = pEntry->pGroup->GetName();
+ break;
+ }
+ nG++;
+ }
+ }
+ rGroup = aSeq;
+}
+
+void StdTabControllerModel::getGroupByName( const OUString& rName, css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > >& rGroup )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ sal_uInt32 nGroup = 0;
+ size_t nEntries = maControls.size();
+ for ( size_t n = 0; n < nEntries; n++ )
+ {
+ UnoControlModelEntry* pEntry = maControls[ n ];
+ if ( pEntry->bGroup )
+ {
+ if ( pEntry->pGroup->GetName() == rName )
+ {
+ OUString Dummy;
+ getGroup( nGroup, rGroup, Dummy );
+ break;
+ }
+ nGroup++;
+ }
+ }
+}
+
+
+// css::io::XPersistObject
+OUString StdTabControllerModel::getServiceName( )
+{
+ return "stardiv.vcl.controlmodel.TabController";
+}
+
+void StdTabControllerModel::write( const css::uno::Reference< css::io::XObjectOutputStream >& OutStream )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ css::uno::Reference< css::io::XMarkableStream > xMark( OutStream, css::uno::UNO_QUERY );
+ DBG_ASSERT( xMark.is(), "write: no XMarkableStream!" );
+
+ OutStream->writeShort( UNOCONTROL_STREAMVERSION );
+
+ css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > > aCtrls = getControlModels();
+ ImplWriteControls( OutStream, aCtrls );
+
+ sal_uInt32 nGroups = getGroupCount();
+ OutStream->writeLong( nGroups );
+ for ( sal_uInt32 n = 0; n < nGroups; n++ )
+ {
+ css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > > aGroupCtrls;
+ OUString aGroupName;
+ getGroup( n, aGroupCtrls, aGroupName );
+ OutStream->writeUTF( aGroupName );
+ ImplWriteControls( OutStream, aGroupCtrls );
+ }
+}
+
+void StdTabControllerModel::read( const css::uno::Reference< css::io::XObjectInputStream >& InStream )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > > aSeq = ImplReadControls( InStream );
+ setControlModels( aSeq );
+
+ sal_uInt32 nGroups = InStream->readLong();
+ for ( sal_uInt32 n = 0; n < nGroups; n++ )
+ {
+ OUString aGroupName = InStream->readUTF();
+ css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > > aCtrlSeq = ImplReadControls( InStream );
+ setGroup( aCtrlSeq, aGroupName );
+ }
+}
+
+OUString StdTabControllerModel::getImplementationName()
+{
+ return "stardiv.Toolkit.StdTabControllerModel";
+}
+
+sal_Bool StdTabControllerModel::supportsService(OUString const & ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+css::uno::Sequence<OUString> StdTabControllerModel::getSupportedServiceNames()
+{
+ return css::uno::Sequence<OUString>{
+ "com.sun.star.awt.TabControllerModel",
+ "stardiv.vcl.controlmodel.TabController"};
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_StdTabControllerModel_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new StdTabControllerModel());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/svmedit.cxx b/toolkit/source/controls/svmedit.cxx
new file mode 100644
index 000000000..383f22804
--- /dev/null
+++ b/toolkit/source/controls/svmedit.cxx
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <awt/vclxwindows.hxx>
+#include <controls/svmedit.hxx>
+
+MultiLineEdit::MultiLineEdit(vcl::Window* pParent, WinBits nWinStyle)
+ : VclMultiLineEdit(pParent, nWinStyle)
+{
+}
+
+// virtual
+css::uno::Reference<css::awt::XWindowPeer> MultiLineEdit::GetComponentInterface(bool bCreate)
+{
+ css::uno::Reference<css::awt::XWindowPeer> xPeer(
+ VclMultiLineEdit::GetComponentInterface(false));
+ if (!xPeer.is() && bCreate)
+ {
+ rtl::Reference<VCLXMultiLineEdit> xVCLMEdit(new VCLXMultiLineEdit);
+ xVCLMEdit->SetWindow(this);
+ xPeer = xVCLMEdit.get();
+ SetComponentInterface(xPeer);
+ }
+ return xPeer;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/tabpagecontainer.cxx b/toolkit/source/controls/tabpagecontainer.cxx
new file mode 100644
index 000000000..d4028b290
--- /dev/null
+++ b/toolkit/source/controls/tabpagecontainer.cxx
@@ -0,0 +1,351 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <controls/geometrycontrolmodel.hxx>
+#include <controls/tabpagecontainer.hxx>
+#include <controls/tabpagemodel.hxx>
+#include <toolkit/helper/property.hxx>
+
+#include <com/sun/star/awt/XControlModel.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <o3tl/safeint.hxx>
+#include <tools/diagnose_ex.h>
+#include <vcl/svapp.hxx>
+
+#include <helper/unopropertyarrayhelper.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::view;
+using ::com::sun::star::awt::tab::XTabPageModel;
+
+constexpr OUStringLiteral WRONG_TYPE_EXCEPTION = u"Type must be css::awt::tab::XTabPageModel!";
+
+
+UnoControlTabPageContainerModel::UnoControlTabPageContainerModel( const Reference< XComponentContext >& i_factory )
+ :UnoControlTabPageContainerModel_Base( i_factory )
+ ,maContainerListeners( *this )
+{
+ ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_BORDER );
+ ImplRegisterProperty( BASEPROPERTY_BORDERCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
+ ImplRegisterProperty( BASEPROPERTY_ENABLED );
+ ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
+ ImplRegisterProperty( BASEPROPERTY_HELPURL );
+ ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
+ ImplRegisterProperty( BASEPROPERTY_TEXT );
+}
+
+OUString UnoControlTabPageContainerModel::getServiceName()
+{
+ return "com.sun.star.awt.tab.UnoControlTabPageContainerModel";
+}
+
+uno::Any UnoControlTabPageContainerModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ switch(nPropId)
+ {
+ case BASEPROPERTY_DEFAULTCONTROL:
+ return uno::Any( OUString("com.sun.star.awt.tab.UnoControlTabPageContainer") );
+ case BASEPROPERTY_BORDER:
+ return uno::Any(sal_Int16(0)); // No Border
+ default:
+ return UnoControlModel::ImplGetDefaultValue( nPropId );
+ }
+}
+
+::cppu::IPropertyArrayHelper& UnoControlTabPageContainerModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+Reference< css::beans::XPropertySetInfo > UnoControlTabPageContainerModel::getPropertySetInfo( )
+{
+ static Reference< css::beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+namespace
+{
+ Reference< XTabPageModel > lcl_createTabPageModel( Reference<XComponentContext> const & i_context,
+ Sequence< Any > const & i_initArguments, Reference< XPropertySet > const & i_parentModel )
+ {
+ try
+ {
+ Reference< XPropertySetInfo > const xPSI( i_parentModel->getPropertySetInfo() );
+ bool const isGeometryControlModel = xPSI.is() && xPSI->hasPropertyByName("PositionX");
+
+ Reference< XInterface > xInstance;
+ if ( isGeometryControlModel )
+ xInstance = *( new OGeometryControlModel< UnoControlTabPageModel >( i_context ) );
+ else
+ xInstance = *( new UnoControlTabPageModel( i_context ) );
+
+ Reference< XTabPageModel > const xTabPageModel( xInstance, UNO_QUERY_THROW );
+ Reference< XInitialization > const xInit( xTabPageModel, UNO_QUERY_THROW );
+ xInit->initialize( i_initArguments );
+
+ return xTabPageModel;
+ }
+ catch( const RuntimeException& )
+ {
+ throw;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+ return nullptr;
+ }
+}
+
+Reference< XTabPageModel > SAL_CALL UnoControlTabPageContainerModel::createTabPage( ::sal_Int16 i_tabPageID )
+{
+ Sequence< Any > aInitArgs{ Any(i_tabPageID) };
+ return lcl_createTabPageModel( m_xContext, aInitArgs, this );
+}
+
+Reference< XTabPageModel > SAL_CALL UnoControlTabPageContainerModel::loadTabPage( ::sal_Int16 i_tabPageID, const OUString& i_resourceURL )
+{
+ Sequence< Any > aInitArgs{ Any(i_tabPageID), Any(i_resourceURL) };
+ return lcl_createTabPageModel( m_xContext, aInitArgs, this );
+}
+
+void SAL_CALL UnoControlTabPageContainerModel::insertByIndex( ::sal_Int32 nIndex, const css::uno::Any& aElement)
+{
+ SolarMutexGuard aSolarGuard;
+ uno::Reference < XTabPageModel > xTabPageModel;
+ if(!(aElement >>= xTabPageModel))
+ throw IllegalArgumentException( WRONG_TYPE_EXCEPTION, static_cast<OWeakObject *>(this), 2 );
+
+ if ( sal_Int32( m_aTabPageVector.size()) ==nIndex )
+ m_aTabPageVector.push_back( xTabPageModel );
+ else if ( sal_Int32( m_aTabPageVector.size()) > nIndex )
+ {
+ std::vector< uno::Reference< XTabPageModel > >::iterator aIter = m_aTabPageVector.begin();
+ aIter += nIndex;
+ m_aTabPageVector.insert( aIter, xTabPageModel );
+ }
+ else
+ throw IndexOutOfBoundsException( OUString(), static_cast<OWeakObject *>(this) );
+ ContainerEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.Element = aElement;
+ aEvent.Accessor <<= OUString::number(nIndex);
+ maContainerListeners.elementInserted( aEvent );
+
+}
+
+void SAL_CALL UnoControlTabPageContainerModel::removeByIndex( ::sal_Int32 /*Index*/ )
+{
+}
+// XIndexReplace
+void SAL_CALL UnoControlTabPageContainerModel::replaceByIndex( ::sal_Int32 /*Index*/, const uno::Any& /*Element*/ )
+{
+}
+
+// XIndexAccess
+::sal_Int32 SAL_CALL UnoControlTabPageContainerModel::getCount( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+ return sal_Int32( m_aTabPageVector.size());
+}
+
+uno::Any SAL_CALL UnoControlTabPageContainerModel::getByIndex( ::sal_Int32 nIndex )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+ if ( nIndex < 0 || o3tl::make_unsigned(nIndex) > m_aTabPageVector.size() )
+ throw lang::IndexOutOfBoundsException();
+ return uno::Any(m_aTabPageVector[nIndex]);
+}
+
+// XElementAccess
+uno::Type SAL_CALL UnoControlTabPageContainerModel::getElementType( )
+{
+ return cppu::UnoType<css::awt::XControlModel>::get();
+}
+
+sal_Bool SAL_CALL UnoControlTabPageContainerModel::hasElements( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+ return !m_aTabPageVector.empty();
+}
+// XContainer
+void UnoControlTabPageContainerModel::addContainerListener( const Reference< XContainerListener >& l )
+{
+ maContainerListeners.addInterface( l );
+}
+
+void UnoControlTabPageContainerModel::removeContainerListener( const Reference< XContainerListener >& l )
+{
+ maContainerListeners.removeInterface( l );
+}
+
+
+
+UnoControlTabPageContainer::UnoControlTabPageContainer( const uno::Reference< uno::XComponentContext >& rxContext )
+ :UnoControlTabPageContainer_Base(rxContext)
+ ,m_aTabPageListeners( *this )
+{
+}
+
+OUString UnoControlTabPageContainer::GetComponentServiceName() const
+{
+ return "TabPageContainer";
+}
+
+void SAL_CALL UnoControlTabPageContainer::dispose( )
+{
+ lang::EventObject aEvt;
+ aEvt.Source = static_cast<cppu::OWeakObject*>(this);
+ m_aTabPageListeners.disposeAndClear( aEvt );
+ UnoControl::dispose();
+}
+
+void UnoControlTabPageContainer::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer > & rParentPeer )
+{
+ UnoControlBase::createPeer( rxToolkit, rParentPeer );
+
+ Reference< XTabPageContainer > xTPContainer( getPeer(), UNO_QUERY_THROW );
+ if ( m_aTabPageListeners.getLength() )
+ xTPContainer->addTabPageContainerListener(&m_aTabPageListeners);
+}
+
+
+// XTabPageContainer
+
+::sal_Int16 SAL_CALL UnoControlTabPageContainer::getActiveTabPageID()
+{
+ SolarMutexGuard aSolarGuard;
+ Reference< XTabPageContainer > xTPContainer( getPeer(), UNO_QUERY_THROW );
+ return xTPContainer->getActiveTabPageID();
+}
+void SAL_CALL UnoControlTabPageContainer::setActiveTabPageID( ::sal_Int16 _activetabpageid )
+{
+ SolarMutexGuard aSolarGuard;
+ Reference< XTabPageContainer > xTPContainer( getPeer(), UNO_QUERY_THROW );
+ xTPContainer->setActiveTabPageID(_activetabpageid);
+}
+::sal_Int16 SAL_CALL UnoControlTabPageContainer::getTabPageCount( )
+{
+ SolarMutexGuard aSolarGuard;
+ Reference< XTabPageContainer > xTPContainer( getPeer(), UNO_QUERY_THROW );
+ return xTPContainer->getTabPageCount();
+}
+sal_Bool SAL_CALL UnoControlTabPageContainer::isTabPageActive( ::sal_Int16 tabPageIndex )
+{
+ SolarMutexGuard aSolarGuard;
+ Reference< XTabPageContainer > xTPContainer( getPeer(), UNO_QUERY_THROW );
+ return xTPContainer->isTabPageActive(tabPageIndex);
+}
+Reference< css::awt::tab::XTabPage > SAL_CALL UnoControlTabPageContainer::getTabPage( ::sal_Int16 tabPageIndex )
+{
+ SolarMutexGuard aSolarGuard;
+ Reference< XTabPageContainer > xTPContainer( getPeer(), UNO_QUERY_THROW );
+ return xTPContainer->getTabPage(tabPageIndex);
+}
+Reference< css::awt::tab::XTabPage > SAL_CALL UnoControlTabPageContainer::getTabPageByID( ::sal_Int16 tabPageID )
+{
+ SolarMutexGuard aSolarGuard;
+ Reference< XTabPageContainer > xTPContainer( getPeer(), UNO_QUERY_THROW );
+ return xTPContainer->getTabPageByID(tabPageID);
+}
+void SAL_CALL UnoControlTabPageContainer::addTabPageContainerListener( const Reference< css::awt::tab::XTabPageContainerListener >& listener )
+{
+ m_aTabPageListeners.addInterface( listener );
+ if( getPeer().is() && m_aTabPageListeners.getLength() == 1 )
+ {
+ uno::Reference < awt::tab::XTabPageContainer > xTabPageContainer( getPeer(), uno::UNO_QUERY );
+ xTabPageContainer->addTabPageContainerListener( &m_aTabPageListeners );
+ }
+}
+void SAL_CALL UnoControlTabPageContainer::removeTabPageContainerListener( const Reference< css::awt::tab::XTabPageContainerListener >& listener )
+{
+ if( getPeer().is() && m_aTabPageListeners.getLength() == 1 )
+ {
+ uno::Reference < awt::tab::XTabPageContainer > xTabPageContainer( getPeer(), uno::UNO_QUERY );
+ xTabPageContainer->removeTabPageContainerListener( &m_aTabPageListeners );
+ }
+ m_aTabPageListeners.removeInterface( listener );
+}
+
+void UnoControlTabPageContainer::propertiesChange(const::css::uno::Sequence<PropertyChangeEvent> &aEvent)
+{
+ UnoControlTabPageContainer_Base::propertiesChange(aEvent);
+
+ SolarMutexGuard aSolarGuard;
+ Reference< XPropertiesChangeListener > xPropertiesChangeListener( getPeer(), UNO_QUERY_THROW );
+ return xPropertiesChangeListener->propertiesChange(aEvent);
+}
+
+void UnoControlTabPageContainer::updateFromModel()
+{
+ UnoControlTabPageContainer_Base::updateFromModel();
+ if (!getPeer().is())
+ throw RuntimeException("No peer for tabpage container!");
+ Reference< XContainerListener > xContainerListener( getPeer(), UNO_QUERY );
+ ENSURE_OR_RETURN_VOID( xContainerListener.is(), "UnoListBoxControl::updateFromModel: a peer which is no ItemListListener?!" );
+
+ ContainerEvent aEvent;
+ aEvent.Source = getModel();
+ const Sequence< Reference< XControl > > aControls = getControls();
+
+ for ( const Reference< XControl >& rCtrl : aControls )
+ {
+ aEvent.Element <<= rCtrl;
+ xContainerListener->elementInserted( aEvent );
+ }
+}
+void SAL_CALL UnoControlTabPageContainer::addControl( const OUString& Name, const Reference< css::awt::XControl >& Control )
+{
+ SolarMutexGuard aSolarGuard;
+ ControlContainerBase::addControl(Name,Control);
+ if (!getPeer().is())
+ throw RuntimeException("No peer for tabpage container!");
+ Reference< XContainerListener > xContainerListener( getPeer(), UNO_QUERY );
+ ContainerEvent aEvent;
+ aEvent.Source = getModel();
+ aEvent.Element <<= Control;
+ xContainerListener->elementInserted( aEvent );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlTabPageContainerModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoControlTabPageContainerModel(context));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlTabPageContainer_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoControlTabPageContainer(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/tabpagemodel.cxx b/toolkit/source/controls/tabpagemodel.cxx
new file mode 100644
index 000000000..c82e54e41
--- /dev/null
+++ b/toolkit/source/controls/tabpagemodel.cxx
@@ -0,0 +1,304 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <controls/tabpagemodel.hxx>
+
+#include <vcl/svapp.hxx>
+#include <toolkit/helper/property.hxx>
+#include <com/sun/star/awt/UnoControlDialogModelProvider.hpp>
+#include <com/sun/star/awt/tab/XTabPage.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <tools/debug.hxx>
+#include <vcl/outdev.hxx>
+
+#include <controls/controlmodelcontainerbase.hxx>
+#include <controls/unocontrolcontainer.hxx>
+
+#include <helper/unopropertyarrayhelper.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+
+UnoControlTabPageModel::UnoControlTabPageModel( Reference< XComponentContext > const & i_factory )
+ :ControlModelContainerBase( i_factory )
+{
+ ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
+ ImplRegisterProperty( BASEPROPERTY_TITLE );
+ ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
+ ImplRegisterProperty( BASEPROPERTY_HELPURL );
+ ImplRegisterProperty( BASEPROPERTY_USERFORMCONTAINEES );
+ ImplRegisterProperty( BASEPROPERTY_HSCROLL );
+ ImplRegisterProperty( BASEPROPERTY_VSCROLL );
+ ImplRegisterProperty( BASEPROPERTY_SCROLLWIDTH );
+ ImplRegisterProperty( BASEPROPERTY_SCROLLHEIGHT );
+ ImplRegisterProperty( BASEPROPERTY_SCROLLTOP );
+ ImplRegisterProperty( BASEPROPERTY_SCROLLLEFT );
+}
+
+OUString SAL_CALL UnoControlTabPageModel::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoControlTabPageModel";
+}
+
+css::uno::Sequence< OUString > SAL_CALL UnoControlTabPageModel::getSupportedServiceNames()
+{
+ css::uno::Sequence< OUString > aNames = ControlModelContainerBase::getSupportedServiceNames( );
+ aNames.realloc( aNames.getLength() + 1 );
+ aNames.getArray()[ aNames.getLength() - 1 ] = "com.sun.star.awt.tab.UnoControlTabPageModel";
+ return aNames;
+}
+
+OUString UnoControlTabPageModel::getServiceName( )
+{
+ return "com.sun.star.awt.tab.UnoControlTabPageModel";
+}
+
+Any UnoControlTabPageModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ Any aAny;
+
+ switch ( nPropId )
+ {
+ case BASEPROPERTY_DEFAULTCONTROL:
+ aAny <<= OUString("com.sun.star.awt.tab.UnoControlTabPage");
+ break;
+ case BASEPROPERTY_USERFORMCONTAINEES:
+ {
+ // We do not have here any usercontainers (yet?), but let's return empty container back
+ // so normal properties could be set without triggering UnknownPropertyException
+ aAny <<= uno::Reference< XNameContainer >();
+ break;
+ }
+ default:
+ aAny = UnoControlModel::ImplGetDefaultValue( nPropId );
+ }
+
+ return aAny;
+}
+
+::cppu::IPropertyArrayHelper& UnoControlTabPageModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+// beans::XMultiPropertySet
+uno::Reference< beans::XPropertySetInfo > UnoControlTabPageModel::getPropertySetInfo( )
+{
+ static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+////----- XInitialization -------------------------------------------------------------------
+void SAL_CALL UnoControlTabPageModel::initialize (const Sequence<Any>& rArguments)
+{
+ sal_Int16 nPageId = -1;
+ if ( rArguments.getLength() == 1 )
+ {
+ if ( !( rArguments[ 0 ] >>= nPageId ))
+ throw lang::IllegalArgumentException();
+ m_nTabPageId = nPageId;
+ }
+ else if ( rArguments.getLength() == 2 )
+ {
+ if ( !( rArguments[ 0 ] >>= nPageId ))
+ throw lang::IllegalArgumentException();
+ m_nTabPageId = nPageId;
+ OUString sURL;
+ if ( !( rArguments[ 1 ] >>= sURL ))
+ throw lang::IllegalArgumentException();
+ Reference<container::XNameContainer > xDialogModel = awt::UnoControlDialogModelProvider::create( m_xContext, sURL );
+ if ( xDialogModel.is() )
+ {
+ const Sequence< OUString> aNames = xDialogModel->getElementNames();
+ for(const OUString& rName : aNames)
+ {
+ try
+ {
+ Any aElement(xDialogModel->getByName(rName));
+ xDialogModel->removeByName(rName);
+ insertByName(rName,aElement);
+ }
+ catch(const Exception&) {}
+ }
+ Reference<XPropertySet> xDialogProp(xDialogModel,UNO_QUERY);
+ if ( xDialogProp.is() )
+ {
+ static constexpr OUStringLiteral s_sResourceResolver = u"ResourceResolver";
+ Reference<XPropertySet> xThis(*this,UNO_QUERY);
+ xThis->setPropertyValue(s_sResourceResolver,xDialogProp->getPropertyValue(s_sResourceResolver));
+ xThis->setPropertyValue(GetPropertyName(BASEPROPERTY_TITLE),xDialogProp->getPropertyValue(GetPropertyName(BASEPROPERTY_TITLE)));
+ xThis->setPropertyValue(GetPropertyName(BASEPROPERTY_HELPTEXT),xDialogProp->getPropertyValue(GetPropertyName(BASEPROPERTY_HELPTEXT)));
+ xThis->setPropertyValue(GetPropertyName(BASEPROPERTY_HELPURL),xDialogProp->getPropertyValue(GetPropertyName(BASEPROPERTY_HELPURL)));
+ }
+ }
+ }
+ else
+ m_nTabPageId = -1;
+}
+
+
+UnoControlTabPage::UnoControlTabPage( const uno::Reference< uno::XComponentContext >& rxContext )
+ :UnoControlTabPage_Base(rxContext)
+ ,m_bWindowListener(false)
+{
+ maComponentInfos.nWidth = 280;
+ maComponentInfos.nHeight = 400;
+}
+UnoControlTabPage::~UnoControlTabPage()
+{
+}
+
+OUString UnoControlTabPage::GetComponentServiceName() const
+{
+ return "TabPageModel";
+}
+
+OUString SAL_CALL UnoControlTabPage::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoControlTabPage";
+}
+
+sal_Bool SAL_CALL UnoControlTabPage::supportsService(OUString const & ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+css::uno::Sequence<OUString> SAL_CALL UnoControlTabPage::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.tab.UnoControlTabPage" };
+}
+
+void UnoControlTabPage::dispose()
+{
+ SolarMutexGuard aSolarGuard;
+
+ lang::EventObject aEvt;
+ aEvt.Source = static_cast< ::cppu::OWeakObject* >( this );
+ ControlContainerBase::dispose();
+}
+
+void SAL_CALL UnoControlTabPage::disposing( const lang::EventObject& Source )
+{
+ ControlContainerBase::disposing( Source );
+}
+
+void UnoControlTabPage::createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer > & rParentPeer )
+{
+ SolarMutexGuard aSolarGuard;
+ ImplUpdateResourceResolver();
+
+ UnoControlContainer::createPeer( rxToolkit, rParentPeer );
+
+ Reference < tab::XTabPage > xTabPage( getPeer(), UNO_QUERY );
+ if ( xTabPage.is() )
+ {
+ if ( !m_bWindowListener )
+ {
+ Reference< XWindowListener > xWL(this);
+ addWindowListener( xWL );
+ m_bWindowListener = true;
+ }
+ }
+}
+
+static ::Size ImplMapPixelToAppFont( OutputDevice const * pOutDev, const ::Size& aSize )
+{
+ ::Size aTmp = pOutDev->PixelToLogic(aSize, MapMode(MapUnit::MapAppFont));
+ return aTmp;
+}
+// css::awt::XWindowListener
+void SAL_CALL UnoControlTabPage::windowResized( const css::awt::WindowEvent& e )
+{
+ OutputDevice*pOutDev = Application::GetDefaultDevice();
+ DBG_ASSERT( pOutDev, "Missing Default Device!" );
+ if ( !pOutDev || mbSizeModified )
+ return;
+
+ // Currently we are simply using MapUnit::MapAppFont
+ ::Size aAppFontSize( e.Width, e.Height );
+
+ Reference< XControl > xDialogControl( *this, UNO_QUERY_THROW );
+ Reference< XDevice > xDialogDevice( xDialogControl->getPeer(), UNO_QUERY );
+ OSL_ENSURE( xDialogDevice.is(), "UnoDialogControl::windowResized: no peer, but a windowResized event?" );
+ if ( xDialogDevice.is() )
+ {
+ DeviceInfo aDeviceInfo( xDialogDevice->getInfo() );
+ aAppFontSize.AdjustWidth( -(aDeviceInfo.LeftInset + aDeviceInfo.RightInset) );
+ aAppFontSize.AdjustHeight( -(aDeviceInfo.TopInset + aDeviceInfo.BottomInset) );
+ }
+
+ aAppFontSize = ImplMapPixelToAppFont( pOutDev, aAppFontSize );
+
+ // Remember that changes have been done by listener. No need to
+ // update the position because of property change event.
+ mbSizeModified = true;
+ // Properties in a sequence must be sorted!
+ Sequence< OUString > aProps{ "Height", "Width" };
+ Sequence< Any > aValues{ Any(aAppFontSize.Height()), Any(aAppFontSize.Width()) };
+
+ ImplSetPropertyValues( aProps, aValues, true );
+ mbSizeModified = false;
+
+}
+
+void SAL_CALL UnoControlTabPage::windowMoved( const css::awt::WindowEvent& e )
+{
+ OutputDevice*pOutDev = Application::GetDefaultDevice();
+ DBG_ASSERT( pOutDev, "Missing Default Device!" );
+ if ( !pOutDev || mbPosModified )
+ return;
+
+ // Currently we are simply using MapUnit::MapAppFont
+ ::Size aTmp( e.X, e.Y );
+ aTmp = ImplMapPixelToAppFont( pOutDev, aTmp );
+
+ // Remember that changes have been done by listener. No need to
+ // update the position because of property change event.
+ mbPosModified = true;
+ Sequence< OUString > aProps{ "PositionX", "PositionY" };
+ Sequence< Any > aValues{ Any(aTmp.Width()), Any(aTmp.Height()) };
+
+ ImplSetPropertyValues( aProps, aValues, true );
+ mbPosModified = false;
+
+}
+
+void SAL_CALL UnoControlTabPage::windowShown( const css::lang::EventObject& ) {}
+
+void SAL_CALL UnoControlTabPage::windowHidden( const css::lang::EventObject& ) {}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlTabPageModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoControlTabPageModel(context));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlTabPage_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoControlTabPage(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/tkscrollbar.cxx b/toolkit/source/controls/tkscrollbar.cxx
new file mode 100644
index 000000000..48a2a560b
--- /dev/null
+++ b/toolkit/source/controls/tkscrollbar.cxx
@@ -0,0 +1,324 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <controls/tkscrollbar.hxx>
+#include <toolkit/helper/property.hxx>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <cppuhelper/typeprovider.hxx>
+#include <cppuhelper/queryinterface.hxx>
+
+#include <toolkit/awt/vclxwindows.hxx>
+
+#include <helper/unopropertyarrayhelper.hxx>
+
+namespace toolkit
+{
+
+
+ using namespace ::com::sun::star;
+
+
+ //= UnoControlScrollBarModel
+
+
+ UnoControlScrollBarModel::UnoControlScrollBarModel( const uno::Reference< uno::XComponentContext >& i_factory )
+ :UnoControlModel( i_factory )
+ {
+ UNO_CONTROL_MODEL_REGISTER_PROPERTIES<VCLXScrollBar>();
+ }
+
+
+ OUString UnoControlScrollBarModel::getServiceName( )
+ {
+ return "stardiv.vcl.controlmodel.ScrollBar";
+ }
+
+ OUString UnoControlScrollBarModel::getImplementationName()
+ {
+ return "stardiv.Toolkit.UnoControlScrollBarModel";
+ }
+
+ css::uno::Sequence<OUString>
+ UnoControlScrollBarModel::getSupportedServiceNames()
+ {
+ auto s(UnoControlModel::getSupportedServiceNames());
+ s.realloc(s.getLength() + 2);
+ auto ps = s.getArray();
+ ps[s.getLength() - 2] = "com.sun.star.awt.UnoControlScrollBarModel";
+ ps[s.getLength() - 1] = "stardiv.vcl.controlmodel.ScrollBar";
+ return s;
+ }
+
+ uno::Any UnoControlScrollBarModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+ {
+ switch ( nPropId )
+ {
+ case BASEPROPERTY_LIVE_SCROLL:
+ return uno::Any( false );
+ case BASEPROPERTY_DEFAULTCONTROL:
+ return uno::Any( OUString( "stardiv.vcl.control.ScrollBar" ) );
+
+ default:
+ return UnoControlModel::ImplGetDefaultValue( nPropId );
+ }
+ }
+
+
+ ::cppu::IPropertyArrayHelper& UnoControlScrollBarModel::getInfoHelper()
+ {
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+ }
+
+
+ uno::Reference< beans::XPropertySetInfo > UnoControlScrollBarModel::getPropertySetInfo( )
+ {
+ static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+ }
+
+
+ //= UnoControlScrollBarModel
+
+ UnoScrollBarControl::UnoScrollBarControl()
+ :maAdjustmentListeners( *this )
+ {
+ }
+
+ OUString UnoScrollBarControl::GetComponentServiceName() const
+ {
+ return "ScrollBar";
+ }
+
+ // css::uno::XInterface
+ uno::Any UnoScrollBarControl::queryAggregation( const uno::Type & rType )
+ {
+ uno::Any aRet = ::cppu::queryInterface( rType,
+ static_cast< awt::XAdjustmentListener* >(this),
+ static_cast< awt::XScrollBar* >(this) );
+ return (aRet.hasValue() ? aRet : UnoControlBase::queryAggregation( rType ));
+ }
+
+ IMPL_IMPLEMENTATION_ID( UnoScrollBarControl )
+
+ // css::lang::XTypeProvider
+ css::uno::Sequence< css::uno::Type > UnoScrollBarControl::getTypes()
+ {
+ static const ::cppu::OTypeCollection aTypeList(
+ cppu::UnoType<css::lang::XTypeProvider>::get(),
+ cppu::UnoType<awt::XAdjustmentListener>::get(),
+ cppu::UnoType<awt::XScrollBar>::get(),
+ UnoControlBase::getTypes()
+ );
+ return aTypeList.getTypes();
+ }
+
+ void UnoScrollBarControl::dispose()
+ {
+ lang::EventObject aEvt;
+ aEvt.Source = static_cast<cppu::OWeakObject*>(this);
+ maAdjustmentListeners.disposeAndClear( aEvt );
+ UnoControl::dispose();
+ }
+
+ void UnoScrollBarControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer > & rParentPeer )
+ {
+ UnoControl::createPeer( rxToolkit, rParentPeer );
+
+ uno::Reference < awt::XScrollBar > xScrollBar( getPeer(), uno::UNO_QUERY );
+ xScrollBar->addAdjustmentListener( this );
+ }
+
+ // css::awt::XAdjustmentListener
+ void UnoScrollBarControl::adjustmentValueChanged( const css::awt::AdjustmentEvent& rEvent )
+ {
+ switch ( rEvent.Type )
+ {
+ case css::awt::AdjustmentType_ADJUST_LINE:
+ case css::awt::AdjustmentType_ADJUST_PAGE:
+ case css::awt::AdjustmentType_ADJUST_ABS:
+ {
+ uno::Reference< awt::XScrollBar > xScrollBar( getPeer(), uno::UNO_QUERY );
+
+ if ( xScrollBar.is() )
+ {
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SCROLLVALUE ), uno::Any(xScrollBar->getValue()), false );
+ }
+ }
+ break;
+ default:
+ {
+ OSL_FAIL( "UnoScrollBarControl::adjustmentValueChanged - unknown Type" );
+
+ }
+ }
+
+ if ( maAdjustmentListeners.getLength() )
+ maAdjustmentListeners.adjustmentValueChanged( rEvent );
+ }
+
+ // css::awt::XScrollBar
+ void UnoScrollBarControl::addAdjustmentListener( const css::uno::Reference< css::awt::XAdjustmentListener > & l )
+ {
+ maAdjustmentListeners.addInterface( l );
+ }
+
+ void UnoScrollBarControl::removeAdjustmentListener( const css::uno::Reference< css::awt::XAdjustmentListener > & l )
+ {
+ maAdjustmentListeners.removeInterface( l );
+ }
+
+ void UnoScrollBarControl::setValue( sal_Int32 n )
+ {
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SCROLLVALUE ), uno::Any( n ), true );
+ }
+
+ void UnoScrollBarControl::setValues( sal_Int32 nValue, sal_Int32 nVisible, sal_Int32 nMax )
+ {
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SCROLLVALUE ), uno::Any(nValue), true );
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_VISIBLESIZE ), uno::Any(nVisible), true );
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SCROLLVALUE_MAX ), uno::Any(nMax), true );
+ }
+
+ sal_Int32 UnoScrollBarControl::getValue()
+ {
+ sal_Int32 n = 0;
+ if ( getPeer().is() )
+ {
+ uno::Reference< awt::XScrollBar > xScrollBar( getPeer(), uno::UNO_QUERY );
+ n = xScrollBar->getValue();
+ }
+ return n;
+ }
+
+ void UnoScrollBarControl::setMaximum( sal_Int32 n )
+ {
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SCROLLVALUE_MAX ), uno::Any( n ), true );
+ }
+
+ sal_Int32 UnoScrollBarControl::getMaximum()
+ {
+ sal_Int32 n = 0;
+ if ( getPeer().is() )
+ {
+ uno::Reference< awt::XScrollBar > xScrollBar( getPeer(), uno::UNO_QUERY );
+ n = xScrollBar->getMaximum();
+ }
+ return n;
+ }
+
+ void UnoScrollBarControl::setLineIncrement( sal_Int32 n )
+ {
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_LINEINCREMENT ), uno::Any( n ), true );
+ }
+
+ sal_Int32 UnoScrollBarControl::getLineIncrement()
+ {
+ sal_Int32 n = 0;
+ if ( getPeer().is() )
+ {
+ uno::Reference< awt::XScrollBar > xScrollBar( getPeer(), uno::UNO_QUERY );
+ n = xScrollBar->getLineIncrement();
+ }
+ return n;
+ }
+
+ void UnoScrollBarControl::setBlockIncrement( sal_Int32 n )
+ {
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_BLOCKINCREMENT ), uno::Any( n ), true );
+ }
+
+ sal_Int32 UnoScrollBarControl::getBlockIncrement()
+ {
+ sal_Int32 n = 0;
+ if ( getPeer().is() )
+ {
+ uno::Reference< awt::XScrollBar > xScrollBar( getPeer(), uno::UNO_QUERY );
+ n = xScrollBar->getBlockIncrement();
+ }
+ return n;
+ }
+
+ void UnoScrollBarControl::setVisibleSize( sal_Int32 n )
+ {
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_VISIBLESIZE ), uno::Any( n ), true );
+ }
+
+ sal_Int32 UnoScrollBarControl::getVisibleSize()
+ {
+ sal_Int32 n = 0;
+ if ( getPeer().is() )
+ {
+ uno::Reference< awt::XScrollBar > xScrollBar( getPeer(), uno::UNO_QUERY );
+ n = xScrollBar->getVisibleSize();
+ }
+ return n;
+ }
+
+ void UnoScrollBarControl::setOrientation( sal_Int32 n )
+ {
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_ORIENTATION ), uno::Any( n ), true );
+ }
+
+ sal_Int32 UnoScrollBarControl::getOrientation()
+ {
+ sal_Int32 n = 0;
+ if ( getPeer().is() )
+ {
+ uno::Reference< awt::XScrollBar > xScrollBar( getPeer(), uno::UNO_QUERY );
+ n = xScrollBar->getOrientation();
+ }
+ return n;
+ }
+
+ OUString UnoScrollBarControl::getImplementationName()
+ {
+ return "stardiv.Toolkit.UnoScrollBarControl";
+ }
+
+ css::uno::Sequence<OUString> UnoScrollBarControl::getSupportedServiceNames()
+ {
+ auto s(UnoControlBase::getSupportedServiceNames());
+ s.realloc(s.getLength() + 2);
+ auto ps = s.getArray();
+ ps[s.getLength() - 2] = "com.sun.star.awt.UnoControlScrollBar";
+ ps[s.getLength() - 1] = "stardiv.vcl.control.ScrollBar";
+ return s;
+ }
+
+} // namespace toolkit
+
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlScrollBarModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new toolkit::UnoControlScrollBarModel(context));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoScrollBarControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new toolkit::UnoScrollBarControl());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/tkspinbutton.cxx b/toolkit/source/controls/tkspinbutton.cxx
new file mode 100644
index 000000000..2040f6688
--- /dev/null
+++ b/toolkit/source/controls/tkspinbutton.cxx
@@ -0,0 +1,421 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/awt/ScrollBarOrientation.hpp>
+#include <com/sun/star/awt/XSpinValue.hpp>
+#include <com/sun/star/awt/XAdjustmentListener.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <comphelper/uno3.hxx>
+#include <cppuhelper/implbase2.hxx>
+#include <toolkit/controls/unocontrolmodel.hxx>
+#include <toolkit/controls/unocontrolbase.hxx>
+#include <toolkit/helper/property.hxx>
+
+#include <helper/unopropertyarrayhelper.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+
+namespace {
+
+class UnoSpinButtonModel : public UnoControlModel
+{
+protected:
+ css::uno::Any ImplGetDefaultValue( sal_uInt16 nPropId ) const override;
+ ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+public:
+ explicit UnoSpinButtonModel( const css::uno::Reference< css::uno::XComponentContext >& i_factory );
+
+ rtl::Reference<UnoControlModel> Clone() const override { return new UnoSpinButtonModel( *this ); }
+
+ // XMultiPropertySet
+ css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+
+ // XPersistObject
+ OUString SAL_CALL getServiceName() override;
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName( ) override;
+ css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+};
+
+
+//= UnoSpinButtonControl
+
+
+typedef ::cppu::ImplHelper2 < css::awt::XAdjustmentListener
+ , css::awt::XSpinValue
+ > UnoSpinButtonControl_Base;
+
+class UnoSpinButtonControl :public UnoControlBase
+ ,public UnoSpinButtonControl_Base
+{
+private:
+ AdjustmentListenerMultiplexer maAdjustmentListeners;
+
+public:
+ UnoSpinButtonControl();
+ OUString GetComponentServiceName() const override;
+
+ DECLARE_UNO3_AGG_DEFAULTS( UnoSpinButtonControl, UnoControlBase )
+ css::uno::Any SAL_CALL queryAggregation( const css::uno::Type & rType ) override;
+
+ void SAL_CALL createPeer( const css::uno::Reference< css::awt::XToolkit >& Toolkit, const css::uno::Reference< css::awt::XWindowPeer >& Parent ) override;
+ void SAL_CALL disposing( const css::lang::EventObject& Source ) override { UnoControlBase::disposing( Source ); }
+ void SAL_CALL dispose( ) override;
+
+ // XTypeProvider
+ DECLARE_XTYPEPROVIDER()
+
+ // XAdjustmentListener
+ void SAL_CALL adjustmentValueChanged( const css::awt::AdjustmentEvent& rEvent ) override;
+
+ // XSpinValue
+ virtual void SAL_CALL addAdjustmentListener( const css::uno::Reference< css::awt::XAdjustmentListener >& listener ) override;
+ virtual void SAL_CALL removeAdjustmentListener( const css::uno::Reference< css::awt::XAdjustmentListener >& listener ) override;
+ virtual void SAL_CALL setValue( sal_Int32 value ) override;
+ virtual void SAL_CALL setValues( sal_Int32 minValue, sal_Int32 maxValue, sal_Int32 currentValue ) override;
+ virtual sal_Int32 SAL_CALL getValue( ) override;
+ virtual void SAL_CALL setMinimum( sal_Int32 minValue ) override;
+ virtual void SAL_CALL setMaximum( sal_Int32 maxValue ) override;
+ virtual sal_Int32 SAL_CALL getMinimum( ) override;
+ virtual sal_Int32 SAL_CALL getMaximum( ) override;
+ virtual void SAL_CALL setSpinIncrement( sal_Int32 spinIncrement ) override;
+ virtual sal_Int32 SAL_CALL getSpinIncrement( ) override;
+ virtual void SAL_CALL setOrientation( sal_Int32 orientation ) override;
+ virtual sal_Int32 SAL_CALL getOrientation( ) override;
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName( ) override;
+ css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+};
+
+
+ //= UnoSpinButtonModel
+
+
+ UnoSpinButtonModel::UnoSpinButtonModel( const css::uno::Reference< css::uno::XComponentContext >& i_factory )
+ :UnoControlModel( i_factory )
+ {
+ ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_BORDER );
+ ImplRegisterProperty( BASEPROPERTY_BORDERCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
+ ImplRegisterProperty( BASEPROPERTY_ENABLED );
+ ImplRegisterProperty( BASEPROPERTY_ENABLEVISIBLE );
+ ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
+ ImplRegisterProperty( BASEPROPERTY_HELPURL );
+ ImplRegisterProperty( BASEPROPERTY_ORIENTATION );
+ ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
+ ImplRegisterProperty( BASEPROPERTY_REPEAT );
+ ImplRegisterProperty( BASEPROPERTY_REPEAT_DELAY );
+ ImplRegisterProperty( BASEPROPERTY_SYMBOL_COLOR );
+ ImplRegisterProperty( BASEPROPERTY_SPINVALUE );
+ ImplRegisterProperty( BASEPROPERTY_SPINVALUE_MIN );
+ ImplRegisterProperty( BASEPROPERTY_SPINVALUE_MAX );
+ ImplRegisterProperty( BASEPROPERTY_SPININCREMENT );
+ ImplRegisterProperty( BASEPROPERTY_TABSTOP );
+ ImplRegisterProperty( BASEPROPERTY_WRITING_MODE );
+ ImplRegisterProperty( BASEPROPERTY_CONTEXT_WRITING_MODE );
+ }
+
+
+ OUString UnoSpinButtonModel::getServiceName( )
+ {
+ return "com.sun.star.awt.UnoControlSpinButtonModel";
+ }
+
+
+ Any UnoSpinButtonModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+ {
+ switch ( nPropId )
+ {
+ case BASEPROPERTY_DEFAULTCONTROL:
+ return Any( OUString("com.sun.star.awt.UnoControlSpinButton") );
+
+ case BASEPROPERTY_BORDER:
+ return Any( sal_Int16(0) );
+
+ case BASEPROPERTY_REPEAT:
+ return Any( true );
+
+ default:
+ return UnoControlModel::ImplGetDefaultValue( nPropId );
+ }
+ }
+
+
+ ::cppu::IPropertyArrayHelper& UnoSpinButtonModel::getInfoHelper()
+ {
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+ }
+
+
+ Reference< XPropertySetInfo > UnoSpinButtonModel::getPropertySetInfo( )
+ {
+ static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+ }
+
+
+ OUString SAL_CALL UnoSpinButtonModel::getImplementationName( )
+ {
+ return "stardiv.Toolkit.UnoSpinButtonModel";
+ }
+
+
+ Sequence< OUString > SAL_CALL UnoSpinButtonModel::getSupportedServiceNames()
+ {
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlSpinButtonModel" };
+ return comphelper::concatSequences( UnoControlModel::getSupportedServiceNames(), vals );
+ }
+
+
+ //= UnoSpinButtonControl
+
+
+ UnoSpinButtonControl::UnoSpinButtonControl()
+ :maAdjustmentListeners( *this )
+ {
+ }
+
+
+ OUString UnoSpinButtonControl::GetComponentServiceName() const
+ {
+ return "SpinButton";
+ }
+
+
+ Any UnoSpinButtonControl::queryAggregation( const Type & rType )
+ {
+ Any aRet = UnoControlBase::queryAggregation( rType );
+ if ( !aRet.hasValue() )
+ aRet = UnoSpinButtonControl_Base::queryInterface( rType );
+ return aRet;
+ }
+
+
+ IMPLEMENT_FORWARD_XTYPEPROVIDER2( UnoSpinButtonControl, UnoControlBase, UnoSpinButtonControl_Base )
+
+
+ void UnoSpinButtonControl::dispose()
+ {
+ ::osl::ClearableMutexGuard aGuard( GetMutex() );
+ if ( maAdjustmentListeners.getLength() )
+ {
+ Reference< XSpinValue > xSpinnable( getPeer(), UNO_QUERY );
+ if ( xSpinnable.is() )
+ xSpinnable->removeAdjustmentListener( this );
+
+ EventObject aDisposeEvent;
+ aDisposeEvent.Source = *this;
+
+ aGuard.clear();
+ maAdjustmentListeners.disposeAndClear( aDisposeEvent );
+ }
+
+ UnoControl::dispose();
+ }
+
+
+ OUString SAL_CALL UnoSpinButtonControl::getImplementationName( )
+ {
+ return "stardiv.Toolkit.UnoSpinButtonControl";
+ }
+
+
+ Sequence< OUString > SAL_CALL UnoSpinButtonControl::getSupportedServiceNames()
+ {
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlSpinButton" };
+ return comphelper::concatSequences( UnoControlBase::getSupportedServiceNames(), vals );
+ }
+
+
+ void UnoSpinButtonControl::createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer > & rParentPeer )
+ {
+ UnoControl::createPeer( rxToolkit, rParentPeer );
+
+ Reference < XSpinValue > xSpinnable( getPeer(), UNO_QUERY );
+ if ( xSpinnable.is() )
+ xSpinnable->addAdjustmentListener( this );
+ }
+
+
+ void UnoSpinButtonControl::adjustmentValueChanged( const AdjustmentEvent& rEvent )
+ {
+ switch ( rEvent.Type )
+ {
+ case AdjustmentType_ADJUST_LINE:
+ case AdjustmentType_ADJUST_PAGE:
+ case AdjustmentType_ADJUST_ABS:
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SPINVALUE ), Any( rEvent.Value ), false );
+ break;
+ default:
+ OSL_FAIL( "UnoSpinButtonControl::adjustmentValueChanged - unknown Type" );
+ }
+
+ if ( maAdjustmentListeners.getLength() )
+ {
+ AdjustmentEvent aEvent( rEvent );
+ aEvent.Source = *this;
+ maAdjustmentListeners.adjustmentValueChanged( aEvent );
+ }
+ }
+
+
+ void UnoSpinButtonControl::addAdjustmentListener( const Reference< XAdjustmentListener > & listener )
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ maAdjustmentListeners.addInterface( listener );
+ }
+
+
+ void UnoSpinButtonControl::removeAdjustmentListener( const Reference< XAdjustmentListener > & listener )
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ maAdjustmentListeners.removeInterface( listener );
+ }
+
+
+ void SAL_CALL UnoSpinButtonControl::setValue( sal_Int32 value )
+ {
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SPINVALUE ), Any( value ), true );
+ }
+
+
+ void SAL_CALL UnoSpinButtonControl::setValues( sal_Int32 minValue, sal_Int32 maxValue, sal_Int32 currentValue )
+ {
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SPINVALUE_MIN ), Any( minValue ), true );
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SPINVALUE_MAX ), Any( maxValue ), true );
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SPINVALUE ), Any( currentValue ), true );
+ }
+
+
+ sal_Int32 SAL_CALL UnoSpinButtonControl::getValue( )
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ sal_Int32 nValue = 0;
+
+ Reference< XSpinValue > xSpinnable( getPeer(), UNO_QUERY );
+ if ( xSpinnable.is() )
+ nValue = xSpinnable->getValue();
+
+ return nValue;
+ }
+
+
+ void SAL_CALL UnoSpinButtonControl::setMinimum( sal_Int32 minValue )
+ {
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SPINVALUE_MIN ), Any( minValue ), true );
+ }
+
+
+ void SAL_CALL UnoSpinButtonControl::setMaximum( sal_Int32 maxValue )
+ {
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SPINVALUE_MAX ), Any( maxValue ), true );
+ }
+
+
+ sal_Int32 SAL_CALL UnoSpinButtonControl::getMinimum( )
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ sal_Int32 nMin = 0;
+
+ Reference< XSpinValue > xSpinnable( getPeer(), UNO_QUERY );
+ if ( xSpinnable.is() )
+ nMin = xSpinnable->getMinimum();
+
+ return nMin;
+ }
+
+
+ sal_Int32 SAL_CALL UnoSpinButtonControl::getMaximum( )
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ sal_Int32 nMax = 0;
+
+ Reference< XSpinValue > xSpinnable( getPeer(), UNO_QUERY );
+ if ( xSpinnable.is() )
+ nMax = xSpinnable->getMaximum();
+
+ return nMax;
+ }
+
+
+ void SAL_CALL UnoSpinButtonControl::setSpinIncrement( sal_Int32 spinIncrement )
+ {
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SPININCREMENT ), Any( spinIncrement ), true );
+ }
+
+
+ sal_Int32 SAL_CALL UnoSpinButtonControl::getSpinIncrement( )
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ sal_Int32 nIncrement = 0;
+
+ Reference< XSpinValue > xSpinnable( getPeer(), UNO_QUERY );
+ if ( xSpinnable.is() )
+ nIncrement = xSpinnable->getSpinIncrement();
+
+ return nIncrement;
+ }
+
+
+ void SAL_CALL UnoSpinButtonControl::setOrientation( sal_Int32 orientation )
+ {
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_ORIENTATION ), Any( orientation ), true );
+ }
+
+
+ sal_Int32 SAL_CALL UnoSpinButtonControl::getOrientation( )
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ sal_Int32 nOrientation = ScrollBarOrientation::HORIZONTAL;
+
+ Reference< XSpinValue > xSpinnable( getPeer(), UNO_QUERY );
+ if ( xSpinnable.is() )
+ nOrientation = xSpinnable->getOrientation();
+
+ return nOrientation;
+ }
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoSpinButtonModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoSpinButtonModel(context));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoSpinButtonControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoSpinButtonControl());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/tree/treecontrol.cxx b/toolkit/source/controls/tree/treecontrol.cxx
new file mode 100644
index 000000000..d4439a4ff
--- /dev/null
+++ b/toolkit/source/controls/tree/treecontrol.cxx
@@ -0,0 +1,514 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "treecontrol.hxx"
+
+#include <com/sun/star/awt/tree/XTreeControl.hpp>
+#include <com/sun/star/awt/tree/XTreeDataModel.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/view/SelectionType.hpp>
+#include <toolkit/controls/unocontrolbase.hxx>
+#include <toolkit/helper/property.hxx>
+#include <osl/diagnose.h>
+#include <cppuhelper/implbase.hxx>
+
+#include <helper/unopropertyarrayhelper.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::awt::tree;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::view;
+
+namespace toolkit
+{
+
+
+UnoTreeModel::UnoTreeModel( const css::uno::Reference< css::uno::XComponentContext >& i_factory )
+ :UnoControlModel( i_factory )
+{
+ ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_BORDER );
+ ImplRegisterProperty( BASEPROPERTY_BORDERCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
+ ImplRegisterProperty( BASEPROPERTY_ENABLED );
+ ImplRegisterProperty( BASEPROPERTY_ENABLEVISIBLE );
+ ImplRegisterProperty( BASEPROPERTY_FILLCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
+ ImplRegisterProperty( BASEPROPERTY_HELPURL );
+ ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
+ ImplRegisterProperty( BASEPROPERTY_TABSTOP );
+ ImplRegisterProperty( BASEPROPERTY_TREE_SELECTIONTYPE );
+ ImplRegisterProperty( BASEPROPERTY_TREE_EDITABLE );
+ ImplRegisterProperty( BASEPROPERTY_TREE_DATAMODEL );
+ ImplRegisterProperty( BASEPROPERTY_TREE_ROOTDISPLAYED );
+ ImplRegisterProperty( BASEPROPERTY_TREE_SHOWSHANDLES );
+ ImplRegisterProperty( BASEPROPERTY_TREE_SHOWSROOTHANDLES );
+ ImplRegisterProperty( BASEPROPERTY_ROW_HEIGHT );
+ ImplRegisterProperty( BASEPROPERTY_TREE_INVOKESSTOPNODEEDITING );
+ ImplRegisterProperty( BASEPROPERTY_HIDEINACTIVESELECTION );
+}
+
+rtl::Reference<UnoControlModel> UnoTreeModel::Clone() const
+{
+ return new UnoTreeModel( *this );
+}
+
+OUString UnoTreeModel::getServiceName()
+{
+ return "com.sun.star.awt.tree.TreeControlModel";
+}
+
+Any UnoTreeModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ switch( nPropId )
+ {
+ case BASEPROPERTY_TREE_SELECTIONTYPE:
+ return Any( SelectionType_NONE );
+ case BASEPROPERTY_ROW_HEIGHT:
+ return Any( sal_Int32( 0 ) );
+ case BASEPROPERTY_TREE_DATAMODEL:
+ return Any( Reference< XTreeDataModel >( nullptr ) );
+ case BASEPROPERTY_TREE_EDITABLE:
+ case BASEPROPERTY_TREE_INVOKESSTOPNODEEDITING:
+ return Any( false );
+ case BASEPROPERTY_TREE_ROOTDISPLAYED:
+ case BASEPROPERTY_TREE_SHOWSROOTHANDLES:
+ case BASEPROPERTY_TREE_SHOWSHANDLES:
+ return Any( true );
+ case BASEPROPERTY_DEFAULTCONTROL:
+ return uno::Any( OUString( "com.sun.star.awt.tree.TreeControl" ) );
+ default:
+ return UnoControlModel::ImplGetDefaultValue( nPropId );
+ }
+}
+
+::cppu::IPropertyArrayHelper& UnoTreeModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+// XMultiPropertySet
+Reference< XPropertySetInfo > UnoTreeModel::getPropertySetInfo( )
+{
+ static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+}
+
+namespace {
+
+typedef ::cppu::ImplInheritanceHelper< UnoControlBase, css::awt::tree::XTreeControl > UnoTreeControl_Base;
+class UnoTreeControl : public UnoTreeControl_Base
+{
+public:
+ UnoTreeControl();
+ OUString GetComponentServiceName() const override;
+
+ // css::lang::XComponent
+ void SAL_CALL dispose( ) override;
+
+ // css::awt::XControl
+ void SAL_CALL createPeer( const css::uno::Reference< css::awt::XToolkit >& Toolkit, const css::uno::Reference< css::awt::XWindowPeer >& Parent ) override;
+
+ // css::view::XSelectionSupplier
+ virtual sal_Bool SAL_CALL select( const css::uno::Any& xSelection ) override;
+ virtual css::uno::Any SAL_CALL getSelection( ) override;
+ virtual void SAL_CALL addSelectionChangeListener( const css::uno::Reference< css::view::XSelectionChangeListener >& xListener ) override;
+ virtual void SAL_CALL removeSelectionChangeListener( const css::uno::Reference< css::view::XSelectionChangeListener >& xListener ) override;
+
+ // css::view::XMultiSelectionSupplier
+ virtual sal_Bool SAL_CALL addSelection( const css::uno::Any& Selection ) override;
+ virtual void SAL_CALL removeSelection( const css::uno::Any& Selection ) override;
+ virtual void SAL_CALL clearSelection( ) override;
+ virtual ::sal_Int32 SAL_CALL getSelectionCount( ) override;
+ virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createSelectionEnumeration( ) override;
+ virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createReverseSelectionEnumeration( ) override;
+
+ // css::awt::XTreeControl
+ virtual OUString SAL_CALL getDefaultExpandedGraphicURL() override;
+ virtual void SAL_CALL setDefaultExpandedGraphicURL( const OUString& _defaultexpandedgraphicurl ) override;
+ virtual OUString SAL_CALL getDefaultCollapsedGraphicURL() override;
+ virtual void SAL_CALL setDefaultCollapsedGraphicURL( const OUString& _defaultcollapsedgraphicurl ) override;
+ virtual sal_Bool SAL_CALL isNodeExpanded( const css::uno::Reference< css::awt::tree::XTreeNode >& Node ) override;
+ virtual sal_Bool SAL_CALL isNodeCollapsed( const css::uno::Reference< css::awt::tree::XTreeNode >& Node ) override;
+ virtual void SAL_CALL makeNodeVisible( const css::uno::Reference< css::awt::tree::XTreeNode >& Node ) override;
+ virtual sal_Bool SAL_CALL isNodeVisible( const css::uno::Reference< css::awt::tree::XTreeNode >& Node ) override;
+ virtual void SAL_CALL expandNode( const css::uno::Reference< css::awt::tree::XTreeNode >& Node ) override;
+ virtual void SAL_CALL collapseNode( const css::uno::Reference< css::awt::tree::XTreeNode >& Node ) override;
+ virtual void SAL_CALL addTreeExpansionListener( const css::uno::Reference< css::awt::tree::XTreeExpansionListener >& Listener ) override;
+ virtual void SAL_CALL removeTreeExpansionListener( const css::uno::Reference< css::awt::tree::XTreeExpansionListener >& Listener ) override;
+ virtual css::uno::Reference< css::awt::tree::XTreeNode > SAL_CALL getNodeForLocation( ::sal_Int32 x, ::sal_Int32 y ) override;
+ virtual css::uno::Reference< css::awt::tree::XTreeNode > SAL_CALL getClosestNodeForLocation( ::sal_Int32 x, ::sal_Int32 y ) override;
+ virtual css::awt::Rectangle SAL_CALL getNodeRect( const css::uno::Reference< css::awt::tree::XTreeNode >& Node ) override;
+ virtual sal_Bool SAL_CALL isEditing( ) override;
+ virtual sal_Bool SAL_CALL stopEditing( ) override;
+ virtual void SAL_CALL cancelEditing( ) override;
+ virtual void SAL_CALL startEditingAtNode( const css::uno::Reference< css::awt::tree::XTreeNode >& Node ) override;
+ virtual void SAL_CALL addTreeEditListener( const css::uno::Reference< css::awt::tree::XTreeEditListener >& Listener ) override;
+ virtual void SAL_CALL removeTreeEditListener( const css::uno::Reference< css::awt::tree::XTreeEditListener >& Listener ) override;
+
+ // css::lang::XServiceInfo
+ DECLIMPL_SERVICEINFO_DERIVED( UnoTreeControl, UnoControlBase, "com.sun.star.awt.tree.TreeControl" )
+
+ using UnoControl::getPeer;
+private:
+ TreeSelectionListenerMultiplexer maSelectionListeners;
+ TreeExpansionListenerMultiplexer maTreeExpansionListeners;
+ TreeEditListenerMultiplexer maTreeEditListeners;
+};
+
+UnoTreeControl::UnoTreeControl()
+: maSelectionListeners( *this )
+, maTreeExpansionListeners( *this )
+, maTreeEditListeners( *this )
+{
+}
+
+OUString UnoTreeControl::GetComponentServiceName() const
+{
+ return "Tree";
+}
+
+
+// css::view::XSelectionSupplier
+
+
+sal_Bool SAL_CALL UnoTreeControl::select( const Any& rSelection )
+{
+ return Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->select( rSelection );
+}
+
+
+Any SAL_CALL UnoTreeControl::getSelection()
+{
+ return Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->getSelection();
+}
+
+
+void SAL_CALL UnoTreeControl::addSelectionChangeListener( const Reference< XSelectionChangeListener >& xListener )
+{
+ maSelectionListeners.addInterface( xListener );
+ if( getPeer().is() && (maSelectionListeners.getLength() == 1) )
+ {
+ // maSelectionListeners acts as a proxy,
+ // add it to the peer if this is the first listener added to that proxy
+ Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->addSelectionChangeListener(&maSelectionListeners);
+ }
+}
+
+
+void SAL_CALL UnoTreeControl::removeSelectionChangeListener( const Reference< XSelectionChangeListener >& xListener )
+{
+ if( getPeer().is() && (maSelectionListeners.getLength() == 1) )
+ {
+ // maSelectionListeners acts as a proxy,
+ // remove it from the peer if this is the last listener removed from that proxy
+ Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->removeSelectionChangeListener(&maSelectionListeners);
+ }
+ maSelectionListeners.removeInterface( xListener );
+}
+
+
+// css::view::XMultiSelectionSupplier
+
+
+sal_Bool SAL_CALL UnoTreeControl::addSelection( const Any& rSelection )
+{
+ return Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->addSelection(rSelection);
+}
+
+
+void SAL_CALL UnoTreeControl::removeSelection( const Any& rSelection )
+{
+ Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->removeSelection(rSelection);
+}
+
+
+void SAL_CALL UnoTreeControl::clearSelection()
+{
+ Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->clearSelection();
+}
+
+
+sal_Int32 SAL_CALL UnoTreeControl::getSelectionCount()
+{
+ return Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->getSelectionCount();
+}
+
+
+Reference< XEnumeration > SAL_CALL UnoTreeControl::createSelectionEnumeration()
+{
+ return Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->createSelectionEnumeration();
+}
+
+
+Reference< XEnumeration > SAL_CALL UnoTreeControl::createReverseSelectionEnumeration()
+{
+ return Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->createReverseSelectionEnumeration();
+}
+
+
+// XTreeControl
+
+
+OUString SAL_CALL UnoTreeControl::getDefaultExpandedGraphicURL()
+{
+ return Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->getDefaultExpandedGraphicURL();
+}
+
+
+void SAL_CALL UnoTreeControl::setDefaultExpandedGraphicURL( const OUString& _defaultexpansiongraphicurl )
+{
+ Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->setDefaultExpandedGraphicURL(_defaultexpansiongraphicurl);
+}
+
+
+OUString SAL_CALL UnoTreeControl::getDefaultCollapsedGraphicURL()
+{
+ return Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->getDefaultCollapsedGraphicURL();
+}
+
+
+void SAL_CALL UnoTreeControl::setDefaultCollapsedGraphicURL( const OUString& _defaultcollapsedgraphicurl )
+{
+ Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->setDefaultCollapsedGraphicURL(_defaultcollapsedgraphicurl);
+}
+
+
+sal_Bool SAL_CALL UnoTreeControl::isNodeExpanded( const Reference< XTreeNode >& xNode )
+{
+ return Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->isNodeExpanded(xNode);
+}
+
+
+sal_Bool SAL_CALL UnoTreeControl::isNodeCollapsed( const Reference< XTreeNode >& xNode )
+{
+ return Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->isNodeCollapsed(xNode);
+}
+
+
+void SAL_CALL UnoTreeControl::makeNodeVisible( const Reference< XTreeNode >& xNode )
+{
+ Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->makeNodeVisible(xNode);
+}
+
+
+sal_Bool SAL_CALL UnoTreeControl::isNodeVisible( const Reference< XTreeNode >& xNode )
+{
+ return Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->isNodeVisible(xNode);
+}
+
+
+void SAL_CALL UnoTreeControl::expandNode( const Reference< XTreeNode >& xNode )
+{
+ Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->expandNode(xNode);
+}
+
+
+void SAL_CALL UnoTreeControl::collapseNode( const Reference< XTreeNode >& xNode )
+{
+ Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->collapseNode(xNode);
+}
+
+
+void SAL_CALL UnoTreeControl::addTreeExpansionListener( const Reference< XTreeExpansionListener >& xListener )
+{
+ maTreeExpansionListeners.addInterface( xListener );
+ if( getPeer().is() && (maTreeExpansionListeners.getLength() == 1) )
+ {
+ // maSelectionListeners acts as a proxy,
+ // add it to the peer if this is the first listener added to that proxy
+ Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->addTreeExpansionListener(&maTreeExpansionListeners);
+ }
+}
+
+
+void SAL_CALL UnoTreeControl::removeTreeExpansionListener( const Reference< XTreeExpansionListener >& xListener )
+{
+ if( getPeer().is() && (maTreeExpansionListeners.getLength() == 1) )
+ {
+ // maSelectionListeners acts as a proxy,
+ // remove it from the peer if this is the last listener removed from that proxy
+ Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->removeTreeExpansionListener(&maTreeExpansionListeners);
+ }
+ maTreeExpansionListeners.removeInterface( xListener );
+}
+
+
+Reference< XTreeNode > SAL_CALL UnoTreeControl::getNodeForLocation( sal_Int32 x, sal_Int32 y )
+{
+ return Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->getNodeForLocation(x,y);
+}
+
+
+Reference< XTreeNode > SAL_CALL UnoTreeControl::getClosestNodeForLocation( sal_Int32 x, sal_Int32 y )
+{
+ return Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->getClosestNodeForLocation(x,y);
+}
+
+
+awt::Rectangle SAL_CALL UnoTreeControl::getNodeRect( const Reference< XTreeNode >& Node )
+{
+ return Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->getNodeRect( Node );
+}
+
+
+sal_Bool SAL_CALL UnoTreeControl::isEditing( )
+{
+ return Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->isEditing();
+}
+
+
+sal_Bool SAL_CALL UnoTreeControl::stopEditing()
+{
+ return Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->stopEditing();
+}
+
+
+void SAL_CALL UnoTreeControl::cancelEditing()
+{
+ Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->cancelEditing();
+}
+
+
+void SAL_CALL UnoTreeControl::startEditingAtNode( const Reference< XTreeNode >& xNode )
+{
+ Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->startEditingAtNode(xNode);
+}
+
+
+void SAL_CALL UnoTreeControl::addTreeEditListener( const Reference< XTreeEditListener >& xListener )
+{
+ maTreeEditListeners.addInterface( xListener );
+ if( getPeer().is() && (maTreeEditListeners.getLength() == 1) )
+ {
+ // maSelectionListeners acts as a proxy,
+ // add it to the peer if this is the first listener added to that proxy
+ Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->addTreeEditListener(&maTreeEditListeners);
+ }
+}
+
+
+void SAL_CALL UnoTreeControl::removeTreeEditListener( const Reference< XTreeEditListener >& xListener )
+{
+ if( getPeer().is() && (maTreeEditListeners.getLength() == 1) )
+ {
+ // maSelectionListeners acts as a proxy,
+ // remove it from the peer if this is the last listener removed from that proxy
+ Reference< XTreeControl >( getPeer(), UNO_QUERY_THROW )->removeTreeEditListener(&maTreeEditListeners);
+ }
+ maTreeEditListeners.removeInterface( xListener );
+}
+
+
+// XComponent
+
+
+void SAL_CALL UnoTreeControl::dispose( )
+{
+ lang::EventObject aEvt;
+ aEvt.Source = static_cast< ::cppu::OWeakObject* >(this);
+ maSelectionListeners.disposeAndClear( aEvt );
+ maTreeExpansionListeners.disposeAndClear( aEvt );
+ UnoControl::dispose();
+}
+
+void UnoTreeControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer > & rParentPeer )
+{
+ UnoControlBase::createPeer( rxToolkit, rParentPeer );
+
+ Reference< XTreeControl > xTree( getPeer(), UNO_QUERY_THROW );
+ if( maSelectionListeners.getLength() )
+ xTree->addSelectionChangeListener( &maSelectionListeners );
+ if( maTreeExpansionListeners.getLength() )
+ xTree->addTreeExpansionListener( &maTreeExpansionListeners );
+}
+
+}
+
+void SAL_CALL TreeEditListenerMultiplexer::nodeEditing( const Reference< XTreeNode >& Node )
+{
+ ::comphelper::OInterfaceIteratorHelper3 aIt(*this);
+ while( aIt.hasMoreElements() )
+ {
+ Reference<XTreeEditListener> xListener(aIt.next());
+ try
+ {
+ xListener->nodeEditing( Node );
+ }
+ catch( const DisposedException& e )
+ {
+ OSL_ENSURE( e.Context.is(), "caught DisposedException with empty Context field" );
+ if ( e.Context == xListener || !e.Context.is() )
+ aIt.remove();
+ }
+ catch( const RuntimeException& )
+ {
+ DISPLAY_EXCEPTION( TreeEditListenerMultiplexer, nodeEditing )
+ }
+ }
+}
+
+void SAL_CALL TreeEditListenerMultiplexer::nodeEdited( const Reference< XTreeNode >& Node, const OUString& NewText )
+{
+ ::comphelper::OInterfaceIteratorHelper3 aIt(*this);
+ while( aIt.hasMoreElements() )
+ {
+ Reference<XTreeEditListener> xListener(aIt.next());
+ try
+ {
+ xListener->nodeEdited( Node, NewText );
+ }
+ catch( const DisposedException& e )
+ {
+ OSL_ENSURE( e.Context.is(), "caught DisposedException with empty Context field" );
+ if ( e.Context == xListener || !e.Context.is() )
+ aIt.remove();
+ }
+ catch( const RuntimeException& )
+ {
+ DISPLAY_EXCEPTION( TreeEditListenerMultiplexer, nodeEdited )
+ }
+ }
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_TreeControlModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new toolkit::UnoTreeModel(context));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_TreeControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoTreeControl());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/tree/treecontrol.hxx b/toolkit/source/controls/tree/treecontrol.hxx
new file mode 100644
index 000000000..af4793fe9
--- /dev/null
+++ b/toolkit/source/controls/tree/treecontrol.hxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_TOOLKIT_SOURCE_CONTROLS_TREE_TREECONTROL_HXX
+#define INCLUDED_TOOLKIT_SOURCE_CONTROLS_TREE_TREECONTROL_HXX
+
+#include <toolkit/controls/unocontrolmodel.hxx>
+
+namespace toolkit
+{
+// = UnoTreeModel
+
+class UnoTreeModel : public UnoControlModel
+{
+protected:
+ css::uno::Any ImplGetDefaultValue(sal_uInt16 nPropId) const override;
+ ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+public:
+ explicit UnoTreeModel(const css::uno::Reference<css::uno::XComponentContext>& i_factory);
+
+ rtl::Reference<UnoControlModel> Clone() const override;
+
+ // css::beans::XMultiPropertySet
+ css::uno::Reference<css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
+
+ // css::io::XPersistObject
+ OUString SAL_CALL getServiceName() override;
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName() override
+ {
+ return "stardiv.Toolkit.TreeControlModel";
+ }
+
+ css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
+ {
+ auto s(UnoControlModel::getSupportedServiceNames());
+ s.realloc(s.getLength() + 1);
+ s.getArray()[s.getLength() - 1] = "com.sun.star.awt.tree.TreeControlModel";
+ return s;
+ }
+};
+
+} // toolkit
+
+#endif // _ INCLUDED_TOOLKIT_SOURCE_CONTROLS_TREE_TREECONTROL_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/tree/treecontrolpeer.cxx b/toolkit/source/controls/tree/treecontrolpeer.cxx
new file mode 100644
index 000000000..fe273e0f6
--- /dev/null
+++ b/toolkit/source/controls/tree/treecontrolpeer.cxx
@@ -0,0 +1,1579 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <com/sun/star/graphic/GraphicProvider.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/view/SelectionType.hpp>
+#include <com/sun/star/util/VetoException.hpp>
+#include <o3tl/any.hxx>
+#include <toolkit/helper/property.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+
+#include <com/sun/star/awt/tree/XMutableTreeNode.hpp>
+#include <controls/treecontrolpeer.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertyvalue.hxx>
+
+#include <cppuhelper/implbase.hxx>
+#include <rtl/ref.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/toolkit/treelistbox.hxx>
+#include <vcl/toolkit/treelistentry.hxx>
+#include <vcl/toolkit/viewdataentry.hxx>
+#include <vcl/toolkit/svlbitm.hxx>
+
+#include <map>
+#include <memory>
+#include <list>
+
+using namespace ::com::sun::star;
+using namespace css::uno;
+using namespace css::lang;
+using namespace css::awt::tree;
+using namespace css::beans;
+using namespace css::view;
+using namespace css::container;
+using namespace css::util;
+using namespace css::graphic;
+
+namespace {
+
+struct LockGuard
+{
+public:
+ explicit LockGuard( sal_Int32& rLock )
+ : mrLock( rLock )
+ {
+ rLock++;
+ }
+
+ ~LockGuard()
+ {
+ mrLock--;
+ }
+
+ sal_Int32& mrLock;
+};
+
+
+class ImplContextGraphicItem : public SvLBoxContextBmp
+{
+public:
+ ImplContextGraphicItem( Image const & rI1, Image const & rI2, bool bExpanded)
+ : SvLBoxContextBmp(rI1, rI2, bExpanded) {}
+
+ OUString msExpandedGraphicURL;
+ OUString msCollapsedGraphicURL;
+};
+
+
+}
+
+class UnoTreeListBoxImpl : public SvTreeListBox
+{
+public:
+ UnoTreeListBoxImpl( TreeControlPeer* pPeer, vcl::Window* pParent, WinBits nWinStyle );
+ virtual ~UnoTreeListBoxImpl() override;
+ virtual void dispose() override;
+
+ void insert( SvTreeListEntry* pEntry, SvTreeListEntry* pParent, sal_uLong nPos );
+
+ virtual void RequestingChildren( SvTreeListEntry* pParent ) override;
+
+ virtual bool EditingEntry( SvTreeListEntry* pEntry ) override;
+ virtual bool EditedEntry( SvTreeListEntry* pEntry, const OUString& rNewText ) override;
+
+ DECL_LINK(OnSelectionChangeHdl, SvTreeListBox*, void);
+ DECL_LINK(OnExpandingHdl, SvTreeListBox*, bool);
+ DECL_LINK(OnExpandedHdl, SvTreeListBox*, void);
+
+private:
+ rtl::Reference< TreeControlPeer > mxPeer;
+};
+
+
+namespace {
+
+class UnoTreeListItem : public SvLBoxString
+{
+public:
+ UnoTreeListItem();
+
+ void InitViewData( SvTreeListBox*,SvTreeListEntry*,SvViewDataItem * = nullptr ) override;
+ void SetImage( const Image& rImage );
+ const OUString& GetGraphicURL() const { return maGraphicURL;}
+ void SetGraphicURL( const OUString& rGraphicURL );
+ virtual void Paint(const Point& rPos, SvTreeListBox& rOutDev, vcl::RenderContext& rRenderContext,
+ const SvViewDataEntry* pView, const SvTreeListEntry& rEntry) override;
+ std::unique_ptr<SvLBoxItem> Clone( SvLBoxItem const * pSource ) const override;
+
+private:
+ OUString maGraphicURL;
+ Image maImage;
+};
+
+}
+
+class UnoTreeListEntry : public SvTreeListEntry
+{
+public:
+ UnoTreeListEntry( const Reference< XTreeNode >& xNode, TreeControlPeer* pPeer );
+ virtual ~UnoTreeListEntry() override;
+
+ Reference< XTreeNode > mxNode;
+ TreeControlPeer* mpPeer;
+};
+
+TreeControlPeer::TreeControlPeer()
+ : maSelectionListeners( *this )
+ , maTreeExpansionListeners( *this )
+ , maTreeEditListeners( *this )
+ , mbIsRootDisplayed(false)
+ , mpTreeImpl( nullptr )
+ , mnEditLock( 0 )
+{
+}
+
+
+TreeControlPeer::~TreeControlPeer()
+{
+ if( mpTreeImpl )
+ mpTreeImpl->Clear();
+}
+
+
+void TreeControlPeer::addEntry( UnoTreeListEntry* pEntry )
+{
+ if( pEntry && pEntry->mxNode.is() )
+ {
+ if( !mpTreeNodeMap )
+ {
+ mpTreeNodeMap.reset( new TreeNodeMap );
+ }
+
+ (*mpTreeNodeMap)[ pEntry->mxNode ] = pEntry;
+ }
+}
+
+
+void TreeControlPeer::removeEntry( UnoTreeListEntry const * pEntry )
+{
+ if( mpTreeNodeMap && pEntry && pEntry->mxNode.is() )
+ {
+ TreeNodeMap::iterator aIter( mpTreeNodeMap->find( pEntry->mxNode ) );
+ if( aIter != mpTreeNodeMap->end() )
+ {
+ mpTreeNodeMap->erase( aIter );
+ }
+ }
+}
+
+
+UnoTreeListEntry* TreeControlPeer::getEntry( const Reference< XTreeNode >& xNode, bool bThrow /* = true */ )
+{
+ if( mpTreeNodeMap )
+ {
+ TreeNodeMap::iterator aIter( mpTreeNodeMap->find( xNode ) );
+ if( aIter != mpTreeNodeMap->end() )
+ return (*aIter).second;
+ }
+
+ if( bThrow )
+ throw IllegalArgumentException();
+
+ return nullptr;
+}
+
+
+vcl::Window* TreeControlPeer::createVclControl( vcl::Window* pParent, sal_Int64 nWinStyle )
+{
+ mpTreeImpl = VclPtr<UnoTreeListBoxImpl>::Create( this, pParent, nWinStyle );
+ return mpTreeImpl;
+}
+
+
+/** called from the UnoTreeListBoxImpl when it gets deleted */
+void TreeControlPeer::disposeControl()
+{
+ mpTreeNodeMap.reset();
+ mpTreeImpl = nullptr;
+}
+
+
+UnoTreeListEntry* TreeControlPeer::createEntry( const Reference< XTreeNode >& xNode, UnoTreeListEntry* pParent, sal_uLong nPos /* = TREELIST_APPEND */ )
+{
+ UnoTreeListEntry* pEntry = nullptr;
+ if( mpTreeImpl )
+ {
+ Image aImage;
+ pEntry = new UnoTreeListEntry( xNode, this );
+ pEntry->AddItem(std::make_unique<ImplContextGraphicItem>(aImage, aImage, true));
+
+ std::unique_ptr<UnoTreeListItem> pUnoItem(new UnoTreeListItem);
+
+ if( !xNode->getNodeGraphicURL().isEmpty() )
+ {
+ pUnoItem->SetGraphicURL( xNode->getNodeGraphicURL() );
+ Image aNodeImage;
+ loadImage( xNode->getNodeGraphicURL(), aNodeImage );
+ pUnoItem->SetImage( aNodeImage );
+ mpTreeImpl->AdjustEntryHeight( aNodeImage );
+ }
+
+ pEntry->AddItem(std::move(pUnoItem));
+
+ mpTreeImpl->insert( pEntry, pParent, nPos );
+
+ if( !msDefaultExpandedGraphicURL.isEmpty() )
+ mpTreeImpl->SetExpandedEntryBmp( pEntry, maDefaultExpandedImage );
+
+ if( !msDefaultCollapsedGraphicURL.isEmpty() )
+ mpTreeImpl->SetCollapsedEntryBmp( pEntry, maDefaultCollapsedImage );
+
+ updateEntry( pEntry );
+ }
+ return pEntry;
+}
+
+
+void TreeControlPeer::updateEntry( UnoTreeListEntry* pEntry )
+{
+ bool bChanged = false;
+ if( !(pEntry && pEntry->mxNode.is() && mpTreeImpl) )
+ return;
+
+ const OUString aValue( getEntryString( pEntry->mxNode->getDisplayValue() ) );
+ UnoTreeListItem* pUnoItem = dynamic_cast< UnoTreeListItem* >( &pEntry->GetItem( 1 ) );
+ if( pUnoItem )
+ {
+ if( aValue != pUnoItem->GetText() )
+ {
+ pUnoItem->SetText( aValue );
+ bChanged = true;
+ }
+
+ if( pUnoItem->GetGraphicURL() != pEntry->mxNode->getNodeGraphicURL() )
+ {
+ Image aImage;
+ if( loadImage( pEntry->mxNode->getNodeGraphicURL(), aImage ) )
+ {
+ pUnoItem->SetGraphicURL( pEntry->mxNode->getNodeGraphicURL() );
+ pUnoItem->SetImage( aImage );
+ mpTreeImpl->AdjustEntryHeight( aImage );
+ bChanged = true;
+ }
+ }
+ }
+
+ if( bool(pEntry->mxNode->hasChildrenOnDemand()) != pEntry->HasChildrenOnDemand() )
+ {
+ pEntry->EnableChildrenOnDemand( pEntry->mxNode->hasChildrenOnDemand() );
+ bChanged = true;
+ }
+
+ ImplContextGraphicItem* pContextGraphicItem = dynamic_cast< ImplContextGraphicItem* >( &pEntry->GetItem( 0 ) );
+ if( pContextGraphicItem )
+ {
+ if( pContextGraphicItem->msExpandedGraphicURL != pEntry->mxNode->getExpandedGraphicURL() )
+ {
+ Image aImage;
+ if( loadImage( pEntry->mxNode->getExpandedGraphicURL(), aImage ) )
+ {
+ pContextGraphicItem->msExpandedGraphicURL = pEntry->mxNode->getExpandedGraphicURL();
+ mpTreeImpl->SetExpandedEntryBmp( pEntry, aImage );
+ bChanged = true;
+ }
+ }
+ if( pContextGraphicItem->msCollapsedGraphicURL != pEntry->mxNode->getCollapsedGraphicURL() )
+ {
+ Image aImage;
+ if( loadImage( pEntry->mxNode->getCollapsedGraphicURL(), aImage ) )
+ {
+ pContextGraphicItem->msCollapsedGraphicURL = pEntry->mxNode->getCollapsedGraphicURL();
+ mpTreeImpl->SetCollapsedEntryBmp( pEntry, aImage );
+ bChanged = true;
+ }
+ }
+ }
+
+ if( bChanged )
+ mpTreeImpl->GetModel()->InvalidateEntry( pEntry );
+}
+
+
+void TreeControlPeer::onSelectionChanged()
+{
+ Reference< XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
+ EventObject aEvent( xSource );
+ maSelectionListeners.selectionChanged( aEvent );
+}
+
+
+void TreeControlPeer::onRequestChildNodes( const Reference< XTreeNode >& xNode )
+{
+ try
+ {
+ Reference< XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
+ TreeExpansionEvent aEvent( xSource, xNode );
+ maTreeExpansionListeners.requestChildNodes( aEvent );
+ }
+ catch( Exception& )
+ {
+ }
+}
+
+
+bool TreeControlPeer::onExpanding( const Reference< XTreeNode >& xNode, bool bExpanding )
+{
+ try
+ {
+ Reference< XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
+ TreeExpansionEvent aEvent( xSource, xNode );
+ if( bExpanding )
+ {
+ maTreeExpansionListeners.treeExpanding( aEvent );
+ }
+ else
+ {
+ maTreeExpansionListeners.treeCollapsing( aEvent );
+ }
+ }
+ catch( Exception& )
+ {
+ return false;
+ }
+ return true;
+}
+
+
+void TreeControlPeer::onExpanded( const Reference< XTreeNode >& xNode, bool bExpanding )
+{
+ try
+ {
+ Reference< XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
+ TreeExpansionEvent aEvent( xSource, xNode );
+
+ if( bExpanding )
+ {
+ maTreeExpansionListeners.treeExpanded( aEvent );
+ }
+ else
+ {
+ maTreeExpansionListeners.treeCollapsed( aEvent );
+ }
+ }
+ catch( Exception& )
+ {
+ }
+}
+
+
+void TreeControlPeer::fillTree( UnoTreeListBoxImpl& rTree, const Reference< XTreeDataModel >& xDataModel )
+{
+ rTree.Clear();
+
+ if( !xDataModel.is() )
+ return;
+
+ Reference< XTreeNode > xRootNode( xDataModel->getRoot() );
+ if( !xRootNode.is() )
+ return;
+
+ if( mbIsRootDisplayed )
+ {
+ addNode( rTree, xRootNode, nullptr );
+ }
+ else
+ {
+ const sal_Int32 nChildCount = xRootNode->getChildCount();
+ for( sal_Int32 nChild = 0; nChild < nChildCount; nChild++ )
+ addNode( rTree, xRootNode->getChildAt( nChild ), nullptr );
+ }
+}
+
+
+void TreeControlPeer::addNode( UnoTreeListBoxImpl& rTree, const Reference< XTreeNode >& xNode, UnoTreeListEntry* pParentEntry )
+{
+ if( xNode.is() )
+ {
+ UnoTreeListEntry* pEntry = createEntry( xNode, pParentEntry, TREELIST_APPEND );
+ const sal_Int32 nChildCount = xNode->getChildCount();
+ for( sal_Int32 nChild = 0; nChild < nChildCount; nChild++ )
+ addNode( rTree, xNode->getChildAt( nChild ), pEntry );
+ }
+}
+
+
+UnoTreeListBoxImpl& TreeControlPeer::getTreeListBoxOrThrow() const
+{
+ if( !mpTreeImpl )
+ throw DisposedException();
+ return *mpTreeImpl;
+}
+
+
+void TreeControlPeer::ChangeNodesSelection( const Any& rSelection, bool bSelect, bool bSetSelection )
+{
+ SolarMutexGuard aGuard;
+
+ UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
+
+ Reference< XTreeNode > xTempNode;
+
+ Sequence<Reference<XTreeNode>> pNodes;
+ sal_Int32 nCount = 0;
+
+ if( rSelection.hasValue() )
+ {
+ switch( rSelection.getValueTypeClass() )
+ {
+ case TypeClass_INTERFACE:
+ {
+ rSelection >>= xTempNode;
+ if( xTempNode.is() )
+ {
+ nCount = 1;
+ pNodes = {xTempNode};
+ }
+ break;
+ }
+ case TypeClass_SEQUENCE:
+ {
+ if( auto rSeq = o3tl::tryAccess<Sequence<Reference<XTreeNode>>>(
+ rSelection) )
+ {
+ nCount = rSeq->getLength();
+ pNodes = *rSeq;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ if( nCount == 0 )
+ throw IllegalArgumentException();
+ }
+
+ if( bSetSelection )
+ rTree.SelectAll( false );
+
+ for( sal_Int32 i = 0; i != nCount; ++i )
+ {
+ UnoTreeListEntry* pEntry = getEntry( pNodes[i] );
+ rTree.Select( pEntry, bSelect );
+ }
+}
+
+
+// css::view::XSelectionSupplier
+
+
+sal_Bool SAL_CALL TreeControlPeer::select( const Any& rSelection )
+{
+ SolarMutexGuard aGuard;
+ ChangeNodesSelection( rSelection, true, true );
+ return true;
+}
+
+
+Any SAL_CALL TreeControlPeer::getSelection()
+{
+ SolarMutexGuard aGuard;
+
+ UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
+
+ Any aRet;
+
+ sal_uLong nSelectionCount = rTree.GetSelectionCount();
+ if( nSelectionCount == 1 )
+ {
+ UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.FirstSelected() );
+ if( pEntry && pEntry->mxNode.is() )
+ aRet <<= pEntry->mxNode;
+ }
+ else if( nSelectionCount > 1 )
+ {
+ Sequence< Reference< XTreeNode > > aSelection( nSelectionCount );
+ Reference< XTreeNode >* pNodes = aSelection.getArray();
+ UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.FirstSelected() );
+ while( pEntry && nSelectionCount )
+ {
+ *pNodes++ = pEntry->mxNode;
+ pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.NextSelected( pEntry ) );
+ --nSelectionCount;
+ }
+
+ OSL_ASSERT( (pEntry == nullptr) && (nSelectionCount == 0) );
+ aRet <<= aSelection;
+ }
+
+ return aRet;
+}
+
+
+void SAL_CALL TreeControlPeer::addSelectionChangeListener( const Reference< XSelectionChangeListener >& xListener )
+{
+ maSelectionListeners.addInterface( xListener );
+}
+
+
+void SAL_CALL TreeControlPeer::removeSelectionChangeListener( const Reference< XSelectionChangeListener >& xListener )
+{
+ maSelectionListeners.addInterface( xListener );
+}
+
+
+// css::view::XMultiSelectionSupplier
+
+
+sal_Bool SAL_CALL TreeControlPeer::addSelection( const Any& rSelection )
+{
+ ChangeNodesSelection( rSelection, true, false );
+ return true;
+}
+
+
+void SAL_CALL TreeControlPeer::removeSelection( const Any& rSelection )
+{
+ ChangeNodesSelection( rSelection, false, false );
+}
+
+
+void SAL_CALL TreeControlPeer::clearSelection()
+{
+ SolarMutexGuard aGuard;
+ getTreeListBoxOrThrow().SelectAll( false );
+}
+
+
+sal_Int32 SAL_CALL TreeControlPeer::getSelectionCount()
+{
+ SolarMutexGuard aGuard;
+ return getTreeListBoxOrThrow().GetSelectionCount();
+}
+
+namespace {
+
+class TreeSelectionEnumeration : public ::cppu::WeakImplHelper< XEnumeration >
+{
+public:
+ explicit TreeSelectionEnumeration( std::list< Any >& rSelection );
+ virtual sal_Bool SAL_CALL hasMoreElements() override;
+ virtual Any SAL_CALL nextElement() override;
+
+ std::list< Any > maSelection;
+ std::list< Any >::iterator maIter;
+};
+
+}
+
+TreeSelectionEnumeration::TreeSelectionEnumeration( std::list< Any >& rSelection )
+{
+ maSelection.swap( rSelection );
+ maIter = maSelection.begin();
+}
+
+
+sal_Bool SAL_CALL TreeSelectionEnumeration::hasMoreElements()
+{
+ return maIter != maSelection.end();
+}
+
+
+Any SAL_CALL TreeSelectionEnumeration::nextElement()
+{
+ if( maIter == maSelection.end() )
+ throw NoSuchElementException();
+
+ return (*maIter++);
+}
+
+
+Reference< XEnumeration > SAL_CALL TreeControlPeer::createSelectionEnumeration()
+{
+ SolarMutexGuard aGuard;
+
+ UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
+
+ sal_uInt32 nSelectionCount = rTree.GetSelectionCount();
+ std::list< Any > aSelection( nSelectionCount );
+
+ UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.FirstSelected() );
+ while( pEntry && nSelectionCount )
+ {
+ aSelection.emplace_back( pEntry->mxNode );
+ pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.NextSelected( pEntry ) );
+ --nSelectionCount;
+ }
+
+ OSL_ASSERT( (pEntry == nullptr) && (nSelectionCount == 0) );
+
+ return Reference< XEnumeration >( new TreeSelectionEnumeration( aSelection ) );
+}
+
+
+Reference< XEnumeration > SAL_CALL TreeControlPeer::createReverseSelectionEnumeration()
+{
+ SolarMutexGuard aGuard;
+
+ UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
+
+ sal_uInt32 nSelectionCount = rTree.GetSelectionCount();
+ std::list< Any > aSelection;
+
+ UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.FirstSelected() );
+ while( pEntry && nSelectionCount )
+ {
+ aSelection.push_front( Any( pEntry->mxNode ) );
+ pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.NextSelected( pEntry ) );
+ --nSelectionCount;
+ }
+
+ OSL_ASSERT( (pEntry == nullptr) && (nSelectionCount == 0) );
+
+ return Reference< XEnumeration >( new TreeSelectionEnumeration( aSelection ) );
+}
+
+
+// css::awt::XTreeControl
+
+
+OUString SAL_CALL TreeControlPeer::getDefaultExpandedGraphicURL()
+{
+ SolarMutexGuard aGuard;
+ return msDefaultExpandedGraphicURL;
+}
+
+
+void SAL_CALL TreeControlPeer::setDefaultExpandedGraphicURL( const OUString& sDefaultExpandedGraphicURL )
+{
+ SolarMutexGuard aGuard;
+ if( msDefaultExpandedGraphicURL == sDefaultExpandedGraphicURL )
+ return;
+
+ if( !sDefaultExpandedGraphicURL.isEmpty() )
+ loadImage( sDefaultExpandedGraphicURL, maDefaultExpandedImage );
+ else
+ maDefaultExpandedImage = Image();
+
+ UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
+
+ SvTreeListEntry* pEntry = rTree.First();
+ while( pEntry )
+ {
+ ImplContextGraphicItem* pContextGraphicItem = dynamic_cast< ImplContextGraphicItem* >( &pEntry->GetItem( 0 ) );
+ if( pContextGraphicItem )
+ {
+ if( pContextGraphicItem->msExpandedGraphicURL.isEmpty() )
+ rTree.SetExpandedEntryBmp( pEntry, maDefaultExpandedImage );
+ }
+ pEntry = rTree.Next( pEntry );
+ }
+
+ msDefaultExpandedGraphicURL = sDefaultExpandedGraphicURL;
+}
+
+
+OUString SAL_CALL TreeControlPeer::getDefaultCollapsedGraphicURL()
+{
+ SolarMutexGuard aGuard;
+ return msDefaultCollapsedGraphicURL;
+}
+
+
+void SAL_CALL TreeControlPeer::setDefaultCollapsedGraphicURL( const OUString& sDefaultCollapsedGraphicURL )
+{
+ SolarMutexGuard aGuard;
+ if( msDefaultCollapsedGraphicURL == sDefaultCollapsedGraphicURL )
+ return;
+
+ if( !sDefaultCollapsedGraphicURL.isEmpty() )
+ loadImage( sDefaultCollapsedGraphicURL, maDefaultCollapsedImage );
+ else
+ maDefaultCollapsedImage = Image();
+
+ UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
+
+ SvTreeListEntry* pEntry = rTree.First();
+ while( pEntry )
+ {
+ ImplContextGraphicItem* pContextGraphicItem = dynamic_cast< ImplContextGraphicItem* >( &pEntry->GetItem( 0 ) );
+ if( pContextGraphicItem )
+ {
+ if( pContextGraphicItem->msCollapsedGraphicURL.isEmpty() )
+ rTree.SetCollapsedEntryBmp( pEntry, maDefaultCollapsedImage );
+ }
+ pEntry = rTree.Next( pEntry );
+ }
+
+ msDefaultCollapsedGraphicURL = sDefaultCollapsedGraphicURL;
+}
+
+
+sal_Bool SAL_CALL TreeControlPeer::isNodeExpanded( const Reference< XTreeNode >& xNode )
+{
+ SolarMutexGuard aGuard;
+
+ UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
+ UnoTreeListEntry* pEntry = getEntry( xNode );
+ return pEntry && rTree.IsExpanded( pEntry );
+}
+
+
+sal_Bool SAL_CALL TreeControlPeer::isNodeCollapsed( const Reference< XTreeNode >& xNode )
+{
+ SolarMutexGuard aGuard;
+ return !isNodeExpanded( xNode );
+}
+
+
+void SAL_CALL TreeControlPeer::makeNodeVisible( const Reference< XTreeNode >& xNode )
+{
+ SolarMutexGuard aGuard;
+
+ UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
+ UnoTreeListEntry* pEntry = getEntry( xNode );
+ if( pEntry )
+ rTree.MakeVisible( pEntry );
+}
+
+
+sal_Bool SAL_CALL TreeControlPeer::isNodeVisible( const Reference< XTreeNode >& xNode )
+{
+ SolarMutexGuard aGuard;
+
+ UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
+ UnoTreeListEntry* pEntry = getEntry( xNode );
+ return pEntry && rTree.IsEntryVisible( pEntry );
+}
+
+
+void SAL_CALL TreeControlPeer::expandNode( const Reference< XTreeNode >& xNode )
+{
+ SolarMutexGuard aGuard;
+
+ UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
+ UnoTreeListEntry* pEntry = getEntry( xNode );
+ if( pEntry )
+ rTree.Expand( pEntry );
+}
+
+
+void SAL_CALL TreeControlPeer::collapseNode( const Reference< XTreeNode >& xNode )
+{
+ SolarMutexGuard aGuard;
+
+ UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
+ UnoTreeListEntry* pEntry = getEntry( xNode );
+ if( pEntry )
+ rTree.Collapse( pEntry );
+}
+
+
+void SAL_CALL TreeControlPeer::addTreeExpansionListener( const Reference< XTreeExpansionListener >& xListener )
+{
+ maTreeExpansionListeners.addInterface( xListener );
+}
+
+
+void SAL_CALL TreeControlPeer::removeTreeExpansionListener( const Reference< XTreeExpansionListener >& xListener )
+{
+ maTreeExpansionListeners.removeInterface( xListener );
+}
+
+
+Reference< XTreeNode > SAL_CALL TreeControlPeer::getNodeForLocation( sal_Int32 x, sal_Int32 y )
+{
+ SolarMutexGuard aGuard;
+
+ UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
+
+ Reference< XTreeNode > xNode;
+
+ const Point aPos( x, y );
+ UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.GetEntry( aPos, true ) );
+ if( pEntry )
+ xNode = pEntry->mxNode;
+
+ return xNode;
+}
+
+
+Reference< XTreeNode > SAL_CALL TreeControlPeer::getClosestNodeForLocation( sal_Int32 x, sal_Int32 y )
+{
+ SolarMutexGuard aGuard;
+
+ UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
+
+ Reference< XTreeNode > xNode;
+
+ const Point aPos( x, y );
+ UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.GetEntry( aPos, true ) );
+ if( pEntry )
+ xNode = pEntry->mxNode;
+
+ return xNode;
+}
+
+
+awt::Rectangle SAL_CALL TreeControlPeer::getNodeRect( const Reference< XTreeNode >& i_Node )
+{
+ SolarMutexGuard aGuard;
+
+ UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
+ UnoTreeListEntry* pEntry = getEntry( i_Node );
+
+ ::tools::Rectangle aEntryRect( rTree.GetFocusRect( pEntry, rTree.GetEntryPosition( pEntry ).Y() ) );
+ return VCLUnoHelper::ConvertToAWTRect( aEntryRect );
+}
+
+
+sal_Bool SAL_CALL TreeControlPeer::isEditing( )
+{
+ SolarMutexGuard aGuard;
+
+ UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
+ return rTree.IsEditingActive();
+}
+
+
+sal_Bool SAL_CALL TreeControlPeer::stopEditing()
+{
+ SolarMutexGuard aGuard;
+
+ UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
+ if( rTree.IsEditingActive() )
+ {
+ rTree.EndEditing();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+void SAL_CALL TreeControlPeer::cancelEditing( )
+{
+ SolarMutexGuard aGuard;
+
+ UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
+ rTree.EndEditing();
+}
+
+
+void SAL_CALL TreeControlPeer::startEditingAtNode( const Reference< XTreeNode >& xNode )
+{
+ SolarMutexGuard aGuard;
+
+ UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
+ UnoTreeListEntry* pEntry = getEntry( xNode );
+ rTree.EditEntry( pEntry );
+}
+
+void SAL_CALL TreeControlPeer::addTreeEditListener( const Reference< XTreeEditListener >& xListener )
+{
+ maTreeEditListeners.addInterface( xListener );
+}
+
+void SAL_CALL TreeControlPeer::removeTreeEditListener( const Reference< XTreeEditListener >& xListener )
+{
+ maTreeEditListeners.removeInterface( xListener );
+}
+
+bool TreeControlPeer::onEditingEntry( UnoTreeListEntry const * pEntry )
+{
+ if( mpTreeImpl && pEntry && pEntry->mxNode.is() && (maTreeEditListeners.getLength() > 0) )
+ {
+ try
+ {
+ maTreeEditListeners.nodeEditing( pEntry->mxNode );
+ }
+ catch( VetoException& )
+ {
+ return false;
+ }
+ catch( Exception& )
+ {
+ }
+ }
+ return true;
+}
+
+bool TreeControlPeer::onEditedEntry( UnoTreeListEntry const * pEntry, const OUString& rNewText )
+{
+ if( mpTreeImpl && pEntry && pEntry->mxNode.is() ) try
+ {
+ LockGuard aLockGuard( mnEditLock );
+ if( maTreeEditListeners.getLength() > 0 )
+ {
+ maTreeEditListeners.nodeEdited( pEntry->mxNode, rNewText );
+ return false;
+ }
+ else
+ {
+ Reference< XMutableTreeNode > xMutableNode( pEntry->mxNode, UNO_QUERY );
+ if( xMutableNode.is() )
+ xMutableNode->setDisplayValue( Any( rNewText ) );
+ else
+ return false;
+ }
+
+ }
+ catch( Exception& )
+ {
+ }
+
+ return true;
+}
+
+
+// css::awt::tree::TreeDataModelListener
+
+
+void SAL_CALL TreeControlPeer::treeNodesChanged( const css::awt::tree::TreeDataModelEvent& rEvent )
+{
+ SolarMutexGuard aGuard;
+
+ if( mnEditLock != 0 )
+ return;
+
+ updateTree( rEvent );
+}
+
+void SAL_CALL TreeControlPeer::treeNodesInserted( const css::awt::tree::TreeDataModelEvent& rEvent )
+{
+ SolarMutexGuard aGuard;
+
+ if( mnEditLock != 0 )
+ return;
+
+ updateTree( rEvent );
+}
+
+void SAL_CALL TreeControlPeer::treeNodesRemoved( const css::awt::tree::TreeDataModelEvent& rEvent )
+{
+ SolarMutexGuard aGuard;
+
+ if( mnEditLock != 0 )
+ return;
+
+ updateTree( rEvent );
+}
+
+void SAL_CALL TreeControlPeer::treeStructureChanged( const css::awt::tree::TreeDataModelEvent& rEvent )
+{
+ SolarMutexGuard aGuard;
+
+ if( mnEditLock != 0 )
+ return;
+
+ updateTree( rEvent );
+}
+
+void TreeControlPeer::updateTree( const css::awt::tree::TreeDataModelEvent& rEvent )
+{
+ UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
+
+ Sequence< Reference< XTreeNode > > Nodes;
+ Reference< XTreeNode > xNode( rEvent.ParentNode );
+ if( !xNode.is() && Nodes.hasElements() )
+ {
+ xNode = Nodes[0];
+ }
+
+ if( xNode.is() )
+ updateNode( rTree, xNode );
+}
+
+void TreeControlPeer::updateNode( UnoTreeListBoxImpl const & rTree, const Reference< XTreeNode >& xNode )
+{
+ if( !xNode.is() )
+ return;
+
+ UnoTreeListEntry* pNodeEntry = getEntry( xNode, false );
+
+ if( !pNodeEntry )
+ {
+ Reference< XTreeNode > xParentNode( xNode->getParent() );
+ UnoTreeListEntry* pParentEntry = nullptr;
+ sal_uLong nChild = TREELIST_APPEND;
+
+ if( xParentNode.is() )
+ {
+ pParentEntry = getEntry( xParentNode );
+ nChild = xParentNode->getIndex( xNode );
+ }
+
+ pNodeEntry = createEntry( xNode, pParentEntry, nChild );
+ }
+
+ updateChildNodes( rTree, xNode, pNodeEntry );
+}
+
+void TreeControlPeer::updateChildNodes( UnoTreeListBoxImpl const & rTree, const Reference< XTreeNode >& xParentNode, UnoTreeListEntry* pParentEntry )
+{
+ if( !(xParentNode.is() && pParentEntry) )
+ return;
+
+ UnoTreeListEntry* pCurrentChild = dynamic_cast< UnoTreeListEntry* >( rTree.FirstChild( pParentEntry ) );
+
+ const sal_Int32 nChildCount = xParentNode->getChildCount();
+ for( sal_Int32 nChild = 0; nChild < nChildCount; nChild++ )
+ {
+ Reference< XTreeNode > xNode( xParentNode->getChildAt( nChild ) );
+ if( !pCurrentChild || ( pCurrentChild->mxNode != xNode ) )
+ {
+ UnoTreeListEntry* pNodeEntry = getEntry( xNode, false );
+ if( pNodeEntry == nullptr )
+ {
+ // child node is not yet part of the tree, add it
+ pCurrentChild = createEntry( xNode, pParentEntry, nChild );
+ }
+ else if( pNodeEntry != pCurrentChild )
+ {
+ // node is already part of the tree, but not on the correct position
+ rTree.GetModel()->Move( pNodeEntry, pParentEntry, nChild );
+ pCurrentChild = pNodeEntry;
+ updateEntry( pCurrentChild );
+ }
+ }
+ else
+ {
+ // child node has entry and entry is equal to current entry,
+ // so no structural changes happened
+ updateEntry( pCurrentChild );
+ }
+
+ pCurrentChild = dynamic_cast< UnoTreeListEntry* >( pCurrentChild->NextSibling() );
+ }
+
+ // check if we have entries without nodes left, we need to remove them
+ while( pCurrentChild )
+ {
+ UnoTreeListEntry* pNextChild = dynamic_cast< UnoTreeListEntry* >( pCurrentChild->NextSibling() );
+ rTree.GetModel()->Remove( pCurrentChild );
+ pCurrentChild = pNextChild;
+ }
+}
+
+OUString TreeControlPeer::getEntryString( const Any& rValue )
+{
+ OUString sValue;
+ if( rValue.hasValue() )
+ {
+ switch( rValue.getValueTypeClass() )
+ {
+ case TypeClass_SHORT:
+ case TypeClass_LONG:
+ {
+ sal_Int32 nValue = 0;
+ if( rValue >>= nValue )
+ sValue = OUString::number( nValue );
+ break;
+ }
+ case TypeClass_BYTE:
+ case TypeClass_UNSIGNED_SHORT:
+ case TypeClass_UNSIGNED_LONG:
+ {
+ sal_uInt32 nValue = 0;
+ if( rValue >>= nValue )
+ sValue = OUString::number( nValue );
+ break;
+ }
+ case TypeClass_HYPER:
+ {
+ sal_Int64 nValue = 0;
+ if( rValue >>= nValue )
+ sValue = OUString::number( nValue );
+ break;
+ }
+ case TypeClass_UNSIGNED_HYPER:
+ {
+ sal_uInt64 nValue = 0;
+ if( rValue >>= nValue )
+ sValue = OUString::number( nValue );
+ break;
+ }
+ case TypeClass_FLOAT:
+ case TypeClass_DOUBLE:
+ {
+ double fValue = 0.0;
+ if( rValue >>= fValue )
+ sValue = OUString::number( fValue );
+ break;
+ }
+ case TypeClass_STRING:
+ rValue >>= sValue;
+ break;
+ /*
+ case TypeClass_INTERFACE:
+ // @todo
+ break;
+ case TypeClass_SEQUENCE:
+ {
+ Sequence< Any > aValues;
+ if( aValue >>= aValues )
+ {
+ updateEntry( SvTreeListEntry& rEntry, aValues );
+ return;
+ }
+ }
+ break;
+ */
+ default:
+ break;
+ }
+ }
+ return sValue;
+}
+
+// XEventListener
+void SAL_CALL TreeControlPeer::disposing( const css::lang::EventObject& )
+{
+ // model is disposed, so we clear our tree
+ SolarMutexGuard aGuard;
+ UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
+ rTree.Clear();
+ mxDataModel.clear();
+}
+
+void TreeControlPeer::onChangeDataModel( UnoTreeListBoxImpl& rTree, const Reference< XTreeDataModel >& xDataModel )
+{
+ if( xDataModel.is() && (mxDataModel == xDataModel) )
+ return; // do nothing
+
+ Reference< XTreeDataModelListener > xListener( this );
+
+ if( mxDataModel.is() )
+ mxDataModel->removeTreeDataModelListener( xListener );
+
+ mxDataModel = xDataModel;
+
+ fillTree( rTree, mxDataModel );
+
+ if( mxDataModel.is() )
+ mxDataModel->addTreeDataModelListener( xListener );
+}
+
+
+// css::awt::XLayoutConstrains
+
+
+css::awt::Size TreeControlPeer::getMinimumSize()
+{
+ SolarMutexGuard aGuard;
+
+ css::awt::Size aSz;
+/* todo
+ MultiLineEdit* pEdit = (MultiLineEdit*) GetWindow();
+ if ( pEdit )
+ aSz = AWTSize(pEdit->CalcMinimumSize());
+*/
+ return aSz;
+}
+
+css::awt::Size TreeControlPeer::getPreferredSize()
+{
+ return getMinimumSize();
+}
+
+css::awt::Size TreeControlPeer::calcAdjustedSize( const css::awt::Size& rNewSize )
+{
+ SolarMutexGuard aGuard;
+
+ css::awt::Size aSz = rNewSize;
+/* todo
+ MultiLineEdit* pEdit = (MultiLineEdit*) GetWindow();
+ if ( pEdit )
+ aSz = AWTSize(pEdit->CalcAdjustedSize( VCLSize(rNewSize )));
+*/
+ return aSz;
+}
+
+
+// css::awt::XVclWindowPeer
+
+
+void TreeControlPeer::setProperty( const OUString& PropertyName, const Any& aValue)
+{
+ SolarMutexGuard aGuard;
+
+ UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
+
+ switch( GetPropertyId( PropertyName ) )
+ {
+ case BASEPROPERTY_HIDEINACTIVESELECTION:
+ {
+ bool bEnabled = false;
+ if ( aValue >>= bEnabled )
+ {
+ WinBits nStyle = rTree.GetStyle();
+ if ( bEnabled )
+ nStyle |= WB_HIDESELECTION;
+ else
+ nStyle &= ~WB_HIDESELECTION;
+ rTree.SetStyle( nStyle );
+ }
+ }
+ break;
+
+ case BASEPROPERTY_TREE_SELECTIONTYPE:
+ {
+ SelectionType eSelectionType;
+ if( aValue >>= eSelectionType )
+ {
+ SelectionMode eSelMode;
+ switch( eSelectionType )
+ {
+ case SelectionType_SINGLE: eSelMode = SelectionMode::Single; break;
+ case SelectionType_RANGE: eSelMode = SelectionMode::Range; break;
+ case SelectionType_MULTI: eSelMode = SelectionMode::Multiple; break;
+ // case SelectionType_NONE:
+ default: eSelMode = SelectionMode::NONE; break;
+ }
+ if( rTree.GetSelectionMode() != eSelMode )
+ rTree.SetSelectionMode( eSelMode );
+ }
+ break;
+ }
+
+ case BASEPROPERTY_TREE_DATAMODEL:
+ onChangeDataModel( rTree, Reference< XTreeDataModel >( aValue, UNO_QUERY ) );
+ break;
+ case BASEPROPERTY_ROW_HEIGHT:
+ {
+ sal_Int32 nHeight = 0;
+ if( aValue >>= nHeight )
+ rTree.SetEntryHeight( static_cast<short>(nHeight) );
+ break;
+ }
+ case BASEPROPERTY_TREE_EDITABLE:
+ {
+ bool bEnabled = false;
+ if( aValue >>= bEnabled )
+ rTree.EnableInplaceEditing( bEnabled );
+ break;
+ }
+ case BASEPROPERTY_TREE_INVOKESSTOPNODEEDITING:
+ break; // @todo
+ case BASEPROPERTY_TREE_ROOTDISPLAYED:
+ {
+ bool bDisplayed = false;
+ if( (aValue >>= bDisplayed) && ( bDisplayed != mbIsRootDisplayed) )
+ {
+ onChangeRootDisplayed(bDisplayed);
+ }
+ break;
+ }
+ case BASEPROPERTY_TREE_SHOWSHANDLES:
+ {
+ bool bEnabled = false;
+ if( aValue >>= bEnabled )
+ {
+ WinBits nBits = rTree.GetStyle() & (~WB_HASLINES);
+ if( bEnabled )
+ nBits |= WB_HASLINES;
+ if( nBits != rTree.GetStyle() )
+ rTree.SetStyle( nBits );
+ }
+ break;
+ }
+ case BASEPROPERTY_TREE_SHOWSROOTHANDLES:
+ {
+ bool bEnabled = false;
+ if( aValue >>= bEnabled )
+ {
+ WinBits nBits = rTree.GetStyle() & (~WB_HASLINESATROOT);
+ if( bEnabled )
+ nBits |= WB_HASLINESATROOT;
+ if( nBits != rTree.GetStyle() )
+ rTree.SetStyle( nBits );
+ }
+ break;
+ }
+ default:
+ VCLXWindow::setProperty( PropertyName, aValue );
+ break;
+ }
+}
+
+Any TreeControlPeer::getProperty( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ const sal_uInt16 nPropId = GetPropertyId( PropertyName );
+ if( (nPropId >= BASEPROPERTY_TREE_START) && (nPropId <= BASEPROPERTY_TREE_END) )
+ {
+ UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
+ switch(nPropId)
+ {
+ case BASEPROPERTY_TREE_SELECTIONTYPE:
+ {
+ SelectionType eSelectionType;
+
+ SelectionMode eSelMode = rTree.GetSelectionMode();
+ switch( eSelMode )
+ {
+ case SelectionMode::Single: eSelectionType = SelectionType_SINGLE; break;
+ case SelectionMode::Range: eSelectionType = SelectionType_RANGE; break;
+ case SelectionMode::Multiple:eSelectionType = SelectionType_MULTI; break;
+// case SelectionMode::NONE:
+ default: eSelectionType = SelectionType_NONE; break;
+ }
+ return Any( eSelectionType );
+ }
+ case BASEPROPERTY_ROW_HEIGHT:
+ return Any( static_cast<sal_Int32>(rTree.GetEntryHeight()) );
+ case BASEPROPERTY_TREE_DATAMODEL:
+ return Any( mxDataModel );
+ case BASEPROPERTY_TREE_EDITABLE:
+ return Any( rTree.IsInplaceEditingEnabled() );
+ case BASEPROPERTY_TREE_INVOKESSTOPNODEEDITING:
+ return Any( true ); // @todo
+ case BASEPROPERTY_TREE_ROOTDISPLAYED:
+ return Any( mbIsRootDisplayed );
+ case BASEPROPERTY_TREE_SHOWSHANDLES:
+ return Any( (rTree.GetStyle() & WB_HASLINES) != 0 );
+ case BASEPROPERTY_TREE_SHOWSROOTHANDLES:
+ return Any( (rTree.GetStyle() & WB_HASLINESATROOT) != 0 );
+ }
+ }
+ return VCLXWindow::getProperty( PropertyName );
+}
+
+void TreeControlPeer::onChangeRootDisplayed( bool bIsRootDisplayed )
+{
+ if( mbIsRootDisplayed == bIsRootDisplayed )
+ return;
+
+ mbIsRootDisplayed = bIsRootDisplayed;
+
+ UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
+
+ if( rTree.GetEntryCount() == 0 )
+ return;
+
+ // todo
+ fillTree( rTree, mxDataModel );
+}
+
+bool TreeControlPeer::loadImage( const OUString& rURL, Image& rImage )
+{
+ if( !mxGraphicProvider.is() )
+ {
+ mxGraphicProvider = graphic::GraphicProvider::create(
+ comphelper::getProcessComponentContext());
+ }
+
+ try
+ {
+ css::beans::PropertyValues aProps{ comphelper::makePropertyValue("URL", rURL) };
+ Reference< XGraphic > xGraphic( mxGraphicProvider->queryGraphic( aProps ) );
+
+ Graphic aGraphic( xGraphic );
+ rImage = Image(aGraphic.GetBitmapEx());
+ return true;
+ }
+ catch( Exception& )
+ {
+ }
+
+ return false;
+}
+
+
+
+
+UnoTreeListBoxImpl::UnoTreeListBoxImpl( TreeControlPeer* pPeer, vcl::Window* pParent, WinBits nWinStyle )
+: SvTreeListBox( pParent, nWinStyle )
+, mxPeer( pPeer )
+{
+ SetStyle( WB_BORDER | WB_HASLINES |WB_HASBUTTONS | WB_HASLINESATROOT | WB_HASBUTTONSATROOT | WB_HSCROLL );
+ SetNodeDefaultImages();
+ SetSelectHdl( LINK(this, UnoTreeListBoxImpl, OnSelectionChangeHdl) );
+ SetDeselectHdl( LINK(this, UnoTreeListBoxImpl, OnSelectionChangeHdl) );
+
+ SetExpandingHdl( LINK(this, UnoTreeListBoxImpl, OnExpandingHdl) );
+ SetExpandedHdl( LINK(this, UnoTreeListBoxImpl, OnExpandedHdl) );
+
+}
+
+
+UnoTreeListBoxImpl::~UnoTreeListBoxImpl()
+{
+ disposeOnce();
+}
+
+void UnoTreeListBoxImpl::dispose()
+{
+ if( mxPeer.is() )
+ mxPeer->disposeControl();
+ mxPeer.clear();
+ SvTreeListBox::dispose();
+}
+
+
+IMPL_LINK_NOARG(UnoTreeListBoxImpl, OnSelectionChangeHdl, SvTreeListBox*, void)
+{
+ if( mxPeer.is() )
+ mxPeer->onSelectionChanged();
+}
+
+
+IMPL_LINK_NOARG(UnoTreeListBoxImpl, OnExpandingHdl, SvTreeListBox*, bool)
+{
+ UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( GetHdlEntry() );
+
+ if( pEntry && mxPeer.is() )
+ {
+ return mxPeer->onExpanding( pEntry->mxNode, !IsExpanded( pEntry ) );
+ }
+ return false;
+}
+
+
+IMPL_LINK_NOARG(UnoTreeListBoxImpl, OnExpandedHdl, SvTreeListBox*, void)
+{
+ UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( GetHdlEntry() );
+ if( pEntry && mxPeer.is() )
+ {
+ mxPeer->onExpanded( pEntry->mxNode, IsExpanded( pEntry ) );
+ }
+}
+
+
+void UnoTreeListBoxImpl::insert( SvTreeListEntry* pEntry,SvTreeListEntry* pParent,sal_uLong nPos )
+{
+ if( pParent )
+ SvTreeListBox::Insert( pEntry, pParent, nPos );
+ else
+ SvTreeListBox::Insert( pEntry, nPos );
+}
+
+
+void UnoTreeListBoxImpl::RequestingChildren( SvTreeListEntry* pParent )
+{
+ UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( pParent );
+ if( pEntry && pEntry->mxNode.is() && mxPeer.is() )
+ mxPeer->onRequestChildNodes( pEntry->mxNode );
+}
+
+
+bool UnoTreeListBoxImpl::EditingEntry( SvTreeListEntry* pEntry )
+{
+ return mxPeer.is() && mxPeer->onEditingEntry( dynamic_cast< UnoTreeListEntry* >( pEntry ) );
+}
+
+
+bool UnoTreeListBoxImpl::EditedEntry( SvTreeListEntry* pEntry, const OUString& rNewText )
+{
+ return mxPeer.is() && mxPeer->onEditedEntry( dynamic_cast< UnoTreeListEntry* >( pEntry ), rNewText );
+}
+
+
+
+
+UnoTreeListItem::UnoTreeListItem()
+: SvLBoxString(OUString())
+{
+}
+
+void UnoTreeListItem::Paint(
+ const Point& rPos, SvTreeListBox& rDev, vcl::RenderContext& rRenderContext, const SvViewDataEntry* /*pView*/, const SvTreeListEntry& rEntry)
+{
+ Point aPos(rPos);
+ Size aSize(GetWidth(&rDev, &rEntry), GetHeight(&rDev, &rEntry));
+ if (!!maImage)
+ {
+ rRenderContext.DrawImage(aPos, maImage, rDev.IsEnabled() ? DrawImageFlags::NONE : DrawImageFlags::Disable);
+ int nWidth = maImage.GetSizePixel().Width() + 6;
+ aPos.AdjustX(nWidth );
+ aSize.AdjustWidth( -nWidth );
+ }
+ rRenderContext.DrawText(tools::Rectangle(aPos,aSize),maText, rDev.IsEnabled() ? DrawTextFlags::NONE : DrawTextFlags::Disable);
+}
+
+
+std::unique_ptr<SvLBoxItem> UnoTreeListItem::Clone(SvLBoxItem const * pSource) const
+{
+ std::unique_ptr<UnoTreeListItem> pNew(new UnoTreeListItem);
+ UnoTreeListItem const * pSourceItem = static_cast< UnoTreeListItem const * >( pSource );
+ pNew->maText = pSourceItem->maText;
+ pNew->maImage = pSourceItem->maImage;
+ return std::unique_ptr<SvLBoxItem>(pNew.release());
+}
+
+
+void UnoTreeListItem::SetImage( const Image& rImage )
+{
+ maImage = rImage;
+}
+
+
+void UnoTreeListItem::SetGraphicURL( const OUString& rGraphicURL )
+{
+ maGraphicURL = rGraphicURL;
+}
+
+
+void UnoTreeListItem::InitViewData( SvTreeListBox* pView,SvTreeListEntry* pEntry, SvViewDataItem* pViewData)
+{
+ if( !pViewData )
+ pViewData = pView->GetViewDataItem( pEntry, this );
+
+ Size aSize(maImage.GetSizePixel());
+ pViewData->mnWidth = aSize.Width();
+ pViewData->mnHeight = aSize.Height();
+
+ const Size aTextSize(pView->GetTextWidth( maText ), pView->GetTextHeight());
+ if( pViewData->mnWidth )
+ {
+ pViewData->mnWidth += (6 + aTextSize.Width());
+ if( pViewData->mnHeight < aTextSize.Height() )
+ pViewData->mnHeight = aTextSize.Height();
+ }
+ else
+ {
+ pViewData->mnWidth = aTextSize.Width();
+ pViewData->mnHeight = aTextSize.Height();
+ }
+}
+
+
+UnoTreeListEntry::UnoTreeListEntry( const Reference< XTreeNode >& xNode, TreeControlPeer* pPeer )
+: mxNode( xNode )
+, mpPeer( pPeer )
+{
+ if( mpPeer )
+ mpPeer->addEntry( this );
+}
+
+
+UnoTreeListEntry::~UnoTreeListEntry()
+{
+ if( mpPeer )
+ mpPeer->removeEntry( this );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/tree/treedatamodel.cxx b/toolkit/source/controls/tree/treedatamodel.cxx
new file mode 100644
index 000000000..df8056057
--- /dev/null
+++ b/toolkit/source/controls/tree/treedatamodel.cxx
@@ -0,0 +1,523 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/awt/tree/XMutableTreeDataModel.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <cppuhelper/implbase2.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <o3tl/safeint.hxx>
+#include <rtl/ref.hxx>
+#include <toolkit/helper/mutexandbroadcasthelper.hxx>
+#include <mutex>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::awt::tree;
+using namespace ::com::sun::star::lang;
+
+namespace {
+
+ enum broadcast_type { nodes_changed, nodes_inserted, nodes_removed, structure_changed };
+
+class MutableTreeNode;
+class MutableTreeDataModel;
+
+typedef std::vector< rtl::Reference< MutableTreeNode > > TreeNodeVector;
+
+class MutableTreeDataModel : public ::cppu::WeakAggImplHelper2< XMutableTreeDataModel, XServiceInfo >,
+ public MutexAndBroadcastHelper
+{
+public:
+ MutableTreeDataModel();
+
+ void broadcast( broadcast_type eType, const Reference< XTreeNode >& xParentNode, const Reference< XTreeNode >& rNode );
+
+ // XMutableTreeDataModel
+ virtual css::uno::Reference< css::awt::tree::XMutableTreeNode > SAL_CALL createNode( const css::uno::Any& DisplayValue, sal_Bool ChildrenOnDemand ) override;
+ virtual void SAL_CALL setRoot( const css::uno::Reference< css::awt::tree::XMutableTreeNode >& RootNode ) override;
+
+ // XTreeDataModel
+ virtual css::uno::Reference< css::awt::tree::XTreeNode > SAL_CALL getRoot( ) override;
+ virtual void SAL_CALL addTreeDataModelListener( const css::uno::Reference< css::awt::tree::XTreeDataModelListener >& Listener ) override;
+ virtual void SAL_CALL removeTreeDataModelListener( const css::uno::Reference< css::awt::tree::XTreeDataModelListener >& Listener ) override;
+
+ // XComponent
+ virtual void SAL_CALL dispose( ) override;
+ virtual void SAL_CALL addEventListener( const Reference< XEventListener >& xListener ) override;
+ virtual void SAL_CALL removeEventListener( const Reference< XEventListener >& aListener ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+private:
+ bool mbDisposed;
+ Reference< XTreeNode > mxRootNode;
+};
+
+class MutableTreeNode: public ::cppu::WeakAggImplHelper2< XMutableTreeNode, XServiceInfo >
+{
+ friend class MutableTreeDataModel;
+
+public:
+ MutableTreeNode( const rtl::Reference< MutableTreeDataModel >& xModel, const Any& rValue, bool bChildrenOnDemand );
+ virtual ~MutableTreeNode() override;
+
+ void setParent( MutableTreeNode* pParent );
+ void broadcast_changes();
+ void broadcast_changes(std::unique_lock<std::mutex> & rLock,
+ const Reference< XTreeNode >& xNode, bool bNew);
+
+ // XMutableTreeNode
+ virtual css::uno::Any SAL_CALL getDataValue() override;
+ virtual void SAL_CALL setDataValue( const css::uno::Any& _datavalue ) override;
+ virtual void SAL_CALL appendChild( const css::uno::Reference< css::awt::tree::XMutableTreeNode >& ChildNode ) override;
+ virtual void SAL_CALL insertChildByIndex( ::sal_Int32 Index, const css::uno::Reference< css::awt::tree::XMutableTreeNode >& ChildNode ) override;
+ virtual void SAL_CALL removeChildByIndex( ::sal_Int32 Index ) override;
+ virtual void SAL_CALL setHasChildrenOnDemand( sal_Bool ChildrenOnDemand ) override;
+ virtual void SAL_CALL setDisplayValue( const css::uno::Any& Value ) override;
+ virtual void SAL_CALL setNodeGraphicURL( const OUString& URL ) override;
+ virtual void SAL_CALL setExpandedGraphicURL( const OUString& URL ) override;
+ virtual void SAL_CALL setCollapsedGraphicURL( const OUString& URL ) override;
+
+ // XTreeNode
+ virtual css::uno::Reference< css::awt::tree::XTreeNode > SAL_CALL getChildAt( ::sal_Int32 Index ) override;
+ virtual ::sal_Int32 SAL_CALL getChildCount( ) override;
+ virtual css::uno::Reference< css::awt::tree::XTreeNode > SAL_CALL getParent( ) override;
+ virtual ::sal_Int32 SAL_CALL getIndex( const css::uno::Reference< css::awt::tree::XTreeNode >& Node ) override;
+ virtual sal_Bool SAL_CALL hasChildrenOnDemand( ) override;
+ virtual css::uno::Any SAL_CALL getDisplayValue( ) override;
+ virtual OUString SAL_CALL getNodeGraphicURL( ) override;
+ virtual OUString SAL_CALL getExpandedGraphicURL( ) override;
+ virtual OUString SAL_CALL getCollapsedGraphicURL( ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+private:
+ TreeNodeVector maChildren;
+ Any maDisplayValue;
+ Any maDataValue;
+ bool mbHasChildrenOnDemand;
+ std::mutex maMutex;
+ MutableTreeNode* mpParent;
+ rtl::Reference< MutableTreeDataModel > mxModel;
+ OUString maNodeGraphicURL;
+ OUString maExpandedGraphicURL;
+ OUString maCollapsedGraphicURL;
+ bool mbIsInserted;
+};
+
+MutableTreeDataModel::MutableTreeDataModel()
+: mbDisposed( false )
+{
+}
+
+void MutableTreeDataModel::broadcast( broadcast_type eType, const Reference< XTreeNode >& xParentNode, const Reference< XTreeNode >& rNode )
+{
+ ::cppu::OInterfaceContainerHelper* pIter = BrdcstHelper.getContainer( cppu::UnoType<XTreeDataModelListener>::get() );
+ if( !pIter )
+ return;
+
+ Reference< XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
+ const Sequence< Reference< XTreeNode > > aNodes { rNode };
+ TreeDataModelEvent aEvent( xSource, aNodes, xParentNode );
+
+ ::cppu::OInterfaceIteratorHelper aListIter(*pIter);
+ while(aListIter.hasMoreElements())
+ {
+ XTreeDataModelListener* pListener = static_cast<XTreeDataModelListener*>(aListIter.next());
+ switch( eType )
+ {
+ case nodes_changed: pListener->treeNodesChanged(aEvent); break;
+ case nodes_inserted: pListener->treeNodesInserted(aEvent); break;
+ case nodes_removed: pListener->treeNodesRemoved(aEvent); break;
+ case structure_changed: pListener->treeStructureChanged(aEvent); break;
+ }
+ }
+}
+
+Reference< XMutableTreeNode > SAL_CALL MutableTreeDataModel::createNode( const Any& aValue, sal_Bool bChildrenOnDemand )
+{
+ return new MutableTreeNode( this, aValue, bChildrenOnDemand );
+}
+
+void SAL_CALL MutableTreeDataModel::setRoot( const Reference< XMutableTreeNode >& xNode )
+{
+ if( !xNode.is() )
+ throw IllegalArgumentException();
+
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+ if( xNode == mxRootNode )
+ return;
+
+ if( mxRootNode.is() )
+ {
+ rtl::Reference< MutableTreeNode > xOldImpl( dynamic_cast< MutableTreeNode* >( mxRootNode.get() ) );
+ if( xOldImpl.is() )
+ xOldImpl->mbIsInserted = false;
+ }
+
+ rtl::Reference< MutableTreeNode > xImpl( dynamic_cast< MutableTreeNode* >( xNode.get() ) );
+ if( !xImpl.is() || xImpl->mbIsInserted )
+ throw IllegalArgumentException();
+
+ xImpl->mbIsInserted = true;
+ mxRootNode = xImpl;
+
+ Reference< XTreeNode > xParentNode;
+ broadcast( structure_changed, xParentNode, mxRootNode );
+}
+
+Reference< XTreeNode > SAL_CALL MutableTreeDataModel::getRoot( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+ return mxRootNode;
+}
+
+void SAL_CALL MutableTreeDataModel::addTreeDataModelListener( const Reference< XTreeDataModelListener >& xListener )
+{
+ BrdcstHelper.addListener( cppu::UnoType<XTreeDataModelListener>::get(), xListener );
+}
+
+void SAL_CALL MutableTreeDataModel::removeTreeDataModelListener( const Reference< XTreeDataModelListener >& xListener )
+{
+ BrdcstHelper.removeListener( cppu::UnoType<XTreeDataModelListener>::get(), xListener );
+}
+
+void SAL_CALL MutableTreeDataModel::dispose()
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ if( !mbDisposed )
+ {
+ mbDisposed = true;
+ css::lang::EventObject aEvent;
+ aEvent.Source.set( static_cast< ::cppu::OWeakObject* >( this ) );
+ BrdcstHelper.aLC.disposeAndClear( aEvent );
+ }
+}
+
+void SAL_CALL MutableTreeDataModel::addEventListener( const Reference< XEventListener >& xListener )
+{
+ BrdcstHelper.addListener( cppu::UnoType<XEventListener>::get(), xListener );
+}
+
+void SAL_CALL MutableTreeDataModel::removeEventListener( const Reference< XEventListener >& xListener )
+{
+ BrdcstHelper.removeListener( cppu::UnoType<XEventListener>::get(), xListener );
+}
+
+OUString SAL_CALL MutableTreeDataModel::getImplementationName( )
+{
+ return "toolkit.MutableTreeDataModel";
+}
+
+sal_Bool SAL_CALL MutableTreeDataModel::supportsService( const OUString& ServiceName )
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+Sequence< OUString > SAL_CALL MutableTreeDataModel::getSupportedServiceNames( )
+{
+ Sequence<OUString> aSeq { "com.sun.star.awt.tree.MutableTreeDataModel" };
+ return aSeq;
+}
+
+MutableTreeNode::MutableTreeNode( const rtl::Reference< MutableTreeDataModel >& xModel, const Any& rValue, bool bChildrenOnDemand )
+: maDisplayValue( rValue )
+, mbHasChildrenOnDemand( bChildrenOnDemand )
+, mpParent( nullptr )
+, mxModel( xModel )
+, mbIsInserted( false )
+{
+}
+
+MutableTreeNode::~MutableTreeNode()
+{
+ for( auto& rChild : maChildren )
+ rChild->setParent(nullptr);
+}
+
+void MutableTreeNode::setParent( MutableTreeNode* pParent )
+{
+ mpParent = pParent;
+}
+
+void MutableTreeNode::broadcast_changes()
+{
+ if( mxModel.is() )
+ {
+ mxModel->broadcast( nodes_changed, mpParent, this );
+ }
+}
+
+void MutableTreeNode::broadcast_changes(std::unique_lock<std::mutex> & rLock,
+ const Reference< XTreeNode >& xNode, bool const bNew)
+{
+ auto const xModel(mxModel);
+ rLock.unlock();
+ if (xModel.is())
+ {
+ xModel->broadcast(bNew ? nodes_inserted : nodes_removed, this, xNode);
+ }
+}
+
+Any SAL_CALL MutableTreeNode::getDataValue()
+{
+ std::scoped_lock aGuard( maMutex );
+ return maDataValue;
+}
+
+void SAL_CALL MutableTreeNode::setDataValue( const Any& _datavalue )
+{
+ std::scoped_lock aGuard( maMutex );
+ maDataValue = _datavalue;
+}
+
+void SAL_CALL MutableTreeNode::appendChild( const Reference< XMutableTreeNode >& xChildNode )
+{
+ std::unique_lock aGuard( maMutex );
+ rtl::Reference< MutableTreeNode > xImpl( dynamic_cast< MutableTreeNode* >( xChildNode.get() ) );
+
+ if( !xImpl.is() || xImpl->mbIsInserted || (this == xImpl.get()) )
+ throw IllegalArgumentException();
+
+ maChildren.push_back( xImpl );
+ xImpl->setParent(this);
+ xImpl->mbIsInserted = true;
+
+ broadcast_changes(aGuard, xChildNode, true);
+}
+
+void SAL_CALL MutableTreeNode::insertChildByIndex( sal_Int32 nChildIndex, const Reference< XMutableTreeNode >& xChildNode )
+{
+ std::unique_lock aGuard( maMutex );
+
+ if( (nChildIndex < 0) || (o3tl::make_unsigned(nChildIndex) > maChildren.size()) )
+ throw IndexOutOfBoundsException();
+
+ rtl::Reference< MutableTreeNode > xImpl( dynamic_cast< MutableTreeNode* >( xChildNode.get() ) );
+ if( !xImpl.is() || xImpl->mbIsInserted || (this == xImpl.get()) )
+ throw IllegalArgumentException();
+
+ xImpl->mbIsInserted = true;
+
+ TreeNodeVector::iterator aIter( maChildren.begin() );
+ std::advance(aIter, nChildIndex);
+
+ maChildren.insert( aIter, xImpl );
+ xImpl->setParent( this );
+
+ broadcast_changes(aGuard, xChildNode, true);
+}
+
+void SAL_CALL MutableTreeNode::removeChildByIndex( sal_Int32 nChildIndex )
+{
+ std::unique_lock aGuard( maMutex );
+
+ if( (nChildIndex < 0) || (o3tl::make_unsigned(nChildIndex) >= maChildren.size()) )
+ throw IndexOutOfBoundsException();
+
+ rtl::Reference< MutableTreeNode > xImpl;
+
+ TreeNodeVector::iterator aIter( maChildren.begin() );
+ std::advance(aIter, nChildIndex);
+
+ xImpl = *aIter;
+ maChildren.erase( aIter );
+
+ if( !xImpl.is() )
+ throw IndexOutOfBoundsException();
+
+ xImpl->setParent(nullptr);
+ xImpl->mbIsInserted = false;
+
+ broadcast_changes(aGuard, xImpl, false);
+}
+
+void SAL_CALL MutableTreeNode::setHasChildrenOnDemand( sal_Bool bChildrenOnDemand )
+{
+ bool bChanged;
+
+ {
+ std::scoped_lock aGuard( maMutex );
+ bChanged = mbHasChildrenOnDemand != bool(bChildrenOnDemand);
+ mbHasChildrenOnDemand = bChildrenOnDemand;
+ }
+
+ if( bChanged )
+ broadcast_changes();
+}
+
+void SAL_CALL MutableTreeNode::setDisplayValue( const Any& aValue )
+{
+ {
+ std::scoped_lock aGuard( maMutex );
+ maDisplayValue = aValue;
+ }
+
+ broadcast_changes();
+}
+
+void SAL_CALL MutableTreeNode::setNodeGraphicURL( const OUString& rURL )
+{
+ bool bChanged;
+
+ {
+ std::scoped_lock aGuard( maMutex );
+ bChanged = maNodeGraphicURL != rURL;
+ maNodeGraphicURL = rURL;
+ }
+
+ if( bChanged )
+ broadcast_changes();
+}
+
+void SAL_CALL MutableTreeNode::setExpandedGraphicURL( const OUString& rURL )
+{
+ bool bChanged;
+
+ {
+ std::scoped_lock aGuard( maMutex );
+ bChanged = maExpandedGraphicURL != rURL;
+ maExpandedGraphicURL = rURL;
+ }
+
+ if( bChanged )
+ broadcast_changes();
+}
+
+void SAL_CALL MutableTreeNode::setCollapsedGraphicURL( const OUString& rURL )
+{
+ bool bChanged;
+
+ {
+ std::scoped_lock aGuard( maMutex );
+ bChanged = maCollapsedGraphicURL != rURL;
+ maCollapsedGraphicURL = rURL;
+ }
+
+ if( bChanged )
+ broadcast_changes();
+}
+
+Reference< XTreeNode > SAL_CALL MutableTreeNode::getChildAt( sal_Int32 nChildIndex )
+{
+ std::scoped_lock aGuard( maMutex );
+
+ if( (nChildIndex < 0) || (o3tl::make_unsigned(nChildIndex) >= maChildren.size()) )
+ throw IndexOutOfBoundsException();
+ return maChildren[nChildIndex];
+}
+
+sal_Int32 SAL_CALL MutableTreeNode::getChildCount( )
+{
+ std::scoped_lock aGuard( maMutex );
+ return static_cast<sal_Int32>(maChildren.size());
+}
+
+Reference< XTreeNode > SAL_CALL MutableTreeNode::getParent( )
+{
+ std::scoped_lock aGuard( maMutex );
+ return mpParent;
+}
+
+sal_Int32 SAL_CALL MutableTreeNode::getIndex( const Reference< XTreeNode >& xNode )
+{
+ std::scoped_lock aGuard( maMutex );
+
+ rtl::Reference< MutableTreeNode > xImpl( dynamic_cast< MutableTreeNode* >( xNode.get() ) );
+ if( xImpl.is() )
+ {
+ sal_Int32 nChildCount = maChildren.size();
+ while( nChildCount-- )
+ {
+ if( maChildren[nChildCount] == xImpl )
+ return nChildCount;
+ }
+ }
+
+ return -1;
+}
+
+sal_Bool SAL_CALL MutableTreeNode::hasChildrenOnDemand( )
+{
+ std::scoped_lock aGuard( maMutex );
+ return mbHasChildrenOnDemand;
+}
+
+Any SAL_CALL MutableTreeNode::getDisplayValue( )
+{
+ std::scoped_lock aGuard( maMutex );
+ return maDisplayValue;
+}
+
+OUString SAL_CALL MutableTreeNode::getNodeGraphicURL( )
+{
+ std::scoped_lock aGuard( maMutex );
+ return maNodeGraphicURL;
+}
+
+OUString SAL_CALL MutableTreeNode::getExpandedGraphicURL( )
+{
+ std::scoped_lock aGuard( maMutex );
+ return maExpandedGraphicURL;
+}
+
+OUString SAL_CALL MutableTreeNode::getCollapsedGraphicURL( )
+{
+ std::scoped_lock aGuard( maMutex );
+ return maCollapsedGraphicURL;
+}
+
+OUString SAL_CALL MutableTreeNode::getImplementationName( )
+{
+ return "toolkit.MutableTreeNode";
+}
+
+sal_Bool SAL_CALL MutableTreeNode::supportsService( const OUString& ServiceName )
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+Sequence< OUString > SAL_CALL MutableTreeNode::getSupportedServiceNames( )
+{
+ Sequence<OUString> aSeq { "com.sun.star.awt.tree.MutableTreeNode" };
+ return aSeq;
+}
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_MutableTreeDataModel_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new MutableTreeDataModel());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/unocontrol.cxx b/toolkit/source/controls/unocontrol.cxx
new file mode 100644
index 000000000..b1e802899
--- /dev/null
+++ b/toolkit/source/controls/unocontrol.cxx
@@ -0,0 +1,1565 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <com/sun/star/awt/XControlContainer.hpp>
+#include <com/sun/star/awt/WindowAttribute.hpp>
+#include <com/sun/star/awt/VclWindowPeerAttribute.hpp>
+#include <com/sun/star/awt/PosSize.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/lang/NoSupportException.hpp>
+#include <com/sun/star/resource/XStringResourceResolver.hpp>
+#include <toolkit/controls/unocontrol.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <osl/mutex.hxx>
+#include <tools/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <toolkit/helper/property.hxx>
+#include <toolkit/awt/vclxwindow.hxx>
+#include <controls/accessiblecontrolcontext.hxx>
+
+#include <algorithm>
+#include <map>
+#include <string_view>
+#include <vector>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::util;
+
+using ::com::sun::star::accessibility::XAccessibleContext;
+using ::com::sun::star::accessibility::XAccessible;
+
+namespace {
+
+struct LanguageDependentProp
+{
+ const char* pPropName;
+ sal_Int32 nPropNameLength;
+};
+
+}
+
+const LanguageDependentProp aLanguageDependentProp[] =
+{
+ { "Text", 4 },
+ { "Label", 5 },
+ { "Title", 5 },
+ { "HelpText", 8 },
+ { "CurrencySymbol", 14 },
+ { "StringItemList", 14 },
+ { nullptr, 0 }
+};
+
+static Sequence< OUString> lcl_ImplGetPropertyNames( const Reference< XMultiPropertySet > & rxModel )
+{
+ Sequence< OUString> aNames;
+ Reference< XPropertySetInfo > xPSInf = rxModel->getPropertySetInfo();
+ DBG_ASSERT( xPSInf.is(), "UpdateFromModel: No PropertySetInfo!" );
+ if ( xPSInf.is() )
+ {
+ const Sequence< Property> aProps = xPSInf->getProperties();
+ sal_Int32 nLen = aProps.getLength();
+ aNames = Sequence< OUString>( nLen );
+ std::transform(aProps.begin(), aProps.end(), aNames.getArray(),
+ [](const Property& rProp) -> OUString { return rProp.Name; });
+ }
+ return aNames;
+}
+
+namespace {
+
+class VclListenerLock
+{
+private:
+ VCLXWindow* m_pLockWindow;
+
+public:
+ explicit VclListenerLock( VCLXWindow* _pLockWindow )
+ : m_pLockWindow( _pLockWindow )
+ {
+ if ( m_pLockWindow )
+ m_pLockWindow->suspendVclEventListening( );
+ }
+ ~VclListenerLock()
+ {
+ if ( m_pLockWindow )
+ m_pLockWindow->resumeVclEventListening( );
+ }
+ VclListenerLock(const VclListenerLock&) = delete;
+ VclListenerLock& operator=(const VclListenerLock&) = delete;
+};
+
+}
+
+typedef ::std::map< OUString, sal_Int32 > MapString2Int;
+struct UnoControl_Data
+{
+ MapString2Int aSuspendedPropertyNotifications;
+ /// true if and only if our model has a property ResourceResolver
+ bool bLocalizationSupport;
+
+ UnoControl_Data()
+ :bLocalizationSupport( false )
+ {
+ }
+};
+
+UnoControl::UnoControl() :
+ maDisposeListeners( *this )
+ , maWindowListeners( *this )
+ , maFocusListeners( *this )
+ , maKeyListeners( *this )
+ , maMouseListeners( *this )
+ , maMouseMotionListeners( *this )
+ , maPaintListeners( *this )
+ , maModeChangeListeners( GetMutex() )
+ , mpData( new UnoControl_Data )
+{
+ mbDisposePeer = true;
+ mbRefreshingPeer = false;
+ mbCreatingPeer = false;
+ mbCreatingCompatiblePeer = false;
+ mbDesignMode = false;
+}
+
+UnoControl::~UnoControl()
+{
+}
+
+OUString UnoControl::GetComponentServiceName() const
+{
+ return OUString();
+}
+
+Reference< XWindowPeer > UnoControl::ImplGetCompatiblePeer()
+{
+ DBG_ASSERT( !mbCreatingCompatiblePeer, "ImplGetCompatiblePeer - recursive?" );
+
+ mbCreatingCompatiblePeer = true;
+
+ Reference< XWindowPeer > xCompatiblePeer = getPeer();
+
+ if ( !xCompatiblePeer.is() )
+ {
+ // Create the pair as invisible
+ bool bVis = maComponentInfos.bVisible;
+ if( bVis )
+ maComponentInfos.bVisible = false;
+
+ Reference< XWindowPeer > xCurrentPeer = getPeer();
+ setPeer( nullptr );
+
+ // queryInterface ourself, to allow aggregation
+ Reference< XControl > xMe;
+ OWeakAggObject::queryInterface( cppu::UnoType<decltype(xMe)>::get() ) >>= xMe;
+
+ vcl::Window* pParentWindow( nullptr );
+ {
+ SolarMutexGuard aGuard;
+ auto pDefaultDevice = Application::GetDefaultDevice();
+ if (pDefaultDevice)
+ pParentWindow = pDefaultDevice->GetOwnerWindow();
+ ENSURE_OR_THROW( pParentWindow != nullptr, "could obtain a default parent window!" );
+ }
+ try
+ {
+ xMe->createPeer( nullptr, pParentWindow->GetComponentInterface() );
+ }
+ catch( const Exception& )
+ {
+ mbCreatingCompatiblePeer = false;
+ throw;
+ }
+ xCompatiblePeer = getPeer();
+ setPeer( xCurrentPeer );
+
+ if ( xCompatiblePeer.is() && mxGraphics.is() )
+ {
+ Reference< XView > xPeerView( xCompatiblePeer, UNO_QUERY );
+ if ( xPeerView.is() )
+ xPeerView->setGraphics( mxGraphics );
+ }
+
+ if( bVis )
+ maComponentInfos.bVisible = true;
+ }
+
+ mbCreatingCompatiblePeer = false;
+
+ return xCompatiblePeer;
+}
+
+bool UnoControl::ImplCheckLocalize( OUString& _rPossiblyLocalizable )
+{
+ if ( !mpData->bLocalizationSupport
+ || ( _rPossiblyLocalizable.isEmpty() )
+ || ( _rPossiblyLocalizable[0] != '&' )
+ // TODO: make this reasonable. At the moment, everything which by accident starts with a & is considered
+ // localizable, which is probably wrong.
+ )
+ return false;
+
+ try
+ {
+ Reference< XPropertySet > xPropSet( mxModel, UNO_QUERY_THROW );
+ Reference< resource::XStringResourceResolver > xStringResourceResolver(
+ xPropSet->getPropertyValue("ResourceResolver"),
+ UNO_QUERY
+ );
+ if ( xStringResourceResolver.is() )
+ {
+ OUString aLocalizationKey( _rPossiblyLocalizable.copy( 1 ) );
+ _rPossiblyLocalizable = xStringResourceResolver->resolveString( aLocalizationKey );
+ return true;
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+ return false;
+}
+
+void UnoControl::ImplSetPeerProperty( const OUString& rPropName, const Any& rVal )
+{
+ // since a change made in propertiesChange, we can't be sure that this is called with a valid getPeer(),
+ // this assumption may be false in some (seldom) multi-threading scenarios (cause propertiesChange
+ // releases our mutex before calling here in)
+ // That's why this additional check
+
+ if ( !mxVclWindowPeer.is() )
+ return;
+
+ Any aConvertedValue( rVal );
+
+ if ( mpData->bLocalizationSupport )
+ {
+ // We now support a mapping for language dependent properties. This is the
+ // central method to implement it.
+ if( rPropName == "Text" ||
+ rPropName == "Label" ||
+ rPropName == "Title" ||
+ rPropName == "HelpText" ||
+ rPropName == "CurrencySymbol" ||
+ rPropName == "StringItemList" )
+ {
+ OUString aValue;
+ uno::Sequence< OUString > aSeqValue;
+ if ( aConvertedValue >>= aValue )
+ {
+ if ( ImplCheckLocalize( aValue ) )
+ aConvertedValue <<= aValue;
+ }
+ else if ( aConvertedValue >>= aSeqValue )
+ {
+ for ( auto& rValue : asNonConstRange(aSeqValue) )
+ ImplCheckLocalize( rValue );
+ aConvertedValue <<= aSeqValue;
+ }
+ }
+ }
+
+ mxVclWindowPeer->setProperty( rPropName, aConvertedValue );
+}
+
+void UnoControl::PrepareWindowDescriptor( WindowDescriptor& )
+{
+}
+
+Reference< XWindow > UnoControl::getParentPeer() const
+{
+ Reference< XWindow > xPeer;
+ if( mxContext.is() )
+ {
+ Reference< XControl > xContComp( mxContext, UNO_QUERY );
+ if ( xContComp.is() )
+ {
+ Reference< XWindowPeer > xP = xContComp->getPeer();
+ if ( xP.is() )
+ xPeer.set( xP, UNO_QUERY );
+ }
+ }
+ return xPeer;
+}
+
+void UnoControl::updateFromModel()
+{
+ // Read default properties and hand over to peer
+ if( getPeer().is() )
+ {
+ Reference< XMultiPropertySet > xPropSet( mxModel, UNO_QUERY );
+ if( xPropSet.is() )
+ {
+ Sequence< OUString> aNames = lcl_ImplGetPropertyNames( xPropSet );
+ xPropSet->firePropertiesChangeEvent( aNames, this );
+ }
+ }
+}
+
+
+// XTypeProvider
+IMPL_IMPLEMENTATION_ID( UnoControl )
+
+void
+UnoControl::DisposeAccessibleContext(Reference<XComponent> const& xContextComp)
+{
+ if (xContextComp.is())
+ {
+ try
+ {
+ xContextComp->removeEventListener( this );
+ xContextComp->dispose();
+ }
+ catch( const Exception& )
+ {
+ OSL_FAIL( "UnoControl::disposeAccessibleContext: could not dispose my AccessibleContext!" );
+ }
+ }
+}
+
+void UnoControl::dispose( )
+{
+ Reference< XWindowPeer > xPeer;
+ Reference<XComponent> xAccessibleComp;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ if( mbDisposePeer )
+ {
+ xPeer = mxPeer;
+ }
+ setPeer( nullptr );
+ xAccessibleComp.set(maAccessibleContext, UNO_QUERY);
+ maAccessibleContext.clear();
+ }
+ if( xPeer.is() )
+ {
+ xPeer->dispose();
+ }
+
+ // dispose our AccessibleContext - without Mutex locked
+ DisposeAccessibleContext(xAccessibleComp);
+
+ EventObject aDisposeEvent;
+ aDisposeEvent.Source = static_cast< XAggregation* >( this );
+
+ maDisposeListeners.disposeAndClear( aDisposeEvent );
+ maWindowListeners.disposeAndClear( aDisposeEvent );
+ maFocusListeners.disposeAndClear( aDisposeEvent );
+ maKeyListeners.disposeAndClear( aDisposeEvent );
+ maMouseListeners.disposeAndClear( aDisposeEvent );
+ maMouseMotionListeners.disposeAndClear( aDisposeEvent );
+ maPaintListeners.disposeAndClear( aDisposeEvent );
+ maModeChangeListeners.disposeAndClear( aDisposeEvent );
+
+ // release Model again
+ setModel( Reference< XControlModel > () );
+ setContext( Reference< XInterface > () );
+}
+
+void UnoControl::addEventListener( const Reference< XEventListener >& rxListener )
+{
+ ::osl::MutexGuard aGuard( GetMutex() );
+
+ maDisposeListeners.addInterface( rxListener );
+}
+
+void UnoControl::removeEventListener( const Reference< XEventListener >& rxListener )
+{
+ ::osl::MutexGuard aGuard( GetMutex() );
+
+ maDisposeListeners.removeInterface( rxListener );
+}
+
+bool UnoControl::requiresNewPeer( const OUString& /* _rPropertyName */ ) const
+{
+ return false;
+}
+
+// XPropertiesChangeListener
+void UnoControl::propertiesChange( const Sequence< PropertyChangeEvent >& rEvents )
+{
+ Sequence< PropertyChangeEvent > aEvents( rEvents );
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+
+ if ( !mpData->aSuspendedPropertyNotifications.empty() )
+ {
+ // strip the property which we are currently updating (somewhere up the stack)
+ PropertyChangeEvent* pEvents = aEvents.getArray();
+ PropertyChangeEvent* pEventsEnd = pEvents + aEvents.getLength();
+ for ( ; pEvents < pEventsEnd; )
+ if ( mpData->aSuspendedPropertyNotifications.find( pEvents->PropertyName ) != mpData->aSuspendedPropertyNotifications.end() )
+ {
+ std::copy(pEvents + 1, pEventsEnd, pEvents);
+ --pEventsEnd;
+ }
+ else
+ ++pEvents;
+ aEvents.realloc( pEventsEnd - aEvents.getConstArray() );
+
+ if ( !aEvents.hasElements() )
+ return;
+ }
+ }
+
+ ImplModelPropertiesChanged( aEvents );
+}
+
+void UnoControl::ImplLockPropertyChangeNotification( const OUString& rPropertyName, bool bLock )
+{
+ MapString2Int::iterator pos = mpData->aSuspendedPropertyNotifications.find( rPropertyName );
+ if ( bLock )
+ {
+ if ( pos == mpData->aSuspendedPropertyNotifications.end() )
+ pos = mpData->aSuspendedPropertyNotifications.emplace( rPropertyName, 0 ).first;
+ ++pos->second;
+ }
+ else
+ {
+ OSL_ENSURE( pos != mpData->aSuspendedPropertyNotifications.end(), "UnoControl::ImplLockPropertyChangeNotification: property not locked!" );
+ if ( pos != mpData->aSuspendedPropertyNotifications.end() )
+ {
+ OSL_ENSURE( pos->second > 0, "UnoControl::ImplLockPropertyChangeNotification: invalid suspension counter!" );
+ if ( 0 == --pos->second )
+ mpData->aSuspendedPropertyNotifications.erase( pos );
+ }
+ }
+}
+
+void UnoControl::ImplLockPropertyChangeNotifications( const Sequence< OUString >& rPropertyNames, bool bLock )
+{
+ for ( auto const & propertyName : rPropertyNames )
+ ImplLockPropertyChangeNotification( propertyName, bLock );
+}
+
+void UnoControl::ImplModelPropertiesChanged( const Sequence< PropertyChangeEvent >& rEvents )
+{
+ ::osl::ClearableGuard< ::osl::Mutex > aGuard( GetMutex() );
+
+ if( !getPeer().is() )
+ return;
+
+ std::vector< PropertyValue > aPeerPropertiesToSet;
+ sal_Int32 nIndependentPos = 0;
+ bool bResourceResolverSet( false );
+ // position where to insert the independent properties into aPeerPropertiesToSet,
+ // dependent ones are inserted at the end of the vector
+
+ bool bNeedNewPeer = false;
+ // some properties require a re-creation of the peer, 'cause they can't be changed on the fly
+
+ Reference< XControlModel > xOwnModel = getModel();
+ // our own model for comparison
+ Reference< XPropertySet > xPS( xOwnModel, UNO_QUERY );
+ Reference< XPropertySetInfo > xPSI = xPS->getPropertySetInfo();
+ OSL_ENSURE( xPSI.is(), "UnoControl::ImplModelPropertiesChanged: should have property set meta data!" );
+
+ sal_Int32 nLen = rEvents.getLength();
+ aPeerPropertiesToSet.reserve(nLen);
+
+ for( const PropertyChangeEvent& rEvent : rEvents )
+ {
+ Reference< XControlModel > xModel( rEvent.Source, UNO_QUERY );
+ bool bOwnModel = xModel.get() == xOwnModel.get();
+ if ( !bOwnModel )
+ continue;
+
+ // Detect changes on our resource resolver which invalidates
+ // automatically some language dependent properties.
+ if ( rEvent.PropertyName == "ResourceResolver" )
+ {
+ Reference< resource::XStringResourceResolver > xStrResolver;
+ if ( rEvent.NewValue >>= xStrResolver )
+ bResourceResolverSet = xStrResolver.is();
+ }
+
+ sal_uInt16 nPType = GetPropertyId( rEvent.PropertyName );
+ if ( mbDesignMode && mbDisposePeer && !mbRefreshingPeer && !mbCreatingPeer )
+ {
+ // if we're in design mode, then some properties can change which
+ // require creating a *new* peer (since these properties cannot
+ // be switched at existing peers)
+ if ( nPType )
+ bNeedNewPeer = ( nPType == BASEPROPERTY_BORDER )
+ || ( nPType == BASEPROPERTY_MULTILINE )
+ || ( nPType == BASEPROPERTY_DROPDOWN )
+ || ( nPType == BASEPROPERTY_HSCROLL )
+ || ( nPType == BASEPROPERTY_VSCROLL )
+ || ( nPType == BASEPROPERTY_AUTOHSCROLL )
+ || ( nPType == BASEPROPERTY_AUTOVSCROLL )
+ || ( nPType == BASEPROPERTY_ORIENTATION )
+ || ( nPType == BASEPROPERTY_SPIN )
+ || ( nPType == BASEPROPERTY_ALIGN )
+ || ( nPType == BASEPROPERTY_PAINTTRANSPARENT );
+ else
+ bNeedNewPeer = requiresNewPeer( rEvent.PropertyName );
+
+ if ( bNeedNewPeer )
+ break;
+ }
+
+ if ( nPType && ( nLen > 1 ) && DoesDependOnOthers( nPType ) )
+ {
+ // Add properties with dependencies on other properties last
+ // since they're dependent on properties added later (such as
+ // VALUE dependency on VALUEMIN/MAX)
+ aPeerPropertiesToSet.emplace_back(rEvent.PropertyName, 0, rEvent.NewValue, PropertyState_DIRECT_VALUE);
+ }
+ else
+ {
+ if ( bResourceResolverSet )
+ {
+ // The resource resolver property change should be one of the first ones.
+ // All language dependent properties are dependent on this property.
+ // As BASEPROPERTY_NATIVE_WIDGET_LOOK is not dependent on resource
+ // resolver. We don't need to handle a special order for these two props.
+ aPeerPropertiesToSet.insert(
+ aPeerPropertiesToSet.begin(),
+ PropertyValue( rEvent.PropertyName, 0, rEvent.NewValue, PropertyState_DIRECT_VALUE ) );
+ ++nIndependentPos;
+ }
+ else if ( nPType == BASEPROPERTY_NATIVE_WIDGET_LOOK )
+ {
+ // since *a lot* of other properties might be overruled by this one, we need
+ // a special handling:
+ // NativeWidgetLook needs to be set first: If it is set to ON, all other
+ // properties describing the look (e.g. BackgroundColor) are ignored, anyway.
+ // If it is switched OFF, then we need to do it first because else it will
+ // overrule other look-related properties, and re-initialize them from system
+ // defaults.
+ aPeerPropertiesToSet.insert(
+ aPeerPropertiesToSet.begin(),
+ PropertyValue( rEvent.PropertyName, 0, rEvent.NewValue, PropertyState_DIRECT_VALUE ) );
+ ++nIndependentPos;
+ }
+ else
+ {
+ aPeerPropertiesToSet.insert(aPeerPropertiesToSet.begin() + nIndependentPos,
+ PropertyValue(rEvent.PropertyName, 0, rEvent.NewValue, PropertyState_DIRECT_VALUE));
+ ++nIndependentPos;
+ }
+ }
+ }
+
+ Reference< XWindow > xParent = getParentPeer();
+ Reference< XControl > xThis(this);
+ // call createPeer via an interface got from queryInterface, so the aggregating class can intercept it
+
+ DBG_ASSERT( !bNeedNewPeer || xParent.is(), "Need new peer, but don't have a parent!" );
+
+ // Check if we have to update language dependent properties
+ if ( !bNeedNewPeer && bResourceResolverSet )
+ {
+ // Add language dependent properties into the peer property set.
+ // Our resource resolver has been changed and we must be sure
+ // that language dependent props use the new resolver.
+ const LanguageDependentProp* pLangDepProp = aLanguageDependentProp;
+ while ( pLangDepProp->pPropName != nullptr )
+ {
+ bool bMustBeInserted( true );
+ for (const PropertyValue & i : aPeerPropertiesToSet)
+ {
+ if ( i.Name.equalsAsciiL(
+ pLangDepProp->pPropName, pLangDepProp->nPropNameLength ))
+ {
+ bMustBeInserted = false;
+ break;
+ }
+ }
+
+ if ( bMustBeInserted )
+ {
+ // Add language dependent props at the end
+ OUString aPropName( OUString::createFromAscii( pLangDepProp->pPropName ));
+ if ( xPSI.is() && xPSI->hasPropertyByName( aPropName ) )
+ {
+ aPeerPropertiesToSet.emplace_back( aPropName, 0, xPS->getPropertyValue( aPropName ), PropertyState_DIRECT_VALUE );
+ }
+ }
+
+ ++pLangDepProp;
+ }
+ }
+ aGuard.clear();
+
+ // clear the guard before creating a new peer - as usual, our peer implementations use the SolarMutex
+
+ if (bNeedNewPeer && xParent.is())
+ {
+ SolarMutexGuard aVclGuard;
+ // and now this is the final withdrawal:
+ // I have no other idea than locking the SolarMutex here...
+ // I really hate the fact that VCL is not threadsafe...
+
+ // Doesn't work for Container!
+ getPeer()->dispose();
+ mxPeer.clear();
+ mxVclWindowPeer = nullptr;
+ mbRefreshingPeer = true;
+ Reference< XWindowPeer > xP( xParent, UNO_QUERY );
+ xThis->createPeer( Reference< XToolkit > (), xP );
+ mbRefreshingPeer = false;
+ aPeerPropertiesToSet.clear();
+ }
+
+ // lock the multiplexing of VCL events to our UNO listeners
+ // this is for compatibility reasons: in OOo 1.0.x, changes which were done at the
+ // model did not cause the listeners of the controls/peers to be called
+ // Since the implementations for the listeners changed a lot towards 1.1, this
+ // would not be the case anymore, if we would not do this listener-lock below
+ // #i14703#
+ VCLXWindow* pPeer;
+ {
+ SolarMutexGuard g;
+ VclPtr<vcl::Window> pVclPeer = VCLUnoHelper::GetWindow( getPeer() );
+ pPeer = pVclPeer ? pVclPeer->GetWindowPeer() : nullptr;
+ }
+ VclListenerLock aNoVclEventMultiplexing( pPeer );
+
+ // setting peer properties may result in an attempt to acquire the solar mutex, 'cause the peers
+ // usually don't have an own mutex but use the SolarMutex instead.
+ // To prevent deadlocks resulting from this, we do this without our own mutex locked
+ for (const auto& rProp : aPeerPropertiesToSet)
+ {
+ ImplSetPeerProperty( rProp.Name, rProp.Value );
+ }
+
+}
+
+void UnoControl::disposing( const EventObject& rEvt )
+{
+ ::osl::ClearableMutexGuard aGuard( GetMutex() );
+ // do not compare differing types in case of multiple inheritance
+
+ if ( maAccessibleContext.get() == rEvt.Source )
+ {
+ // just in case the context is disposed, but not released - ensure that we do not re-use it in the future
+ maAccessibleContext.clear();
+ }
+ else if( mxModel.get() == Reference< XControlModel >(rEvt.Source,UNO_QUERY).get() )
+ {
+ // #62337# if the model dies, it does not make sense for us to live ...
+ Reference< XControl > xThis = this;
+
+ aGuard.clear();
+ xThis->dispose();
+
+ DBG_ASSERT( !mxModel.is(), "UnoControl::disposing: invalid dispose behaviour!" );
+ mxModel.clear();
+ }
+}
+
+
+void SAL_CALL UnoControl::setOutputSize( const awt::Size& aSize )
+{
+ Reference< XWindow2 > xPeerWindow;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
+ }
+
+ if ( xPeerWindow.is() )
+ xPeerWindow->setOutputSize( aSize );
+}
+
+namespace
+{
+ template < typename RETVALTYPE, typename DEFAULTTYPE >
+ RETVALTYPE lcl_askPeer( const uno::Reference< awt::XWindowPeer >& _rxPeer, RETVALTYPE (SAL_CALL XWindow2::*_pMethod)(), DEFAULTTYPE _aDefault )
+ {
+ RETVALTYPE aReturn( _aDefault );
+
+ Reference< XWindow2 > xPeerWindow( _rxPeer, UNO_QUERY );
+ if ( xPeerWindow.is() )
+ aReturn = (xPeerWindow.get()->*_pMethod)();
+
+ return aReturn;
+ }
+}
+
+awt::Size SAL_CALL UnoControl::getOutputSize( )
+{
+ return lcl_askPeer( getPeer(), &XWindow2::getOutputSize, awt::Size() );
+}
+
+sal_Bool SAL_CALL UnoControl::isVisible( )
+{
+ return lcl_askPeer( getPeer(), &XWindow2::isVisible, maComponentInfos.bVisible );
+}
+
+sal_Bool SAL_CALL UnoControl::isActive( )
+{
+ return lcl_askPeer( getPeer(), &XWindow2::isActive, false );
+}
+
+sal_Bool SAL_CALL UnoControl::isEnabled( )
+{
+ return lcl_askPeer( getPeer(), &XWindow2::isEnabled, maComponentInfos.bEnable );
+}
+
+sal_Bool SAL_CALL UnoControl::hasFocus( )
+{
+ return lcl_askPeer( getPeer(), &XWindow2::hasFocus, false );
+}
+
+// XWindow
+void UnoControl::setPosSize( sal_Int32 X, sal_Int32 Y, sal_Int32 Width, sal_Int32 Height, sal_Int16 Flags )
+{
+ Reference< XWindow > xWindow;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+
+ if ( Flags & awt::PosSize::X )
+ maComponentInfos.nX = X;
+ if ( Flags & awt::PosSize::Y )
+ maComponentInfos.nY = Y;
+ if ( Flags & awt::PosSize::WIDTH )
+ maComponentInfos.nWidth = Width;
+ if ( Flags & awt::PosSize::HEIGHT )
+ maComponentInfos.nHeight = Height;
+ maComponentInfos.nFlags |= Flags;
+
+ xWindow.set(getPeer(), css::uno::UNO_QUERY);
+ }
+
+ if( xWindow.is() )
+ xWindow->setPosSize( X, Y, Width, Height, Flags );
+}
+
+awt::Rectangle UnoControl::getPosSize( )
+{
+ awt::Rectangle aRect( maComponentInfos.nX, maComponentInfos.nY, maComponentInfos.nWidth, maComponentInfos.nHeight);
+ Reference< XWindow > xWindow;
+
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ xWindow.set(getPeer(), css::uno::UNO_QUERY);
+ }
+
+ if( xWindow.is() )
+ aRect = xWindow->getPosSize();
+ return aRect;
+}
+
+void UnoControl::setVisible( sal_Bool bVisible )
+{
+ Reference< XWindow > xWindow;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+
+ // Visible status is handled by View
+ maComponentInfos.bVisible = bVisible;
+ xWindow.set(getPeer(), css::uno::UNO_QUERY);
+ }
+ if ( xWindow.is() )
+ xWindow->setVisible( bVisible );
+}
+
+void UnoControl::setEnable( sal_Bool bEnable )
+{
+ Reference< XWindow > xWindow;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+
+ // Enable status is handled by View
+ maComponentInfos.bEnable = bEnable;
+ xWindow.set(getPeer(), css::uno::UNO_QUERY);
+ }
+ if ( xWindow.is() )
+ xWindow->setEnable( bEnable );
+}
+
+void UnoControl::setFocus( )
+{
+ Reference< XWindow > xWindow;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ xWindow.set(getPeer(), css::uno::UNO_QUERY);
+ }
+ if ( xWindow.is() )
+ xWindow->setFocus();
+}
+
+void UnoControl::addWindowListener( const Reference< XWindowListener >& rxListener )
+{
+ Reference< XWindow > xPeerWindow;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ maWindowListeners.addInterface( rxListener );
+ if ( maWindowListeners.getLength() == 1 )
+ xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
+ }
+ if ( xPeerWindow.is() )
+ xPeerWindow->addWindowListener( &maWindowListeners );
+}
+
+void UnoControl::removeWindowListener( const Reference< XWindowListener >& rxListener )
+{
+ Reference< XWindow > xPeerWindow;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ if ( maWindowListeners.getLength() == 1 )
+ xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
+ maWindowListeners.removeInterface( rxListener );
+ }
+ if ( xPeerWindow.is() )
+ xPeerWindow->removeWindowListener( &maWindowListeners );
+}
+
+void UnoControl::addFocusListener( const Reference< XFocusListener >& rxListener )
+{
+ Reference< XWindow > xPeerWindow;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ maFocusListeners.addInterface( rxListener );
+ if ( maFocusListeners.getLength() == 1 )
+ xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
+ }
+ if ( xPeerWindow.is() )
+ xPeerWindow->addFocusListener( &maFocusListeners );
+}
+
+void UnoControl::removeFocusListener( const Reference< XFocusListener >& rxListener )
+{
+ Reference< XWindow > xPeerWindow;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ if ( maFocusListeners.getLength() == 1 )
+ xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
+ maFocusListeners.removeInterface( rxListener );
+ }
+ if ( xPeerWindow.is() )
+ xPeerWindow->removeFocusListener( &maFocusListeners );
+}
+
+void UnoControl::addKeyListener( const Reference< XKeyListener >& rxListener )
+{
+ Reference< XWindow > xPeerWindow;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ maKeyListeners.addInterface( rxListener );
+ if ( maKeyListeners.getLength() == 1 )
+ xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
+ }
+ if ( xPeerWindow.is() )
+ xPeerWindow->addKeyListener( &maKeyListeners);
+}
+
+void UnoControl::removeKeyListener( const Reference< XKeyListener >& rxListener )
+{
+ Reference< XWindow > xPeerWindow;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ if ( maKeyListeners.getLength() == 1 )
+ xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
+ maKeyListeners.removeInterface( rxListener );
+ }
+ if ( xPeerWindow.is() )
+ xPeerWindow->removeKeyListener( &maKeyListeners);
+}
+
+void UnoControl::addMouseListener( const Reference< XMouseListener >& rxListener )
+{
+ Reference< XWindow > xPeerWindow;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ maMouseListeners.addInterface( rxListener );
+ if ( maMouseListeners.getLength() == 1 )
+ xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
+ }
+ if ( xPeerWindow.is() )
+ xPeerWindow->addMouseListener( &maMouseListeners);
+}
+
+void UnoControl::removeMouseListener( const Reference< XMouseListener >& rxListener )
+{
+ Reference< XWindow > xPeerWindow;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ if ( maMouseListeners.getLength() == 1 )
+ xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
+ maMouseListeners.removeInterface( rxListener );
+ }
+ if ( xPeerWindow.is() )
+ xPeerWindow->removeMouseListener( &maMouseListeners );
+}
+
+void UnoControl::addMouseMotionListener( const Reference< XMouseMotionListener >& rxListener )
+{
+ Reference< XWindow > xPeerWindow;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ maMouseMotionListeners.addInterface( rxListener );
+ if ( maMouseMotionListeners.getLength() == 1 )
+ xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
+ }
+ if ( xPeerWindow.is() )
+ xPeerWindow->addMouseMotionListener( &maMouseMotionListeners);
+}
+
+void UnoControl::removeMouseMotionListener( const Reference< XMouseMotionListener >& rxListener )
+{
+ Reference< XWindow > xPeerWindow;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ if ( maMouseMotionListeners.getLength() == 1 )
+ xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
+ maMouseMotionListeners.removeInterface( rxListener );
+ }
+ if ( xPeerWindow.is() )
+ xPeerWindow->removeMouseMotionListener( &maMouseMotionListeners );
+}
+
+void UnoControl::addPaintListener( const Reference< XPaintListener >& rxListener )
+{
+ Reference< XWindow > xPeerWindow;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ maPaintListeners.addInterface( rxListener );
+ if ( maPaintListeners.getLength() == 1 )
+ xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
+ }
+ if ( xPeerWindow.is() )
+ xPeerWindow->addPaintListener( &maPaintListeners);
+}
+
+void UnoControl::removePaintListener( const Reference< XPaintListener >& rxListener )
+{
+ Reference< XWindow > xPeerWindow;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ if ( maPaintListeners.getLength() == 1 )
+ xPeerWindow.set(getPeer(), css::uno::UNO_QUERY);
+ maPaintListeners.removeInterface( rxListener );
+ }
+ if ( xPeerWindow.is() )
+ xPeerWindow->removePaintListener( &maPaintListeners );
+}
+
+// XView
+sal_Bool UnoControl::setGraphics( const Reference< XGraphics >& rDevice )
+{
+ Reference< XView > xView;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+
+ mxGraphics = rDevice;
+ xView.set(getPeer(), css::uno::UNO_QUERY);
+ }
+ return !xView.is() || xView->setGraphics( rDevice );
+}
+
+Reference< XGraphics > UnoControl::getGraphics( )
+{
+ return mxGraphics;
+}
+
+awt::Size UnoControl::getSize( )
+{
+ ::osl::MutexGuard aGuard( GetMutex() );
+ return awt::Size( maComponentInfos.nWidth, maComponentInfos.nHeight );
+}
+
+void UnoControl::draw( sal_Int32 x, sal_Int32 y )
+{
+ Reference< XWindowPeer > xDrawPeer;
+ Reference< XView > xDrawPeerView;
+
+ bool bDisposeDrawPeer( false );
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+
+ xDrawPeer = ImplGetCompatiblePeer();
+ bDisposeDrawPeer = xDrawPeer.is() && ( xDrawPeer != getPeer() );
+
+ xDrawPeerView.set( xDrawPeer, UNO_QUERY );
+ DBG_ASSERT( xDrawPeerView.is(), "UnoControl::draw: no peer!" );
+ }
+
+ if ( xDrawPeerView.is() )
+ {
+ Reference< XVclWindowPeer > xWindowPeer;
+ xWindowPeer.set( xDrawPeer, UNO_QUERY );
+ if ( xWindowPeer.is() )
+ xWindowPeer->setDesignMode( mbDesignMode );
+ xDrawPeerView->draw( x, y );
+ }
+
+ if ( bDisposeDrawPeer )
+ xDrawPeer->dispose();
+}
+
+void UnoControl::setZoom( float fZoomX, float fZoomY )
+{
+ Reference< XView > xView;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+
+ maComponentInfos.nZoomX = fZoomX;
+ maComponentInfos.nZoomY = fZoomY;
+
+ xView.set(getPeer(), css::uno::UNO_QUERY);
+ }
+ if ( xView.is() )
+ xView->setZoom( fZoomX, fZoomY );
+}
+
+// XControl
+void UnoControl::setContext( const Reference< XInterface >& rxContext )
+{
+ ::osl::MutexGuard aGuard( GetMutex() );
+
+ mxContext = rxContext;
+}
+
+Reference< XInterface > UnoControl::getContext( )
+{
+ ::osl::MutexGuard aGuard( GetMutex() );
+
+ return mxContext;
+}
+
+void UnoControl::peerCreated()
+{
+ Reference< XWindow > xWindow( getPeer(), UNO_QUERY );
+ if ( !xWindow.is() )
+ return;
+
+ if ( maWindowListeners.getLength() )
+ xWindow->addWindowListener( &maWindowListeners );
+
+ if ( maFocusListeners.getLength() )
+ xWindow->addFocusListener( &maFocusListeners );
+
+ if ( maKeyListeners.getLength() )
+ xWindow->addKeyListener( &maKeyListeners );
+
+ if ( maMouseListeners.getLength() )
+ xWindow->addMouseListener( &maMouseListeners );
+
+ if ( maMouseMotionListeners.getLength() )
+ xWindow->addMouseMotionListener( &maMouseMotionListeners );
+
+ if ( maPaintListeners.getLength() )
+ xWindow->addPaintListener( &maPaintListeners );
+}
+
+void UnoControl::createPeer( const Reference< XToolkit >& rxToolkit, const Reference< XWindowPeer >& rParentPeer )
+{
+ ::osl::ClearableMutexGuard aGuard( GetMutex() );
+ if ( !mxModel.is() )
+ {
+ RuntimeException aException;
+ aException.Message = "createPeer: no model!";
+ aException.Context = static_cast<XAggregation*>(static_cast<cppu::OWeakAggObject*>(this));
+ throw aException;
+ }
+
+ if( getPeer().is() )
+ return;
+
+ mbCreatingPeer = true;
+
+ WindowClass eType;
+ Reference< XToolkit > xToolkit = rxToolkit;
+ if( rParentPeer.is() && mxContext.is() )
+ {
+ // no TopWindow
+ if ( !xToolkit.is() )
+ xToolkit = rParentPeer->getToolkit();
+ Any aAny = OWeakAggObject::queryInterface( cppu::UnoType<XControlContainer>::get());
+ Reference< XControlContainer > xC;
+ aAny >>= xC;
+ if( xC.is() )
+ // It's a container
+ eType = WindowClass_CONTAINER;
+ else
+ eType = WindowClass_SIMPLE;
+ }
+ else
+ { // This is only correct for Top Window
+ if( rParentPeer.is() )
+ {
+ if ( !xToolkit.is() )
+ xToolkit = rParentPeer->getToolkit();
+ eType = WindowClass_CONTAINER;
+ }
+ else
+ {
+ if ( !xToolkit.is() )
+ xToolkit = VCLUnoHelper::CreateToolkit();
+ eType = WindowClass_TOP;
+ }
+ }
+ WindowDescriptor aDescr;
+ aDescr.Type = eType;
+ aDescr.WindowServiceName = GetComponentServiceName();
+ aDescr.Parent = rParentPeer;
+ aDescr.Bounds = getPosSize();
+ aDescr.WindowAttributes = 0;
+
+ // Border
+ Reference< XPropertySet > xPSet( mxModel, UNO_QUERY );
+ Reference< XPropertySetInfo > xInfo = xPSet->getPropertySetInfo();
+
+ Any aVal;
+ OUString aPropName = GetPropertyName( BASEPROPERTY_BORDER );
+ if ( xInfo->hasPropertyByName( aPropName ) )
+ {
+ aVal = xPSet->getPropertyValue( aPropName );
+ sal_Int16 n = sal_Int16();
+ if ( aVal >>= n )
+ {
+ if ( n )
+ aDescr.WindowAttributes |= WindowAttribute::BORDER;
+ else
+ aDescr.WindowAttributes |= VclWindowPeerAttribute::NOBORDER;
+ }
+ }
+
+ // DESKTOP_AS_PARENT
+ if ( aDescr.Type == WindowClass_TOP )
+ {
+ aPropName = GetPropertyName( BASEPROPERTY_DESKTOP_AS_PARENT );
+ if ( xInfo->hasPropertyByName( aPropName ) )
+ {
+ aVal = xPSet->getPropertyValue( aPropName );
+ bool b = bool();
+ if ( ( aVal >>= b ) && b)
+ aDescr.ParentIndex = -1;
+ }
+ }
+ // Moveable
+ aPropName = GetPropertyName( BASEPROPERTY_MOVEABLE );
+ if ( xInfo->hasPropertyByName( aPropName ) )
+ {
+ aVal = xPSet->getPropertyValue( aPropName );
+ bool b = bool();
+ if ( ( aVal >>= b ) && b)
+ aDescr.WindowAttributes |= WindowAttribute::MOVEABLE;
+ }
+
+ // Sizeable
+ aPropName = GetPropertyName( BASEPROPERTY_SIZEABLE );
+ if ( xInfo->hasPropertyByName( aPropName ) )
+ {
+ aVal = xPSet->getPropertyValue( aPropName );
+ bool b = bool();
+ if ( ( aVal >>= b ) && b)
+ aDescr.WindowAttributes |= WindowAttribute::SIZEABLE;
+ }
+
+ // Closeable
+ aPropName = GetPropertyName( BASEPROPERTY_CLOSEABLE );
+ if ( xInfo->hasPropertyByName( aPropName ) )
+ {
+ aVal = xPSet->getPropertyValue( aPropName );
+ bool b = bool();
+ if ( ( aVal >>= b ) && b)
+ aDescr.WindowAttributes |= WindowAttribute::CLOSEABLE;
+ }
+
+ // Dropdown
+ aPropName = GetPropertyName( BASEPROPERTY_DROPDOWN );
+ if ( xInfo->hasPropertyByName( aPropName ) )
+ {
+ aVal = xPSet->getPropertyValue( aPropName );
+ bool b = bool();
+ if ( ( aVal >>= b ) && b)
+ aDescr.WindowAttributes |= VclWindowPeerAttribute::DROPDOWN;
+ }
+
+ // Spin
+ aPropName = GetPropertyName( BASEPROPERTY_SPIN );
+ if ( xInfo->hasPropertyByName( aPropName ) )
+ {
+ aVal = xPSet->getPropertyValue( aPropName );
+ bool b = bool();
+ if ( ( aVal >>= b ) && b)
+ aDescr.WindowAttributes |= VclWindowPeerAttribute::SPIN;
+ }
+
+ // HScroll
+ aPropName = GetPropertyName( BASEPROPERTY_HSCROLL );
+ if ( xInfo->hasPropertyByName( aPropName ) )
+ {
+ aVal = xPSet->getPropertyValue( aPropName );
+ bool b = bool();
+ if ( ( aVal >>= b ) && b)
+ aDescr.WindowAttributes |= VclWindowPeerAttribute::HSCROLL;
+ }
+
+ // VScroll
+ aPropName = GetPropertyName( BASEPROPERTY_VSCROLL );
+ if ( xInfo->hasPropertyByName( aPropName ) )
+ {
+ aVal = xPSet->getPropertyValue( aPropName );
+ bool b = bool();
+ if ( ( aVal >>= b ) && b)
+ aDescr.WindowAttributes |= VclWindowPeerAttribute::VSCROLL;
+ }
+
+ // AutoHScroll
+ aPropName = GetPropertyName( BASEPROPERTY_AUTOHSCROLL );
+ if ( xInfo->hasPropertyByName( aPropName ) )
+ {
+ aVal = xPSet->getPropertyValue( aPropName );
+ bool b = bool();
+ if ( ( aVal >>= b ) && b)
+ aDescr.WindowAttributes |= VclWindowPeerAttribute::AUTOHSCROLL;
+ }
+
+ // AutoVScroll
+ aPropName = GetPropertyName( BASEPROPERTY_AUTOVSCROLL );
+ if ( xInfo->hasPropertyByName( aPropName ) )
+ {
+ aVal = xPSet->getPropertyValue( aPropName );
+ bool b = bool();
+ if ( ( aVal >>= b ) && b)
+ aDescr.WindowAttributes |= VclWindowPeerAttribute::AUTOVSCROLL;
+ }
+
+ //added for issue79712
+ //NoLabel
+ aPropName = GetPropertyName( BASEPROPERTY_NOLABEL );
+ if ( xInfo->hasPropertyByName( aPropName ) )
+ {
+ aVal = xPSet->getPropertyValue( aPropName );
+ bool b = bool();
+ if ( ( aVal >>=b ) && b )
+ aDescr.WindowAttributes |= VclWindowPeerAttribute::NOLABEL;
+ }
+ //issue79712 ends
+
+ // Align
+ aPropName = GetPropertyName( BASEPROPERTY_ALIGN );
+ if ( xInfo->hasPropertyByName( aPropName ) )
+ {
+ aVal = xPSet->getPropertyValue( aPropName );
+ sal_Int16 n = sal_Int16();
+ if ( aVal >>= n )
+ {
+ if ( n == PROPERTY_ALIGN_LEFT )
+ aDescr.WindowAttributes |= VclWindowPeerAttribute::LEFT;
+ else if ( n == PROPERTY_ALIGN_CENTER )
+ aDescr.WindowAttributes |= VclWindowPeerAttribute::CENTER;
+ else
+ aDescr.WindowAttributes |= VclWindowPeerAttribute::RIGHT;
+ }
+ }
+
+ // Allow derivates to manipulate attributes
+ PrepareWindowDescriptor(aDescr);
+
+ // create the peer
+ setPeer( xToolkit->createWindow( aDescr ) );
+
+ // release the mutex guard (and work with copies of our members)
+ // this is necessary as our peer may lock the SolarMutex (actually, all currently known peers do), so calling
+ // into the peer with our own mutex locked may cause deadlocks
+ // (We _really_ need peers which do not use the SolarMutex. It's really pissing me off that from time to
+ // time deadlocks pop up because the low-level components like our peers use a mutex which usually
+ // is locked at the top of the stack (it protects the global message looping). This is always dangerous, and
+ // can not always be solved by tampering with other mutexes.
+ // Unfortunately, the VCL used in the peers is not threadsafe, and by definition needs a locked SolarMutex.)
+ // 82300 - 12/21/00 - FS
+ UnoControlComponentInfos aComponentInfos(maComponentInfos);
+ bool bDesignMode(mbDesignMode);
+
+ Reference< XGraphics > xGraphics( mxGraphics );
+ Reference< XView > xView ( getPeer(), UNO_QUERY_THROW );
+ Reference< XWindow > xWindow ( getPeer(), UNO_QUERY_THROW );
+
+ aGuard.clear();
+
+ // the updateFromModel is done without a locked mutex, too.
+ // The reason is that the only thing this method does is firing property changes, and this in general has
+ // to be done without locked mutexes (as every notification to external listeners).
+ // 82300 - 12/21/00 - FS
+ updateFromModel();
+
+ xView->setZoom( aComponentInfos.nZoomX, aComponentInfos.nZoomY );
+
+ setPosSize( aComponentInfos.nX, aComponentInfos.nY, aComponentInfos.nWidth, aComponentInfos.nHeight, aComponentInfos.nFlags );
+
+ if( aComponentInfos.bVisible && !bDesignMode )
+ // Show only after setting the data
+ xWindow->setVisible( aComponentInfos.bVisible );
+
+ if( !aComponentInfos.bEnable )
+ xWindow->setEnable( aComponentInfos.bEnable );
+
+ xView->setGraphics( xGraphics );
+
+ peerCreated();
+
+ mbCreatingPeer = false;
+
+}
+
+Reference< XWindowPeer > UnoControl::getPeer()
+{
+ ::osl::MutexGuard aGuard( GetMutex() );
+ return mxPeer;
+}
+
+sal_Bool UnoControl::setModel( const Reference< XControlModel >& rxModel )
+{
+ ::osl::MutexGuard aGuard( GetMutex() );
+
+ Reference< XMultiPropertySet > xPropSet( mxModel, UNO_QUERY );
+
+ // query for the XPropertiesChangeListener - our delegator is allowed to overwrite this interface
+ Reference< XPropertiesChangeListener > xListener;
+ queryInterface( cppu::UnoType<decltype(xListener)>::get() ) >>= xListener;
+
+ if( xPropSet.is() )
+ xPropSet->removePropertiesChangeListener( xListener );
+
+ mpData->bLocalizationSupport = false;
+ mxModel = rxModel;
+
+ if( mxModel.is() )
+ {
+ try
+ {
+ xPropSet.set( mxModel, UNO_QUERY_THROW );
+ Reference< XPropertySetInfo > xPSI( xPropSet->getPropertySetInfo(), UNO_SET_THROW );
+
+ Sequence< OUString> aNames = lcl_ImplGetPropertyNames( xPropSet );
+ xPropSet->addPropertiesChangeListener( aNames, xListener );
+
+ mpData->bLocalizationSupport = xPSI->hasPropertyByName("ResourceResolver");
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ mxModel.clear();
+ }
+ }
+
+ return mxModel.is();
+}
+
+Reference< XControlModel > UnoControl::getModel( )
+{
+ return mxModel;
+}
+
+Reference< XView > UnoControl::getView( )
+{
+ return static_cast< XView* >( this );
+}
+
+void UnoControl::setDesignMode( sal_Bool bOn )
+{
+ ModeChangeEvent aModeChangeEvent;
+
+ Reference< XWindow > xWindow;
+ Reference<XComponent> xAccessibleComp;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ if ( bool(bOn) == mbDesignMode )
+ return;
+
+ // remember this
+ mbDesignMode = bOn;
+ xWindow.set(getPeer(), css::uno::UNO_QUERY);
+
+ xAccessibleComp.set(maAccessibleContext, UNO_QUERY);
+ maAccessibleContext.clear();
+
+ aModeChangeEvent.Source = *this;
+ aModeChangeEvent.NewMode = mbDesignMode ? std::u16string_view(u"design") : std::u16string_view(u"alive" );
+ }
+
+ // dispose current AccessibleContext, if we have one - without Mutex lock
+ // (changing the design mode implies having a new implementation for this context,
+ // so the old one must be declared DEFUNC)
+ DisposeAccessibleContext(xAccessibleComp);
+
+ // adjust the visibility of our window
+ if ( xWindow.is() )
+ xWindow->setVisible( !bOn );
+
+ // and notify our mode listeners
+ maModeChangeListeners.notifyEach( &XModeChangeListener::modeChanged, aModeChangeEvent );
+}
+
+sal_Bool UnoControl::isDesignMode( )
+{
+ return mbDesignMode;
+}
+
+sal_Bool UnoControl::isTransparent( )
+{
+ return false;
+}
+
+// XServiceInfo
+OUString UnoControl::getImplementationName( )
+{
+ OSL_FAIL( "This method should be overridden!" );
+ return OUString();
+}
+
+sal_Bool UnoControl::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+Sequence< OUString > UnoControl::getSupportedServiceNames( )
+{
+ return { "com.sun.star.awt.UnoControl" };
+}
+
+
+Reference< XAccessibleContext > SAL_CALL UnoControl::getAccessibleContext( )
+{
+ // creation of the context will certainly require the SolarMutex ...
+ SolarMutexGuard aSolarGuard;
+ ::osl::MutexGuard aGuard( GetMutex() );
+
+ Reference< XAccessibleContext > xCurrentContext( maAccessibleContext.get(), UNO_QUERY );
+ if ( !xCurrentContext.is() )
+ {
+ if ( !mbDesignMode )
+ { // in alive mode, use the AccessibleContext of the peer
+ Reference< XAccessible > xPeerAcc( getPeer(), UNO_QUERY );
+ if ( xPeerAcc.is() )
+ xCurrentContext = xPeerAcc->getAccessibleContext( );
+ }
+ else
+ // in design mode, use a fallback
+ xCurrentContext = ::toolkit::OAccessibleControlContext::create( this );
+
+ DBG_ASSERT( xCurrentContext.is(), "UnoControl::getAccessibleContext: invalid context (invalid peer?)!" );
+ maAccessibleContext = xCurrentContext;
+
+ // get notified when the context is disposed
+ Reference< XComponent > xContextComp( xCurrentContext, UNO_QUERY );
+ if ( xContextComp.is() )
+ xContextComp->addEventListener( this );
+ // In an ideal world, this is not necessary - there the object would be released as soon as it has been
+ // disposed, and thus our weak reference would be empty, too.
+ // But 'til this ideal world comes (means 'til we do never have any refcount/lifetime bugs anymore), we
+ // need to listen for disposal and reset our weak reference then.
+ }
+
+ return xCurrentContext;
+}
+
+void SAL_CALL UnoControl::addModeChangeListener( const Reference< XModeChangeListener >& _rxListener )
+{
+ ::osl::MutexGuard aGuard( GetMutex() );
+ maModeChangeListeners.addInterface( _rxListener );
+}
+
+void SAL_CALL UnoControl::removeModeChangeListener( const Reference< XModeChangeListener >& _rxListener )
+{
+ ::osl::MutexGuard aGuard( GetMutex() );
+ maModeChangeListeners.removeInterface( _rxListener );
+}
+
+void SAL_CALL UnoControl::addModeChangeApproveListener( const Reference< XModeChangeApproveListener >& )
+{
+ throw NoSupportException( );
+}
+
+void SAL_CALL UnoControl::removeModeChangeApproveListener( const Reference< XModeChangeApproveListener >& )
+{
+ throw NoSupportException( );
+}
+
+
+awt::Point SAL_CALL UnoControl::convertPointToLogic( const awt::Point& i_Point, ::sal_Int16 i_TargetUnit )
+{
+ Reference< XUnitConversion > xPeerConversion;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ xPeerConversion.set(getPeer(), css::uno::UNO_QUERY);
+ }
+ if ( xPeerConversion.is() )
+ return xPeerConversion->convertPointToLogic( i_Point, i_TargetUnit );
+ return awt::Point( );
+}
+
+
+awt::Point SAL_CALL UnoControl::convertPointToPixel( const awt::Point& i_Point, ::sal_Int16 i_SourceUnit )
+{
+ Reference< XUnitConversion > xPeerConversion;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ xPeerConversion.set(getPeer(), css::uno::UNO_QUERY);
+ }
+ if ( xPeerConversion.is() )
+ return xPeerConversion->convertPointToPixel( i_Point, i_SourceUnit );
+ return awt::Point( );
+}
+
+
+awt::Size SAL_CALL UnoControl::convertSizeToLogic( const awt::Size& i_Size, ::sal_Int16 i_TargetUnit )
+{
+ Reference< XUnitConversion > xPeerConversion;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ xPeerConversion.set(getPeer(), css::uno::UNO_QUERY);
+ }
+ if ( xPeerConversion.is() )
+ return xPeerConversion->convertSizeToLogic( i_Size, i_TargetUnit );
+ return awt::Size( );
+}
+
+
+awt::Size SAL_CALL UnoControl::convertSizeToPixel( const awt::Size& i_Size, ::sal_Int16 i_SourceUnit )
+{
+ Reference< XUnitConversion > xPeerConversion;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ xPeerConversion.set(getPeer(), css::uno::UNO_QUERY);
+ }
+ if ( xPeerConversion.is() )
+ return xPeerConversion->convertSizeToPixel( i_Size, i_SourceUnit );
+ return awt::Size( );
+}
+
+
+uno::Reference< awt::XStyleSettings > SAL_CALL UnoControl::getStyleSettings()
+{
+ Reference< awt::XStyleSettingsSupplier > xPeerSupplier;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ xPeerSupplier.set(getPeer(), css::uno::UNO_QUERY);
+ }
+ if ( xPeerSupplier.is() )
+ return xPeerSupplier->getStyleSettings();
+ return nullptr;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/unocontrolbase.cxx b/toolkit/source/controls/unocontrolbase.cxx
new file mode 100644
index 000000000..69cfbac5d
--- /dev/null
+++ b/toolkit/source/controls/unocontrolbase.cxx
@@ -0,0 +1,253 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/awt/XLayoutConstrains.hpp>
+#include <com/sun/star/awt/XTextLayoutConstrains.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+
+#include <toolkit/controls/unocontrolbase.hxx>
+#include <toolkit/helper/property.hxx>
+
+#include <tools/debug.hxx>
+
+using namespace com::sun::star;
+
+
+
+
+bool UnoControlBase::ImplHasProperty( sal_uInt16 nPropId )
+{
+ const OUString& aPropName( GetPropertyName( nPropId ) );
+ return ImplHasProperty( aPropName );
+}
+
+bool UnoControlBase::ImplHasProperty( const OUString& aPropertyName )
+{
+ css::uno::Reference< css::beans::XPropertySet > xPSet( mxModel, css::uno::UNO_QUERY );
+ if ( !xPSet.is() )
+ return false;
+ css::uno::Reference< css::beans::XPropertySetInfo > xInfo = xPSet->getPropertySetInfo();
+ if ( !xInfo.is() )
+ return false;
+
+ return xInfo->hasPropertyByName( aPropertyName );
+}
+
+void UnoControlBase::ImplSetPropertyValues( const css::uno::Sequence< OUString >& aPropertyNames, const css::uno::Sequence< css::uno::Any >& aValues, bool bUpdateThis )
+{
+ css::uno::Reference< css::beans::XMultiPropertySet > xMPS( mxModel, css::uno::UNO_QUERY );
+ if ( !mxModel.is() )
+ return;
+
+ DBG_ASSERT( xMPS.is(), "UnoControlBase::ImplSetPropertyValues: no multi property set interface!" );
+ if ( !xMPS.is() )
+ return;
+
+ if ( !bUpdateThis )
+ ImplLockPropertyChangeNotifications( aPropertyNames, true );
+
+ try
+ {
+ xMPS->setPropertyValues( aPropertyNames, aValues );
+ }
+ catch( const css::uno::Exception& )
+ {
+ if ( !bUpdateThis )
+ ImplLockPropertyChangeNotifications( aPropertyNames, false );
+ }
+ if ( !bUpdateThis )
+ ImplLockPropertyChangeNotifications( aPropertyNames, false );
+}
+
+void UnoControlBase::ImplSetPropertyValue( const OUString& aPropertyName, const css::uno::Any& aValue, bool bUpdateThis )
+{
+ // Model might be logged off already but an event still fires
+ if ( !mxModel.is() )
+ return;
+
+ css::uno::Reference< css::beans::XPropertySet > xPSet( mxModel, css::uno::UNO_QUERY );
+ if ( !bUpdateThis )
+ ImplLockPropertyChangeNotification( aPropertyName, true );
+
+ try
+ {
+ xPSet->setPropertyValue( aPropertyName, aValue );
+ }
+ catch( const css::uno::Exception& )
+ {
+ if ( !bUpdateThis )
+ ImplLockPropertyChangeNotification( aPropertyName, false );
+ throw;
+ }
+ if ( !bUpdateThis )
+ ImplLockPropertyChangeNotification( aPropertyName, false );
+}
+
+css::uno::Any UnoControlBase::ImplGetPropertyValue( const OUString& aPropertyName ) const
+{
+ css::uno::Reference< css::beans::XPropertySet > xPSet( mxModel, css::uno::UNO_QUERY );
+ if ( xPSet.is() )
+ return xPSet->getPropertyValue( aPropertyName );
+ else
+ return css::uno::Any();
+}
+
+template <typename T> T UnoControlBase::ImplGetPropertyValuePOD( sal_uInt16 nProp )
+{
+ T t(0);
+ if ( mxModel.is() )
+ {
+ css::uno::Any aVal = ImplGetPropertyValue( GetPropertyName( nProp ) );
+ aVal >>= t;
+ }
+ return t;
+}
+
+template <typename T> T UnoControlBase::ImplGetPropertyValueClass( sal_uInt16 nProp )
+{
+ T t;
+ if ( mxModel.is() )
+ {
+ css::uno::Any aVal = ImplGetPropertyValue( GetPropertyName( nProp ) );
+ aVal >>= t;
+ }
+ return t;
+}
+
+bool UnoControlBase::ImplGetPropertyValue_BOOL( sal_uInt16 nProp )
+{
+ return ImplGetPropertyValuePOD<bool>(nProp);
+}
+
+sal_Int16 UnoControlBase::ImplGetPropertyValue_INT16( sal_uInt16 nProp )
+{
+ return ImplGetPropertyValuePOD<sal_Int16>(nProp);
+}
+
+sal_Int32 UnoControlBase::ImplGetPropertyValue_INT32( sal_uInt16 nProp )
+{
+ return ImplGetPropertyValuePOD<sal_Int32>(nProp);
+}
+
+double UnoControlBase::ImplGetPropertyValue_DOUBLE( sal_uInt16 nProp )
+{
+ return ImplGetPropertyValuePOD<double>(nProp);
+}
+
+OUString UnoControlBase::ImplGetPropertyValue_UString( sal_uInt16 nProp )
+{
+ return ImplGetPropertyValueClass<OUString>(nProp);
+}
+
+util::Date UnoControlBase::ImplGetPropertyValue_Date( sal_uInt16 nProp )
+{
+ return ImplGetPropertyValueClass<util::Date>(nProp);
+}
+
+util::Time UnoControlBase::ImplGetPropertyValue_Time( sal_uInt16 nProp )
+{
+ return ImplGetPropertyValueClass<util::Time>(nProp);
+}
+
+css::awt::Size UnoControlBase::Impl_getMinimumSize()
+{
+ css::awt::Size aSz;
+ css::uno::Reference< css::awt::XWindowPeer > xP = ImplGetCompatiblePeer();
+ DBG_ASSERT( xP.is(), "Layout: No Peer!" );
+ if ( xP.is() )
+ {
+ css::uno::Reference< css::awt::XLayoutConstrains > xL( xP, css::uno::UNO_QUERY );
+ if ( xL.is() )
+ aSz = xL->getMinimumSize();
+
+ if ( !getPeer().is() || ( getPeer() != xP ) )
+ xP->dispose();
+ }
+ return aSz;
+}
+
+css::awt::Size UnoControlBase::Impl_getPreferredSize()
+{
+ css::awt::Size aSz;
+ css::uno::Reference< css::awt::XWindowPeer > xP = ImplGetCompatiblePeer();
+ DBG_ASSERT( xP.is(), "Layout: No Peer!" );
+ if ( xP.is() )
+ {
+ css::uno::Reference< css::awt::XLayoutConstrains > xL( xP, css::uno::UNO_QUERY );
+ if ( xL.is() )
+ aSz = xL->getPreferredSize();
+
+ if ( !getPeer().is() || ( getPeer() != xP ) )
+ xP->dispose();
+ }
+ return aSz;
+}
+
+css::awt::Size UnoControlBase::Impl_calcAdjustedSize( const css::awt::Size& rNewSize )
+{
+ css::awt::Size aSz;
+ css::uno::Reference< css::awt::XWindowPeer > xP = ImplGetCompatiblePeer();
+ DBG_ASSERT( xP.is(), "Layout: No Peer!" );
+ if ( xP.is() )
+ {
+ css::uno::Reference< css::awt::XLayoutConstrains > xL( xP, css::uno::UNO_QUERY );
+ if ( xL.is() )
+ aSz = xL->calcAdjustedSize( rNewSize );
+
+ if ( !getPeer().is() || ( getPeer() != xP ) )
+ xP->dispose();
+ }
+ return aSz;
+}
+
+css::awt::Size UnoControlBase::Impl_getMinimumSize( sal_Int16 nCols, sal_Int16 nLines )
+{
+ css::awt::Size aSz;
+ css::uno::Reference< css::awt::XWindowPeer > xP = ImplGetCompatiblePeer();
+ DBG_ASSERT( xP.is(), "Layout: No Peer!" );
+ if ( xP.is() )
+ {
+ css::uno::Reference< css::awt::XTextLayoutConstrains > xL( xP, css::uno::UNO_QUERY );
+ if ( xL.is() )
+ aSz = xL->getMinimumSize( nCols, nLines );
+
+ if ( !getPeer().is() || ( getPeer() != xP ) )
+ xP->dispose();
+ }
+ return aSz;
+}
+
+void UnoControlBase::Impl_getColumnsAndLines( sal_Int16& nCols, sal_Int16& nLines )
+{
+ css::uno::Reference< css::awt::XWindowPeer > xP = ImplGetCompatiblePeer();
+ DBG_ASSERT( xP.is(), "Layout: No Peer!" );
+ if ( xP.is() )
+ {
+ css::uno::Reference< css::awt::XTextLayoutConstrains > xL( xP, css::uno::UNO_QUERY );
+ if ( xL.is() )
+ xL->getColumnsAndLines( nCols, nLines );
+
+ if ( !getPeer().is() || ( getPeer() != xP ) )
+ xP->dispose();
+ }
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/unocontrolcontainer.cxx b/toolkit/source/controls/unocontrolcontainer.cxx
new file mode 100644
index 000000000..806ec4863
--- /dev/null
+++ b/toolkit/source/controls/unocontrolcontainer.cxx
@@ -0,0 +1,822 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/awt/XVclContainerPeer.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyChangeListener.hpp>
+#include <com/sun/star/container/NoSuchElementException.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+#include <controls/unocontrolcontainer.hxx>
+#include <comphelper/sequence.hxx>
+
+#include <tools/debug.hxx>
+
+#include <limits>
+#include <map>
+#include <memory>
+#include <com/sun/star/awt/VclWindowPeerAttribute.hpp>
+
+using namespace ::com::sun::star;
+
+
+
+namespace {
+
+struct UnoControlHolder
+{
+ uno::Reference< awt::XControl > mxControl;
+ OUString msName;
+
+public:
+ UnoControlHolder( const OUString& rName, const uno::Reference< awt::XControl > & rControl )
+ : mxControl( rControl ),
+ msName( rName )
+ {
+ }
+
+ const OUString& getName() const { return msName; }
+ const uno::Reference< awt::XControl >& getControl() const { return mxControl; }
+};
+
+}
+
+class UnoControlHolderList
+{
+public:
+ typedef sal_Int32 ControlIdentifier;
+private:
+ typedef std::shared_ptr< UnoControlHolder > ControlInfo;
+ typedef ::std::map< ControlIdentifier, ControlInfo > ControlMap;
+
+private:
+ ControlMap maControls;
+
+public:
+ UnoControlHolderList();
+
+ /** adds a control with the given name to the list
+ @param _rxControl
+ the control to add. Must not be <NULL/>
+ @param _pBName
+ the name of the control, or <NULL/> if an automatic name should be generated
+ @return
+ the identifier of the newly added control
+ */
+ ControlIdentifier addControl( const uno::Reference< awt::XControl >& _rxControl, const OUString* _pName );
+
+ /** determines whether or not the list is empty
+ */
+ bool empty() const { return maControls.empty(); }
+
+ /** retrieves all controls currently in the list
+ */
+ void getControls( uno::Sequence< uno::Reference< awt::XControl > >& _out_rControls ) const;
+
+ /** retrieves all identifiers of all controls currently in the list
+ */
+ void getIdentifiers( uno::Sequence< sal_Int32 >& _out_rIdentifiers ) const;
+
+ /** returns the first control which is registered under the given name
+ */
+ uno::Reference< awt::XControl >
+ getControlForName( const OUString& _rName ) const;
+
+ /** returns the identifier which a control is registered for, or -1 if the control
+ isn't registered
+ */
+ ControlIdentifier
+ getControlIdentifier( const uno::Reference< awt::XControl >& _rxControl );
+
+ /** retrieves the control for a given id
+ @param _nIdentifier
+ the identifier for the control
+ @param _out_rxControl
+ takes the XControl upon successful return
+ @return
+ <TRUE/> if and only if a control with the given id is part of the list
+ */
+ bool getControlForIdentifier( ControlIdentifier _nIdentifier, uno::Reference< awt::XControl >& _out_rxControl ) const;
+
+ /** removes a control from the list, given by id
+ @param _nId
+ The identifier of the control to remove.
+ */
+ void removeControlById( ControlIdentifier _nId );
+
+ /** replaces a control from the list with another one
+ @param _nId
+ The identifier of the control to replace
+ @param _rxNewControl
+ the new control to put into the list
+ */
+ void replaceControlById( ControlIdentifier _nId, const uno::Reference< awt::XControl >& _rxNewControl );
+
+private:
+ /** adds a control
+ @param _rxControl
+ the control to add to the container
+ @param _pName
+ pointer to the name of the control. Might be <NULL/>, in this case, a name is generated.
+ @return
+ the identifier of the newly inserted control
+ */
+ ControlIdentifier impl_addControl(
+ const uno::Reference< awt::XControl >& _rxControl,
+ const OUString* _pName
+ );
+
+ /** finds a free identifier
+ @throw uno::RuntimeException
+ if no free identifier can be found
+ */
+ ControlIdentifier impl_getFreeIdentifier_throw();
+
+ /** finds a free name
+ @throw uno::RuntimeException
+ if no free name can be found
+ */
+ OUString impl_getFreeName_throw();
+};
+
+
+UnoControlHolderList::UnoControlHolderList()
+{
+}
+
+
+UnoControlHolderList::ControlIdentifier UnoControlHolderList::addControl( const uno::Reference< awt::XControl >& _rxControl, const OUString* _pName )
+{
+ return impl_addControl( _rxControl, _pName );
+}
+
+
+void UnoControlHolderList::getControls( uno::Sequence< uno::Reference< awt::XControl > >& _out_rControls ) const
+{
+ _out_rControls.realloc( maControls.size() );
+ uno::Reference< awt::XControl >* pControls = _out_rControls.getArray();
+ for (const auto& rEntry : maControls)
+ {
+ *pControls = rEntry.second->getControl();
+ ++pControls;
+ }
+}
+
+
+void UnoControlHolderList::getIdentifiers( uno::Sequence< sal_Int32 >& _out_rIdentifiers ) const
+{
+ _out_rIdentifiers.realloc( maControls.size() );
+ sal_Int32* pIdentifiers = _out_rIdentifiers.getArray();
+ for (const auto& rEntry : maControls)
+ {
+ *pIdentifiers = rEntry.first;
+ ++pIdentifiers;
+ }
+}
+
+
+uno::Reference< awt::XControl > UnoControlHolderList::getControlForName( const OUString& _rName ) const
+{
+ auto loop = std::find_if(maControls.begin(), maControls.end(),
+ [&_rName](const ControlMap::value_type& rEntry) { return rEntry.second->getName() == _rName; });
+ if (loop != maControls.end())
+ return loop->second->getControl();
+ return uno::Reference< awt::XControl >();
+}
+
+
+UnoControlHolderList::ControlIdentifier UnoControlHolderList::getControlIdentifier( const uno::Reference< awt::XControl >& _rxControl )
+{
+ auto loop = std::find_if(maControls.begin(), maControls.end(),
+ [&_rxControl](const ControlMap::value_type& rEntry) { return rEntry.second->getControl().get() == _rxControl.get(); });
+ if (loop != maControls.end())
+ return loop->first;
+ return -1;
+}
+
+
+bool UnoControlHolderList::getControlForIdentifier( UnoControlHolderList::ControlIdentifier _nIdentifier, uno::Reference< awt::XControl >& _out_rxControl ) const
+{
+ ControlMap::const_iterator pos = maControls.find( _nIdentifier );
+ if ( pos == maControls.end() )
+ return false;
+ _out_rxControl = pos->second->getControl();
+ return true;
+}
+
+
+void UnoControlHolderList::removeControlById( UnoControlHolderList::ControlIdentifier _nId )
+{
+ ControlMap::iterator pos = maControls.find( _nId );
+ DBG_ASSERT( pos != maControls.end(), "UnoControlHolderList::removeControlById: invalid id!" );
+ if ( pos == maControls.end() )
+ return;
+
+ maControls.erase( pos );
+}
+
+
+void UnoControlHolderList::replaceControlById( ControlIdentifier _nId, const uno::Reference< awt::XControl >& _rxNewControl )
+{
+ DBG_ASSERT( _rxNewControl.is(), "UnoControlHolderList::replaceControlById: invalid new control!" );
+
+ ControlMap::iterator pos = maControls.find( _nId );
+ DBG_ASSERT( pos != maControls.end(), "UnoControlHolderList::replaceControlById: invalid id!" );
+ if ( pos == maControls.end() )
+ return;
+
+ pos->second = std::make_shared<UnoControlHolder>( pos->second->getName(), _rxNewControl );
+}
+
+
+UnoControlHolderList::ControlIdentifier UnoControlHolderList::impl_addControl( const uno::Reference< awt::XControl >& _rxControl, const OUString* _pName )
+{
+ DBG_ASSERT( _rxControl.is(), "UnoControlHolderList::impl_addControl: invalid control!" );
+
+ OUString sName = _pName ? *_pName : impl_getFreeName_throw();
+ sal_Int32 nId = impl_getFreeIdentifier_throw();
+
+ maControls[ nId ] = std::make_shared<UnoControlHolder>( sName, _rxControl );
+ return nId;
+}
+
+
+UnoControlHolderList::ControlIdentifier UnoControlHolderList::impl_getFreeIdentifier_throw()
+{
+ for ( ControlIdentifier candidateId = 0; candidateId < ::std::numeric_limits< ControlIdentifier >::max(); ++candidateId )
+ {
+ ControlMap::const_iterator existent = maControls.find( candidateId );
+ if ( existent == maControls.end() )
+ return candidateId;
+ }
+ throw uno::RuntimeException("out of identifiers" );
+}
+
+
+OUString UnoControlHolderList::impl_getFreeName_throw()
+{
+ for ( ControlIdentifier candidateId = 0; candidateId < ::std::numeric_limits< ControlIdentifier >::max(); ++candidateId )
+ {
+ OUString candidateName( "control_" + OUString::number( candidateId ) );
+ if ( std::none_of(maControls.begin(), maControls.end(),
+ [&candidateName](const ControlMap::value_type& rEntry) { return rEntry.second->getName() == candidateName; }) )
+ return candidateName;
+ }
+ throw uno::RuntimeException("out of identifiers" );
+}
+
+// Function to set the controls' visibility according
+// to the dialog's "Step" property
+
+static void implUpdateVisibility
+(
+ sal_Int32 nDialogStep,
+ const uno::Reference< awt::XControlContainer >& xControlContainer
+)
+{
+ const uno::Sequence< uno::Reference< awt::XControl > >
+ aCtrls = xControlContainer->getControls();
+ bool bCompleteVisible = (nDialogStep == 0);
+ for( const uno::Reference< awt::XControl >& xControl : aCtrls )
+ {
+ bool bVisible = bCompleteVisible;
+ if( !bVisible )
+ {
+ uno::Reference< awt::XControlModel > xModel( xControl->getModel() );
+ uno::Reference< beans::XPropertySet > xPSet
+ ( xModel, uno::UNO_QUERY );
+ uno::Reference< beans::XPropertySetInfo >
+ xInfo = xPSet->getPropertySetInfo();
+ OUString aPropName( "Step" );
+ sal_Int32 nControlStep = 0;
+ if ( xInfo->hasPropertyByName( aPropName ) )
+ {
+ uno::Any aVal = xPSet->getPropertyValue( aPropName );
+ aVal >>= nControlStep;
+ }
+ bVisible = (nControlStep == 0) || (nControlStep == nDialogStep);
+ }
+
+ uno::Reference< awt::XWindow> xWindow
+ ( xControl, uno::UNO_QUERY );
+ if( xWindow.is() )
+ xWindow->setVisible( bVisible );
+ }
+}
+
+
+
+typedef ::cppu::WeakImplHelper< beans::XPropertyChangeListener > PropertyChangeListenerHelper;
+
+namespace {
+
+class DialogStepChangedListener: public PropertyChangeListenerHelper
+{
+private:
+ uno::Reference< awt::XControlContainer > mxControlContainer;
+
+public:
+ explicit DialogStepChangedListener( uno::Reference< awt::XControlContainer > const & xControlContainer )
+ : mxControlContainer( xControlContainer ) {}
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const lang::EventObject& Source ) override;
+
+ // XPropertyChangeListener
+ virtual void SAL_CALL propertyChange( const beans::PropertyChangeEvent& evt ) override;
+
+};
+
+}
+
+void SAL_CALL DialogStepChangedListener::disposing( const lang::EventObject& /*_rSource*/)
+{
+ mxControlContainer.clear();
+}
+
+void SAL_CALL DialogStepChangedListener::propertyChange( const beans::PropertyChangeEvent& evt )
+{
+ // evt.PropertyName HAS to be "Step" because we only use the listener for that
+ sal_Int32 nDialogStep = 0;
+ evt.NewValue >>= nDialogStep;
+ implUpdateVisibility( nDialogStep, mxControlContainer );
+}
+
+
+
+UnoControlContainer::UnoControlContainer()
+ :maCListeners( *this )
+{
+ mpControls.reset(new UnoControlHolderList);
+}
+
+UnoControlContainer::UnoControlContainer(const uno::Reference< awt::XWindowPeer >& xP )
+ :maCListeners( *this )
+{
+ setPeer( xP );
+ mbDisposePeer = false;
+ mpControls.reset(new UnoControlHolderList);
+}
+
+UnoControlContainer::~UnoControlContainer()
+{
+}
+
+void UnoControlContainer::ImplActivateTabControllers()
+{
+ for ( auto& rTabController : asNonConstRange(maTabControllers) )
+ {
+ rTabController->setContainer( this );
+ rTabController->activateTabOrder();
+ }
+}
+
+// lang::XComponent
+void UnoControlContainer::dispose( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ lang::EventObject aDisposeEvent;
+ aDisposeEvent.Source = static_cast< uno::XAggregation* >( this );
+
+ // Notify listeners about disposal of this Container (This is much faster if they
+ // listen on the controls and the container).
+ maDisposeListeners.disposeAndClear( aDisposeEvent );
+ maCListeners.disposeAndClear( aDisposeEvent );
+
+
+ const uno::Sequence< uno::Reference< awt::XControl > > aCtrls = getControls();
+
+ for( uno::Reference< awt::XControl > const & control : aCtrls )
+ {
+ removingControl( control );
+ // Delete control
+ control->dispose();
+ }
+
+
+ // Delete all structures
+ mpControls.reset(new UnoControlHolderList);
+
+ UnoControlBase::dispose();
+}
+
+// lang::XEventListener
+void UnoControlContainer::disposing( const lang::EventObject& _rEvt )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ uno::Reference< awt::XControl > xControl( _rEvt.Source, uno::UNO_QUERY );
+ if ( xControl.is() )
+ removeControl( xControl );
+
+ UnoControlBase::disposing( _rEvt );
+}
+
+// container::XContainer
+void UnoControlContainer::addContainerListener( const uno::Reference< container::XContainerListener >& rxListener )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ maCListeners.addInterface( rxListener );
+}
+
+void UnoControlContainer::removeContainerListener( const uno::Reference< container::XContainerListener >& rxListener )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ maCListeners.removeInterface( rxListener );
+}
+
+
+::sal_Int32 SAL_CALL UnoControlContainer::insert( const uno::Any& _rElement )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ uno::Reference< awt::XControl > xControl;
+ if ( !( _rElement >>= xControl ) || !xControl.is() )
+ throw lang::IllegalArgumentException(
+ "Elements must support the XControl interface.",
+ *this,
+ 1
+ );
+
+ return impl_addControl( xControl );
+}
+
+void SAL_CALL UnoControlContainer::removeByIdentifier( ::sal_Int32 _nIdentifier )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ uno::Reference< awt::XControl > xControl;
+ if ( !mpControls->getControlForIdentifier( _nIdentifier, xControl ) )
+ throw container::NoSuchElementException(
+ "There is no element with the given identifier.",
+ *this
+ );
+
+ impl_removeControl( _nIdentifier, xControl );
+}
+
+void SAL_CALL UnoControlContainer::replaceByIdentifer( ::sal_Int32 _nIdentifier, const uno::Any& _rElement )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ uno::Reference< awt::XControl > xExistentControl;
+ if ( !mpControls->getControlForIdentifier( _nIdentifier, xExistentControl ) )
+ throw container::NoSuchElementException(
+ "There is no element with the given identifier.",
+ *this
+ );
+
+ uno::Reference< awt::XControl > xNewControl;
+ if ( !( _rElement >>= xNewControl ) )
+ throw lang::IllegalArgumentException(
+ "Elements must support the XControl interface.",
+ *this,
+ 1
+ );
+
+ removingControl( xExistentControl );
+
+ mpControls->replaceControlById( _nIdentifier, xNewControl );
+
+ addingControl( xNewControl );
+
+ impl_createControlPeerIfNecessary( xNewControl );
+
+ if ( maCListeners.getLength() )
+ {
+ container::ContainerEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.Accessor <<= _nIdentifier;
+ aEvent.Element <<= xNewControl;
+ aEvent.ReplacedElement <<= xExistentControl;
+ maCListeners.elementReplaced( aEvent );
+ }
+}
+
+uno::Any SAL_CALL UnoControlContainer::getByIdentifier( ::sal_Int32 _nIdentifier )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ uno::Reference< awt::XControl > xControl;
+ if ( !mpControls->getControlForIdentifier( _nIdentifier, xControl ) )
+ throw container::NoSuchElementException();
+ return uno::Any( xControl );
+}
+
+uno::Sequence< ::sal_Int32 > SAL_CALL UnoControlContainer::getIdentifiers( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ uno::Sequence< ::sal_Int32 > aIdentifiers;
+ mpControls->getIdentifiers( aIdentifiers );
+ return aIdentifiers;
+}
+
+// container::XElementAccess
+uno::Type SAL_CALL UnoControlContainer::getElementType( )
+{
+ return cppu::UnoType<awt::XControlModel>::get();
+}
+
+sal_Bool SAL_CALL UnoControlContainer::hasElements( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+ return !mpControls->empty();
+}
+
+// awt::XControlContainer
+void UnoControlContainer::setStatusText( const OUString& rStatusText )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ // Descend the parent hierarchy
+ uno::Reference< awt::XControlContainer > xContainer( mxContext, uno::UNO_QUERY );
+ if( xContainer.is() )
+ xContainer->setStatusText( rStatusText );
+}
+
+uno::Sequence< uno::Reference< awt::XControl > > UnoControlContainer::getControls( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+ uno::Sequence< uno::Reference< awt::XControl > > aControls;
+ mpControls->getControls( aControls );
+ return aControls;
+}
+
+uno::Reference< awt::XControl > UnoControlContainer::getControl( const OUString& rName )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+ return mpControls->getControlForName( rName );
+}
+
+void UnoControlContainer::addingControl( const uno::Reference< awt::XControl >& _rxControl )
+{
+ if ( _rxControl.is() )
+ {
+ uno::Reference< uno::XInterface > xThis;
+ OWeakAggObject::queryInterface( cppu::UnoType<uno::XInterface>::get() ) >>= xThis;
+
+ _rxControl->setContext( xThis );
+ _rxControl->addEventListener( this );
+ }
+}
+
+void UnoControlContainer::impl_createControlPeerIfNecessary( const uno::Reference< awt::XControl >& _rxControl )
+{
+ OSL_PRECOND( _rxControl.is(), "UnoControlContainer::impl_createControlPeerIfNecessary: invalid control, this will crash!" );
+
+ // if the container already has a peer, then also create a peer for the control
+ uno::Reference< awt::XWindowPeer > xMyPeer( getPeer() );
+
+ if( xMyPeer.is() )
+ {
+ _rxControl->createPeer( nullptr, xMyPeer );
+ ImplActivateTabControllers();
+ }
+
+}
+
+sal_Int32 UnoControlContainer::impl_addControl( const uno::Reference< awt::XControl >& _rxControl, const OUString* _pName )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+ UnoControlHolderList::ControlIdentifier id = mpControls->addControl( _rxControl, _pName );
+
+ addingControl( _rxControl );
+
+ impl_createControlPeerIfNecessary( _rxControl );
+
+ if ( maCListeners.getLength() )
+ {
+ container::ContainerEvent aEvent;
+ aEvent.Source = *this;
+ if (_pName)
+ aEvent.Accessor <<= *_pName;
+ else
+ aEvent.Accessor <<= static_cast<sal_Int32>(id);
+ aEvent.Element <<= _rxControl;
+ maCListeners.elementInserted( aEvent );
+ }
+
+ return id;
+}
+
+void UnoControlContainer::addControl( const OUString& rName, const uno::Reference< awt::XControl >& rControl )
+{
+ if ( rControl.is() )
+ impl_addControl( rControl, &rName );
+}
+
+void UnoControlContainer::removingControl( const uno::Reference< awt::XControl >& _rxControl )
+{
+ if ( _rxControl.is() )
+ {
+ _rxControl->removeEventListener( this );
+ _rxControl->setContext( nullptr );
+ }
+}
+
+void UnoControlContainer::impl_removeControl( sal_Int32 _nId, const uno::Reference< awt::XControl >& _rxControl )
+{
+#ifdef DBG_UTIL
+ {
+ uno::Reference< awt::XControl > xControl;
+ bool bHas = mpControls->getControlForIdentifier( _nId, xControl );
+ DBG_ASSERT( bHas && xControl == _rxControl, "UnoControlContainer::impl_removeControl: inconsistency in the parameters!" );
+ }
+#endif
+ removingControl( _rxControl );
+
+ mpControls->removeControlById( _nId );
+
+ if ( maCListeners.getLength() )
+ {
+ container::ContainerEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.Accessor <<= _nId;
+ aEvent.Element <<= _rxControl;
+ maCListeners.elementRemoved( aEvent );
+ }
+}
+
+void UnoControlContainer::removeControl( const uno::Reference< awt::XControl >& _rxControl )
+{
+ if ( _rxControl.is() )
+ {
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ UnoControlHolderList::ControlIdentifier id = mpControls->getControlIdentifier( _rxControl );
+ if ( id != -1 )
+ impl_removeControl( id, _rxControl );
+ }
+}
+
+
+// awt::XUnoControlContainer
+void UnoControlContainer::setTabControllers( const uno::Sequence< uno::Reference< awt::XTabController > >& TabControllers )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ maTabControllers = TabControllers;
+}
+
+uno::Sequence< uno::Reference< awt::XTabController > > UnoControlContainer::getTabControllers( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ return maTabControllers;
+}
+
+void UnoControlContainer::addTabController( const uno::Reference< awt::XTabController >& TabController )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ sal_uInt32 nCount = maTabControllers.getLength();
+ maTabControllers.realloc( nCount + 1 );
+ maTabControllers.getArray()[ nCount ] = TabController;
+}
+
+void UnoControlContainer::removeTabController( const uno::Reference< awt::XTabController >& TabController )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ auto pTabController = std::find_if(std::cbegin(maTabControllers), std::cend(maTabControllers),
+ [&TabController](const uno::Reference< awt::XTabController >& rTabController) {
+ return rTabController.get() == TabController.get(); });
+ if (pTabController != std::cend(maTabControllers))
+ {
+ auto n = static_cast<sal_Int32>(std::distance(std::cbegin(maTabControllers), pTabController));
+ ::comphelper::removeElementAt( maTabControllers, n );
+ }
+}
+
+// awt::XControl
+void UnoControlContainer::createPeer( const uno::Reference< awt::XToolkit >& rxToolkit, const uno::Reference< awt::XWindowPeer >& rParent )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ if( getPeer().is() )
+ return;
+
+ bool bVis = maComponentInfos.bVisible;
+ if( bVis )
+ UnoControl::setVisible( false );
+
+ // Create a new peer
+ UnoControl::createPeer( rxToolkit, rParent );
+
+ // Create all children's peers
+ if ( !mbCreatingCompatiblePeer )
+ {
+ // Evaluate "Step" property
+ uno::Reference< awt::XControlModel > xModel( getModel() );
+ uno::Reference< beans::XPropertySet > xPSet
+ ( xModel, uno::UNO_QUERY );
+ uno::Reference< beans::XPropertySetInfo >
+ xInfo = xPSet->getPropertySetInfo();
+ OUString aPropName( "Step" );
+ if ( xInfo->hasPropertyByName( aPropName ) )
+ {
+ css::uno::Any aVal = xPSet->getPropertyValue( aPropName );
+ sal_Int32 nDialogStep = 0;
+ aVal >>= nDialogStep;
+ uno::Reference< awt::XControlContainer > xContainer =
+ static_cast< awt::XControlContainer* >(this);
+ implUpdateVisibility( nDialogStep, xContainer );
+
+ uno::Reference< beans::XPropertyChangeListener > xListener =
+ new DialogStepChangedListener(xContainer);
+ xPSet->addPropertyChangeListener( aPropName, xListener );
+ }
+
+ uno::Sequence< uno::Reference< awt::XControl > > aCtrls = getControls();
+ for( auto& rCtrl : asNonConstRange(aCtrls) )
+ rCtrl->createPeer( rxToolkit, getPeer() );
+
+ uno::Reference< awt::XVclContainerPeer > xC( getPeer(), uno::UNO_QUERY );
+ if ( xC.is() )
+ xC->enableDialogControl( true );
+ ImplActivateTabControllers();
+ }
+
+ if( bVis && !isDesignMode() )
+ UnoControl::setVisible( true );
+}
+
+
+// awt::XWindow
+void UnoControlContainer::setVisible( sal_Bool bVisible )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ UnoControl::setVisible( bVisible );
+ if( !mxContext.is() && bVisible )
+ // This is a Topwindow, thus show it automatically
+ createPeer( uno::Reference< awt::XToolkit > (), uno::Reference< awt::XWindowPeer > () );
+}
+
+OUString UnoControlContainer::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoControlContainer";
+}
+
+css::uno::Sequence<OUString> UnoControlContainer::getSupportedServiceNames()
+{
+ auto s(UnoControlBase::getSupportedServiceNames());
+ s.realloc(s.getLength() + 2);
+ auto ps = s.getArray();
+ ps[s.getLength() - 2] = "com.sun.star.awt.UnoControlContainer";
+ ps[s.getLength() - 1] = "stardiv.vcl.control.ControlContainer";
+ return s;
+}
+
+void UnoControlContainer::PrepareWindowDescriptor( css::awt::WindowDescriptor& rDesc )
+{
+ // HACK due to the fact that we can't really use VSCROLL & HSCROLL
+ // for Dialog ( css::awt::VclWindowPeerAttribute::VSCROLL
+ // has the same value as
+ // css::awt::WindowAttribute::NODECORATION )
+ // For convenience in the PropBrowse using HSCROLL and VSCROLL ensures
+ // the Correct text. We exchange them here and the control knows
+ // about this hack ( it sucks badly I know )
+ if ( rDesc.WindowAttributes & css::awt::VclWindowPeerAttribute::VSCROLL )
+ {
+ rDesc.WindowAttributes &= ~css::awt::VclWindowPeerAttribute::VSCROLL;
+ rDesc.WindowAttributes |= css::awt::VclWindowPeerAttribute::AUTOVSCROLL;
+ }
+ if ( rDesc.WindowAttributes & css::awt::VclWindowPeerAttribute::HSCROLL )
+ {
+ rDesc.WindowAttributes &= ~css::awt::VclWindowPeerAttribute::HSCROLL;
+ rDesc.WindowAttributes |= css::awt::VclWindowPeerAttribute::AUTOHSCROLL;
+ }
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlContainer_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoControlContainer());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/unocontrolcontainermodel.cxx b/toolkit/source/controls/unocontrolcontainermodel.cxx
new file mode 100644
index 000000000..ffcd520a4
--- /dev/null
+++ b/toolkit/source/controls/unocontrolcontainermodel.cxx
@@ -0,0 +1,93 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <controls/unocontrolcontainermodel.hxx>
+#include <toolkit/helper/property.hxx>
+
+#include <helper/unopropertyarrayhelper.hxx>
+
+
+UnoControlContainerModel::UnoControlContainerModel( const css::uno::Reference< css::uno::XComponentContext >& i_factory )
+ :UnoControlModel( i_factory )
+{
+ ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_BORDER );
+ ImplRegisterProperty( BASEPROPERTY_BORDERCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
+ ImplRegisterProperty( BASEPROPERTY_ENABLED );
+ ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
+ ImplRegisterProperty( BASEPROPERTY_HELPURL );
+ ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
+ ImplRegisterProperty( BASEPROPERTY_TEXT );
+}
+
+OUString UnoControlContainerModel::getServiceName()
+{
+ return "stardiv.vcl.controlmodel.ControlContainer";
+}
+
+OUString UnoControlContainerModel::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoControlContainerModel";
+}
+
+css::uno::Sequence<OUString>
+UnoControlContainerModel::getSupportedServiceNames()
+{
+ auto s(UnoControlModel::getSupportedServiceNames());
+ s.realloc(s.getLength() + 2);
+ auto ps = s.getArray();
+ ps[s.getLength() - 2] = "com.sun.star.awt.UnoControlContainerModel";
+ ps[s.getLength() - 1] = "stardiv.vcl.controlmodel.ControlContainer";
+ return s;
+}
+
+css::uno::Any UnoControlContainerModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ css::uno::Any aDefault;
+ if ( nPropId == BASEPROPERTY_BORDER )
+ aDefault <<= sal_Int16(0);
+ else
+ aDefault = UnoControlModel::ImplGetDefaultValue( nPropId );
+ return aDefault;
+}
+
+
+css::uno::Reference< css::beans::XPropertySetInfo > UnoControlContainerModel::getPropertySetInfo( )
+{
+ static css::uno::Reference< css::beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+::cppu::IPropertyArrayHelper& UnoControlContainerModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlContainerModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoControlContainerModel(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/unocontrolmodel.cxx b/toolkit/source/controls/unocontrolmodel.cxx
new file mode 100644
index 000000000..f28a0c0b4
--- /dev/null
+++ b/toolkit/source/controls/unocontrolmodel.cxx
@@ -0,0 +1,1388 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/beans/PropertyState.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/awt/FontDescriptor.hpp>
+#include <com/sun/star/awt/FontWidth.hpp>
+#include <com/sun/star/awt/FontSlant.hpp>
+#include <com/sun/star/awt/MouseWheelBehavior.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/awt/XDevice.hpp>
+#include <com/sun/star/text/WritingMode2.hpp>
+#include <com/sun/star/io/XMarkableStream.hpp>
+#include <com/sun/star/i18n/Currency2.hpp>
+#include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/util/Time.hpp>
+#include <toolkit/controls/unocontrolmodel.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <sal/log.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/debug.hxx>
+#include <tools/long.hxx>
+#include <toolkit/helper/property.hxx>
+#include <toolkit/helper/emptyfontdescriptor.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <unotools/configmgr.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/extract.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <vcl/unohelp.hxx>
+
+#include <memory>
+#include <o3tl/sorted_vector.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::i18n;
+using ::com::sun::star::awt::FontDescriptor;
+
+
+#define UNOCONTROL_STREAMVERSION short(2)
+
+static void lcl_ImplMergeFontProperty( FontDescriptor& rFD, sal_uInt16 nPropId, const Any& rValue )
+{
+ // some props are defined with other types than the matching FontDescriptor members have
+ // (e.g. FontWidth, FontSlant)
+ // 78474 - 09/19/2000 - FS
+ float nExtractFloat = 0;
+ sal_Int16 nExtractShort = 0;
+
+ switch ( nPropId )
+ {
+ case BASEPROPERTY_FONTDESCRIPTORPART_NAME: rValue >>= rFD.Name;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_STYLENAME: rValue >>= rFD.StyleName;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_FAMILY: rValue >>= rFD.Family;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_CHARSET: rValue >>= rFD.CharSet;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_HEIGHT: rValue >>= nExtractFloat; rFD.Height = static_cast<sal_Int16>(nExtractFloat);
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_WEIGHT: rValue >>= rFD.Weight;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_SLANT: if ( rValue >>= nExtractShort )
+ rFD.Slant = static_cast<css::awt::FontSlant>(nExtractShort);
+ else
+ rValue >>= rFD.Slant;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_UNDERLINE: rValue >>= rFD.Underline;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_STRIKEOUT: rValue >>= rFD.Strikeout;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_WIDTH: rValue >>= rFD.Width;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_PITCH: rValue >>= rFD.Pitch;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_CHARWIDTH: rValue >>= rFD.CharacterWidth;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_ORIENTATION: rValue >>= rFD.Orientation;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_KERNING: rValue >>= rFD.Kerning;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_WORDLINEMODE: rValue >>= rFD.WordLineMode;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_TYPE: rValue >>= rFD.Type;
+ break;
+ default: OSL_FAIL( "FontProperty?!" );
+ }
+}
+
+
+
+UnoControlModel::UnoControlModel( const Reference< XComponentContext >& rxContext )
+ :UnoControlModel_Base()
+ ,OPropertySetHelper( BrdcstHelper )
+ ,maDisposeListeners( *this )
+ ,m_xContext( rxContext )
+{
+ // Insert properties from Model into table,
+ // only existing properties are valid, even if they're VOID
+}
+
+UnoControlModel::UnoControlModel( const UnoControlModel& rModel )
+ : UnoControlModel_Base()
+ , OPropertySetHelper( BrdcstHelper )
+ , maData( rModel.maData )
+ , maDisposeListeners( *this )
+ , m_xContext( rModel.m_xContext )
+{
+}
+
+css::uno::Sequence<sal_Int32> UnoControlModel::ImplGetPropertyIds() const
+{
+ sal_uInt32 nIDs = maData.size();
+ css::uno::Sequence<sal_Int32> aIDs( nIDs );
+ sal_Int32* pIDs = aIDs.getArray();
+ sal_uInt32 n = 0;
+ for ( const auto& rData : maData )
+ pIDs[n++] = rData.first;
+ return aIDs;
+}
+
+bool UnoControlModel::ImplHasProperty( sal_uInt16 nPropId ) const
+{
+ if ( ( nPropId >= BASEPROPERTY_FONTDESCRIPTORPART_START ) && ( nPropId <= BASEPROPERTY_FONTDESCRIPTORPART_END ) )
+ nPropId = BASEPROPERTY_FONTDESCRIPTOR;
+
+ return maData.find( nPropId ) != maData.end();
+}
+
+css::uno::Any UnoControlModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ css::uno::Any aDefault;
+
+ if (
+ (nPropId == BASEPROPERTY_FONTDESCRIPTOR) ||
+ (
+ (nPropId >= BASEPROPERTY_FONTDESCRIPTORPART_START) &&
+ (nPropId <= BASEPROPERTY_FONTDESCRIPTORPART_END)
+ )
+ )
+ {
+ EmptyFontDescriptor aFD;
+ switch ( nPropId )
+ {
+ case BASEPROPERTY_FONTDESCRIPTOR: aDefault <<= aFD; break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_NAME: aDefault <<= aFD.Name; break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_STYLENAME: aDefault <<= aFD.StyleName; break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_FAMILY: aDefault <<= aFD.Family; break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_CHARSET: aDefault <<= aFD.CharSet; break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_HEIGHT: aDefault <<= static_cast<float>(aFD.Height); break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_WEIGHT: aDefault <<= aFD.Weight; break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_SLANT: aDefault <<= static_cast<sal_Int16>(aFD.Slant); break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_UNDERLINE: aDefault <<= aFD.Underline; break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_STRIKEOUT: aDefault <<= aFD.Strikeout; break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_WIDTH: aDefault <<= aFD.Width; break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_PITCH: aDefault <<= aFD.Pitch; break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_CHARWIDTH: aDefault <<= aFD.CharacterWidth; break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_ORIENTATION: aDefault <<= aFD.Orientation; break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_KERNING: aDefault <<= aFD.Kerning; break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_WORDLINEMODE: aDefault <<= aFD.WordLineMode; break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_TYPE: aDefault <<= aFD.Type; break;
+ default: OSL_FAIL( "FontProperty?!" );
+ }
+ }
+ else
+ {
+ switch ( nPropId )
+ {
+ case BASEPROPERTY_GRAPHIC:
+ aDefault <<= Reference< graphic::XGraphic >();
+ break;
+
+ case BASEPROPERTY_REFERENCE_DEVICE:
+ aDefault <<= Reference< awt::XDevice >();
+ break;
+
+ case BASEPROPERTY_ITEM_SEPARATOR_POS:
+ case BASEPROPERTY_VERTICALALIGN:
+ case BASEPROPERTY_BORDERCOLOR:
+ case BASEPROPERTY_SYMBOL_COLOR:
+ case BASEPROPERTY_TABSTOP:
+ case BASEPROPERTY_TEXTCOLOR:
+ case BASEPROPERTY_TEXTLINECOLOR:
+ case BASEPROPERTY_DATE:
+ case BASEPROPERTY_DATESHOWCENTURY:
+ case BASEPROPERTY_TIME:
+ case BASEPROPERTY_VALUE_DOUBLE:
+ case BASEPROPERTY_PROGRESSVALUE:
+ case BASEPROPERTY_SCROLLVALUE:
+ case BASEPROPERTY_VISIBLESIZE:
+ case BASEPROPERTY_BACKGROUNDCOLOR:
+ case BASEPROPERTY_FILLCOLOR: break; // Void
+
+ case BASEPROPERTY_FONTRELIEF:
+ case BASEPROPERTY_FONTEMPHASISMARK:
+ case BASEPROPERTY_MAXTEXTLEN:
+ case BASEPROPERTY_STATE:
+ case BASEPROPERTY_EXTDATEFORMAT:
+ case BASEPROPERTY_EXTTIMEFORMAT:
+ case BASEPROPERTY_ECHOCHAR: aDefault <<= sal_Int16(0); break;
+ case BASEPROPERTY_BORDER: aDefault <<= sal_Int16(1); break;
+ case BASEPROPERTY_DECIMALACCURACY: aDefault <<= sal_Int16(2); break;
+ case BASEPROPERTY_LINECOUNT: aDefault <<= sal_Int16(5); break;
+ case BASEPROPERTY_ALIGN: aDefault <<= sal_Int16(PROPERTY_ALIGN_LEFT); break;
+ case BASEPROPERTY_IMAGEALIGN: aDefault <<= sal_Int16(1) /*ImageAlign::Top*/; break;
+ case BASEPROPERTY_IMAGEPOSITION: aDefault <<= sal_Int16(12) /*ImagePosition::Centered*/; break;
+ case BASEPROPERTY_PUSHBUTTONTYPE: aDefault <<= sal_Int16(0) /*PushButtonType::STANDARD*/; break;
+ case BASEPROPERTY_MOUSE_WHEEL_BEHAVIOUR:aDefault <<= sal_Int16(awt::MouseWheelBehavior::SCROLL_FOCUS_ONLY); break;
+
+ case BASEPROPERTY_DATEMAX: aDefault <<= util::Date( 31, 12, 2200 ); break;
+ case BASEPROPERTY_DATEMIN: aDefault <<= util::Date( 1, 1, 1900 ); break;
+ case BASEPROPERTY_TIMEMAX: aDefault <<= util::Time(0, 0, 59, 23, false); break;
+ case BASEPROPERTY_TIMEMIN: aDefault <<= util::Time(); break;
+ case BASEPROPERTY_VALUEMAX_DOUBLE: aDefault <<= double(1000000); break;
+ case BASEPROPERTY_VALUEMIN_DOUBLE: aDefault <<= double(-1000000); break;
+ case BASEPROPERTY_VALUESTEP_DOUBLE: aDefault <<= double(1); break;
+ case BASEPROPERTY_PROGRESSVALUE_MAX: aDefault <<= sal_Int32(100); break;
+ case BASEPROPERTY_PROGRESSVALUE_MIN: aDefault <<= sal_Int32(0); break;
+ case BASEPROPERTY_SCROLLVALUE_MAX: aDefault <<= sal_Int32(100); break;
+ case BASEPROPERTY_SCROLLVALUE_MIN: aDefault <<= sal_Int32(0); break;
+ case BASEPROPERTY_LINEINCREMENT: aDefault <<= sal_Int32(1); break;
+ case BASEPROPERTY_BLOCKINCREMENT: aDefault <<= sal_Int32(10); break;
+ case BASEPROPERTY_ORIENTATION: aDefault <<= sal_Int32(0); break;
+ case BASEPROPERTY_SPINVALUE: aDefault <<= sal_Int32(0); break;
+ case BASEPROPERTY_SPININCREMENT: aDefault <<= sal_Int32(1); break;
+ case BASEPROPERTY_SPINVALUE_MIN: aDefault <<= sal_Int32(0); break;
+ case BASEPROPERTY_SPINVALUE_MAX: aDefault <<= sal_Int32(100); break;
+ case BASEPROPERTY_REPEAT_DELAY: aDefault <<= sal_Int32(50); break; // 50 milliseconds
+ case BASEPROPERTY_DEFAULTCONTROL: aDefault <<= const_cast<UnoControlModel*>(this)->getServiceName(); break;
+
+ case BASEPROPERTY_AUTOHSCROLL:
+ case BASEPROPERTY_AUTOVSCROLL:
+ case BASEPROPERTY_MOVEABLE:
+ case BASEPROPERTY_CLOSEABLE:
+ case BASEPROPERTY_SIZEABLE:
+ case BASEPROPERTY_HSCROLL:
+ case BASEPROPERTY_DEFAULTBUTTON:
+ case BASEPROPERTY_MULTILINE:
+ case BASEPROPERTY_MULTISELECTION:
+ case BASEPROPERTY_TRISTATE:
+ case BASEPROPERTY_DROPDOWN:
+ case BASEPROPERTY_SPIN:
+ case BASEPROPERTY_READONLY:
+ case BASEPROPERTY_VSCROLL:
+ case BASEPROPERTY_NUMSHOWTHOUSANDSEP:
+ case BASEPROPERTY_STRICTFORMAT:
+ case BASEPROPERTY_REPEAT:
+ case BASEPROPERTY_PAINTTRANSPARENT:
+ case BASEPROPERTY_DESKTOP_AS_PARENT:
+ case BASEPROPERTY_HARDLINEBREAKS:
+ case BASEPROPERTY_NOLABEL: aDefault <<= false; break;
+
+ case BASEPROPERTY_MULTISELECTION_SIMPLEMODE:
+ case BASEPROPERTY_HIDEINACTIVESELECTION:
+ case BASEPROPERTY_ENFORCE_FORMAT:
+ case BASEPROPERTY_AUTOCOMPLETE:
+ case BASEPROPERTY_SCALEIMAGE:
+ case BASEPROPERTY_ENABLED:
+ case BASEPROPERTY_PRINTABLE:
+ case BASEPROPERTY_ENABLEVISIBLE:
+ case BASEPROPERTY_DECORATION: aDefault <<= true; break;
+
+ case BASEPROPERTY_GROUPNAME:
+ case BASEPROPERTY_HELPTEXT:
+ case BASEPROPERTY_HELPURL:
+ case BASEPROPERTY_IMAGEURL:
+ case BASEPROPERTY_DIALOGSOURCEURL:
+ case BASEPROPERTY_EDITMASK:
+ case BASEPROPERTY_LITERALMASK:
+ case BASEPROPERTY_LABEL:
+ case BASEPROPERTY_TITLE:
+ case BASEPROPERTY_TEXT: aDefault <<= OUString(); break;
+
+ case BASEPROPERTY_WRITING_MODE:
+ case BASEPROPERTY_CONTEXT_WRITING_MODE:
+ aDefault <<= text::WritingMode2::CONTEXT;
+ break;
+
+ case BASEPROPERTY_STRINGITEMLIST:
+ {
+ css::uno::Sequence< OUString> aStringSeq;
+ aDefault <<= aStringSeq;
+
+ }
+ break;
+ case BASEPROPERTY_TYPEDITEMLIST:
+ {
+ css::uno::Sequence< css::uno::Any > aAnySeq;
+ aDefault <<= aAnySeq;
+
+ }
+ break;
+ case BASEPROPERTY_SELECTEDITEMS:
+ {
+ css::uno::Sequence<sal_Int16> aINT16Seq;
+ aDefault <<= aINT16Seq;
+ }
+ break;
+ case BASEPROPERTY_CURRENCYSYMBOL:
+ {
+ OUString sDefaultCurrency(
+ utl::ConfigManager::getDefaultCurrency() );
+
+ // extract the bank symbol
+ sal_Int32 nSepPos = sDefaultCurrency.indexOf( '-' );
+ OUString sBankSymbol;
+ if ( nSepPos >= 0 )
+ {
+ sBankSymbol = sDefaultCurrency.copy( 0, nSepPos );
+ sDefaultCurrency = sDefaultCurrency.copy( nSepPos + 1 );
+ }
+
+ // the remaining is the locale
+ LocaleDataWrapper aLocaleInfo( m_xContext, LanguageTag(sDefaultCurrency) );
+ if ( sBankSymbol.isEmpty() )
+ sBankSymbol = aLocaleInfo.getCurrBankSymbol();
+
+ // look for the currency entry (for this language) which has the given bank symbol
+ const Sequence< Currency2 > aAllCurrencies = aLocaleInfo.getAllCurrencies();
+
+ OUString sCurrencySymbol = aLocaleInfo.getCurrSymbol();
+ if ( sBankSymbol.isEmpty() )
+ {
+ DBG_ASSERT( aAllCurrencies.hasElements(), "UnoControlModel::ImplGetDefaultValue: no currencies at all!" );
+ if ( aAllCurrencies.hasElements() )
+ {
+ sBankSymbol = aAllCurrencies[0].BankSymbol;
+ sCurrencySymbol = aAllCurrencies[0].Symbol;
+ }
+ }
+
+ if ( !sBankSymbol.isEmpty() )
+ {
+ bool bLegacy = false;
+ bool bFound = false;
+ for ( const Currency2& rCurrency : aAllCurrencies )
+ if ( rCurrency.BankSymbol == sBankSymbol )
+ {
+ sCurrencySymbol = rCurrency.Symbol;
+ if ( rCurrency.LegacyOnly )
+ bLegacy = true;
+ else
+ {
+ bFound = true;
+ break;
+ }
+ }
+ DBG_ASSERT( bLegacy || bFound, "UnoControlModel::ImplGetDefaultValue: did not find the given bank symbol!" );
+ }
+
+ aDefault <<= sCurrencySymbol;
+ }
+ break;
+
+ default: OSL_FAIL( "ImplGetDefaultValue - unknown Property" );
+ }
+ }
+
+ return aDefault;
+}
+
+void UnoControlModel::ImplRegisterProperty( sal_uInt16 nPropId, const css::uno::Any& rDefault )
+{
+ maData[ nPropId ] = rDefault;
+}
+
+void UnoControlModel::ImplRegisterProperty( sal_uInt16 nPropId )
+{
+ ImplRegisterProperty( nPropId, ImplGetDefaultValue( nPropId ) );
+
+ if ( nPropId == BASEPROPERTY_FONTDESCRIPTOR )
+ {
+ // some properties are not included in the FontDescriptor, but every time
+ // when we have a FontDescriptor we want to have these properties too.
+ // => Easier to register the here, instead everywhere where I register the FontDescriptor...
+
+ ImplRegisterProperty( BASEPROPERTY_TEXTCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_TEXTLINECOLOR );
+ ImplRegisterProperty( BASEPROPERTY_FONTRELIEF );
+ ImplRegisterProperty( BASEPROPERTY_FONTEMPHASISMARK );
+ }
+}
+
+void UnoControlModel::ImplRegisterProperties( const std::vector< sal_uInt16 > &rIds )
+{
+ for (const auto& rId : rIds)
+ {
+ if( !ImplHasProperty( rId ) )
+ ImplRegisterProperty( rId, ImplGetDefaultValue( rId ) );
+ }
+}
+
+// css::uno::XInterface
+css::uno::Any UnoControlModel::queryAggregation( const css::uno::Type & rType )
+{
+ Any aRet = UnoControlModel_Base::queryAggregation( rType );
+ if ( !aRet.hasValue() )
+ aRet = ::cppu::OPropertySetHelper::queryInterface( rType );
+ return aRet;
+}
+
+// css::lang::XUnoTunnel
+
+const css::uno::Sequence< sal_Int8 >& UnoControlModel::getUnoTunnelId() noexcept
+{
+ static const comphelper::UnoIdInit theUnoControlModelUnoTunnelId;
+ return theUnoControlModelUnoTunnelId.getSeq();
+}
+
+sal_Int64 UnoControlModel::getSomething( const css::uno::Sequence< sal_Int8 >& rIdentifier )
+{
+ return comphelper::getSomethingImpl(rIdentifier, this);
+}
+
+// XInterface
+IMPLEMENT_FORWARD_REFCOUNT( UnoControlModel, UnoControlModel_Base )
+
+// css::lang::XTypeProvider
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( UnoControlModel, UnoControlModel_Base, ::cppu::OPropertySetHelper )
+
+
+uno::Reference< util::XCloneable > UnoControlModel::createClone()
+{
+ rtl::Reference<UnoControlModel> pClone = Clone();
+ return pClone;
+}
+
+// css::lang::XComponent
+void UnoControlModel::dispose( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ css::lang::EventObject aEvt;
+ aEvt.Source = static_cast<css::uno::XAggregation*>(static_cast<cppu::OWeakAggObject*>(this));
+ maDisposeListeners.disposeAndClear( aEvt );
+
+ BrdcstHelper.aLC.disposeAndClear( aEvt );
+
+ // let the property set helper notify our property listeners
+ OPropertySetHelper::disposing();
+}
+
+void UnoControlModel::addEventListener( const css::uno::Reference< css::lang::XEventListener >& rxListener )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ maDisposeListeners.addInterface( rxListener );
+}
+
+void UnoControlModel::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& rxListener )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ maDisposeListeners.removeInterface( rxListener );
+}
+
+
+// css::beans::XPropertyState
+css::beans::PropertyState UnoControlModel::getPropertyState( const OUString& PropertyName )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ sal_uInt16 nPropId = GetPropertyId( PropertyName );
+
+ css::uno::Any aValue = getPropertyValue( PropertyName );
+ css::uno::Any aDefault = ImplGetDefaultValue( nPropId );
+
+ return CompareProperties( aValue, aDefault ) ? css::beans::PropertyState_DEFAULT_VALUE : css::beans::PropertyState_DIRECT_VALUE;
+}
+
+css::uno::Sequence< css::beans::PropertyState > UnoControlModel::getPropertyStates( const css::uno::Sequence< OUString >& PropertyNames )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ sal_Int32 nNames = PropertyNames.getLength();
+
+ css::uno::Sequence< css::beans::PropertyState > aStates( nNames );
+
+ std::transform(PropertyNames.begin(), PropertyNames.end(), aStates.getArray(),
+ [this](const OUString& rName) -> css::beans::PropertyState { return getPropertyState(rName); });
+
+ return aStates;
+}
+
+void UnoControlModel::setPropertyToDefault( const OUString& PropertyName )
+{
+ Any aDefaultValue;
+ {
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+ aDefaultValue = ImplGetDefaultValue( GetPropertyId( PropertyName ) );
+ }
+ setPropertyValue( PropertyName, aDefaultValue );
+}
+
+css::uno::Any UnoControlModel::getPropertyDefault( const OUString& rPropertyName )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ return ImplGetDefaultValue( GetPropertyId( rPropertyName ) );
+}
+
+
+// css::io::XPersistObjec
+OUString UnoControlModel::getServiceName( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ OSL_FAIL( "ServiceName of UnoControlModel ?!" );
+ return OUString();
+}
+
+void UnoControlModel::write( const css::uno::Reference< css::io::XObjectOutputStream >& OutStream )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ css::uno::Reference< css::io::XMarkableStream > xMark( OutStream, css::uno::UNO_QUERY );
+ DBG_ASSERT( xMark.is(), "write: no css::io::XMarkableStream!" );
+
+ OutStream->writeShort( UNOCONTROL_STREAMVERSION );
+
+ o3tl::sorted_vector<sal_uInt16> aProps;
+
+ for (const auto& rData : maData)
+ {
+ if ( ( ( GetPropertyAttribs( rData.first ) & css::beans::PropertyAttribute::TRANSIENT ) == 0 )
+ && ( getPropertyState( GetPropertyName( rData.first ) ) != css::beans::PropertyState_DEFAULT_VALUE ) )
+ {
+ aProps.insert( rData.first );
+ }
+ }
+
+ sal_uInt32 nProps = aProps.size();
+
+ // Save FontProperty always in the old format (due to missing distinction
+ // between 5.0 and 5.1)
+ OutStream->writeLong( ( aProps.find( BASEPROPERTY_FONTDESCRIPTOR ) != aProps.end() ) ? ( nProps + 3 ) : nProps );
+ for ( const auto& rProp : aProps )
+ {
+ sal_Int32 nPropDataBeginMark = xMark->createMark();
+ OutStream->writeLong( 0 ); // DataLen
+
+ const css::uno::Any* pProp = &(maData[rProp]);
+ OutStream->writeShort( rProp );
+
+ bool bVoid = pProp->getValueType().getTypeClass() == css::uno::TypeClass_VOID;
+
+ OutStream->writeBoolean( bVoid );
+
+ if ( !bVoid )
+ {
+ const css::uno::Any& rValue = *pProp;
+ const css::uno::Type& rType = rValue.getValueType();
+
+ if ( rType == cppu::UnoType< bool >::get() )
+ {
+ bool b = false;
+ rValue >>= b;
+ OutStream->writeBoolean( b );
+ }
+ else if ( rType == ::cppu::UnoType< OUString >::get() )
+ {
+ OUString aUString;
+ rValue >>= aUString;
+ OutStream->writeUTF( aUString );
+ }
+ else if ( rType == ::cppu::UnoType< ::cppu::UnoUnsignedShortType >::get() )
+ {
+ sal_uInt16 n = 0;
+ rValue >>= n;
+ OutStream->writeShort( n );
+ }
+ else if ( rType == cppu::UnoType<sal_Int16>::get() )
+ {
+ sal_Int16 n = 0;
+ rValue >>= n;
+ OutStream->writeShort( n );
+ }
+ else if ( rType == cppu::UnoType<sal_uInt32>::get() )
+ {
+ sal_uInt32 n = 0;
+ rValue >>= n;
+ OutStream->writeLong( n );
+ }
+ else if ( rType == cppu::UnoType<sal_Int32>::get() )
+ {
+ sal_Int32 n = 0;
+ rValue >>= n;
+ OutStream->writeLong( n );
+ }
+ else if ( rType == cppu::UnoType<double>::get() )
+ {
+ double n = 0;
+ rValue >>= n;
+ OutStream->writeDouble( n );
+ }
+ else if ( rType == cppu::UnoType< css::awt::FontDescriptor >::get() )
+ {
+ css::awt::FontDescriptor aFD;
+ rValue >>= aFD;
+ OutStream->writeUTF( aFD.Name );
+ OutStream->writeShort( aFD.Height );
+ OutStream->writeShort( aFD.Width );
+ OutStream->writeUTF( aFD.StyleName );
+ OutStream->writeShort( aFD.Family );
+ OutStream->writeShort( aFD.CharSet );
+ OutStream->writeShort( aFD.Pitch );
+ OutStream->writeDouble( aFD.CharacterWidth );
+ OutStream->writeDouble( aFD.Weight );
+ OutStream->writeShort(
+ sal::static_int_cast< sal_Int16 >(aFD.Slant) );
+ OutStream->writeShort( aFD.Underline );
+ OutStream->writeShort( aFD.Strikeout );
+ OutStream->writeDouble( aFD.Orientation );
+ OutStream->writeBoolean( aFD.Kerning );
+ OutStream->writeBoolean( aFD.WordLineMode );
+ OutStream->writeShort( aFD.Type );
+ }
+ else if ( rType == cppu::UnoType<css::util::Date>::get() )
+ {
+ css::util::Date d;
+ rValue >>= d;
+ OutStream->writeLong(d.Day + 100 * d.Month + 10000 * d.Year);
+ // YYYYMMDD
+ }
+ else if ( rType == cppu::UnoType<css::util::Time>::get() )
+ {
+ css::util::Time t;
+ rValue >>= t;
+ OutStream->writeLong(
+ t.NanoSeconds / 1000000 + 100 * t.Seconds
+ + 10000 * t.Minutes + 1000000 * t.Hours); // HHMMSShh
+ }
+ else if ( rType == cppu::UnoType< css::uno::Sequence< OUString> >::get() )
+ {
+ css::uno::Sequence< OUString> aSeq;
+ rValue >>= aSeq;
+ tools::Long nEntries = aSeq.getLength();
+ OutStream->writeLong( nEntries );
+ for ( const auto& rVal : std::as_const(aSeq) )
+ OutStream->writeUTF( rVal );
+ }
+ else if ( rType == cppu::UnoType< cppu::UnoSequenceType<cppu::UnoUnsignedShortType> >::get() )
+ {
+ css::uno::Sequence<sal_uInt16> aSeq;
+ rValue >>= aSeq;
+ tools::Long nEntries = aSeq.getLength();
+ OutStream->writeLong( nEntries );
+ for ( const auto nVal : std::as_const(aSeq) )
+ OutStream->writeShort( nVal );
+ }
+ else if ( rType == cppu::UnoType< css::uno::Sequence<sal_Int16> >::get() )
+ {
+ css::uno::Sequence<sal_Int16> aSeq;
+ rValue >>= aSeq;
+ tools::Long nEntries = aSeq.getLength();
+ OutStream->writeLong( nEntries );
+ for ( const auto nVal : std::as_const(aSeq) )
+ OutStream->writeShort( nVal );
+ }
+ else if ( rType.getTypeClass() == TypeClass_ENUM )
+ {
+ sal_Int32 nAsInt = 0;
+ ::cppu::enum2int( nAsInt, rValue );
+ OutStream->writeLong( nAsInt );
+ }
+#if OSL_DEBUG_LEVEL > 0
+ else
+ {
+ SAL_WARN( "toolkit", "UnoControlModel::write: don't know how to handle a property of type '"
+ << rType.getTypeName()
+ << "'.\n(Currently handling property '"
+ << GetPropertyName( rProp )
+ << "'.)");
+ }
+#endif
+ }
+
+ sal_Int32 nPropDataLen = xMark->offsetToMark( nPropDataBeginMark );
+ xMark->jumpToMark( nPropDataBeginMark );
+ OutStream->writeLong( nPropDataLen );
+ xMark->jumpToFurthest();
+ xMark->deleteMark(nPropDataBeginMark);
+ }
+
+ if ( aProps.find( BASEPROPERTY_FONTDESCRIPTOR ) == aProps.end() )
+ return;
+
+ const css::uno::Any* pProp = &maData[ BASEPROPERTY_FONTDESCRIPTOR ];
+ // Until 5.0 export arrives, write old format...
+ css::awt::FontDescriptor aFD;
+ (*pProp) >>= aFD;
+
+ for ( sal_uInt16 n = BASEPROPERTY_FONT_TYPE; n <= BASEPROPERTY_FONT_ATTRIBS; n++ )
+ {
+ sal_Int32 nPropDataBeginMark = xMark->createMark();
+ OutStream->writeLong( 0 ); // DataLen
+ OutStream->writeShort( n ); // PropId
+ OutStream->writeBoolean( false ); // Void
+
+ if ( n == BASEPROPERTY_FONT_TYPE )
+ {
+ OutStream->writeUTF( aFD.Name );
+ OutStream->writeUTF( aFD.StyleName );
+ OutStream->writeShort( aFD.Family );
+ OutStream->writeShort( aFD.CharSet );
+ OutStream->writeShort( aFD.Pitch );
+ }
+ else if ( n == BASEPROPERTY_FONT_SIZE )
+ {
+ OutStream->writeLong( aFD.Width );
+ OutStream->writeLong( aFD.Height );
+ OutStream->writeShort(
+ sal::static_int_cast< sal_Int16 >(
+ vcl::unohelper::ConvertFontWidth(aFD.CharacterWidth)) );
+ }
+ else if ( n == BASEPROPERTY_FONT_ATTRIBS )
+ {
+ OutStream->writeShort(
+ sal::static_int_cast< sal_Int16 >(
+ vcl::unohelper::ConvertFontWeight(aFD.Weight)) );
+ OutStream->writeShort(
+ sal::static_int_cast< sal_Int16 >(aFD.Slant) );
+ OutStream->writeShort( aFD.Underline );
+ OutStream->writeShort( aFD.Strikeout );
+ OutStream->writeShort( static_cast<short>(aFD.Orientation * 10) );
+ OutStream->writeBoolean( aFD.Kerning );
+ OutStream->writeBoolean( aFD.WordLineMode );
+ }
+ else
+ {
+ OSL_FAIL( "Property?!" );
+ }
+
+ sal_Int32 nPropDataLen = xMark->offsetToMark( nPropDataBeginMark );
+ xMark->jumpToMark( nPropDataBeginMark );
+ OutStream->writeLong( nPropDataLen );
+ xMark->jumpToFurthest();
+ xMark->deleteMark(nPropDataBeginMark);
+ }
+}
+
+void UnoControlModel::read( const css::uno::Reference< css::io::XObjectInputStream >& InStream )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ css::uno::Reference< css::io::XMarkableStream > xMark( InStream, css::uno::UNO_QUERY );
+ DBG_ASSERT( xMark.is(), "read: no css::io::XMarkableStream!" );
+
+ short nVersion = InStream->readShort();
+ sal_uInt32 nProps = static_cast<sal_uInt32>(InStream->readLong());
+ css::uno::Sequence< OUString> aProps( nProps );
+ css::uno::Sequence< css::uno::Any> aValues( nProps );
+ bool bInvalidEntries = false;
+
+ // Unfortunately, there's no mark for the whole block, thus only properties may be changed.
+ // No data for the model may be added following the properties
+
+ // Used for import of old parts in css::awt::FontDescriptor
+ std::unique_ptr<css::awt::FontDescriptor> pFD;
+
+ for ( sal_uInt32 i = 0; i < nProps; i++ )
+ {
+ sal_Int32 nPropDataBeginMark = xMark->createMark();
+ sal_Int32 nPropDataLen = InStream->readLong();
+
+ sal_uInt16 nPropId = static_cast<sal_uInt16>(InStream->readShort());
+
+ css::uno::Any aValue;
+ bool bIsVoid = InStream->readBoolean();
+ if ( !bIsVoid )
+ {
+ if ( maData.find( nPropId ) != maData.end() )
+ {
+ const css::uno::Type* pType = GetPropertyType( nPropId );
+ if ( *pType == cppu::UnoType<bool>::get() )
+ {
+ bool b = InStream->readBoolean();
+ aValue <<= b;
+ }
+ else if ( *pType == cppu::UnoType<OUString>::get() )
+ {
+ OUString aUTF = InStream->readUTF();
+ aValue <<= aUTF;
+ }
+ else if ( *pType == ::cppu::UnoType< ::cppu::UnoUnsignedShortType >::get() )
+ {
+ sal_uInt16 n = InStream->readShort();
+ aValue <<= n;
+ }
+ else if ( *pType == cppu::UnoType<sal_Int16>::get() )
+ {
+ sal_Int16 n = InStream->readShort();
+ aValue <<= n;
+ }
+ else if ( *pType == cppu::UnoType<sal_uInt32>::get() )
+ {
+ sal_uInt32 n = InStream->readLong();
+ aValue <<= n;
+ }
+ else if ( *pType == cppu::UnoType<sal_Int32>::get() )
+ {
+ sal_Int32 n = InStream->readLong();
+ aValue <<= n;
+ }
+ else if ( *pType == cppu::UnoType<double>::get() )
+ {
+ double n = InStream->readDouble();
+ aValue <<= n;
+ }
+ else if ( *pType == cppu::UnoType< css::awt::FontDescriptor >::get() )
+ {
+ css::awt::FontDescriptor aFD;
+ aFD.Name = InStream->readUTF();
+ aFD.Height = InStream->readShort();
+ aFD.Width = InStream->readShort();
+ aFD.StyleName = InStream->readUTF();
+ aFD.Family = InStream->readShort();
+ aFD.CharSet = InStream->readShort();
+ aFD.Pitch = InStream->readShort();
+ aFD.CharacterWidth = static_cast<float>(InStream->readDouble());
+ aFD.Weight = static_cast<float>(InStream->readDouble());
+ aFD.Slant = static_cast<css::awt::FontSlant>(InStream->readShort());
+ aFD.Underline = InStream->readShort();
+ aFD.Strikeout = InStream->readShort();
+ aFD.Orientation = static_cast<float>(InStream->readDouble());
+ aFD.Kerning = InStream->readBoolean() != 0;
+ aFD.WordLineMode = InStream->readBoolean() != 0;
+ aFD.Type = InStream->readShort();
+ aValue <<= aFD;
+ }
+ else if ( *pType == cppu::UnoType<css::util::Date>::get() )
+ {
+ sal_Int32 n = InStream->readLong(); // YYYYMMDD
+ aValue <<= css::util::Date(
+ n % 100, (n / 100) % 100, n / 10000);
+ }
+ else if ( *pType == cppu::UnoType<css::util::Time>::get() )
+ {
+ sal_Int32 n = InStream->readLong(); // HHMMSShh
+ aValue <<= css::util::Time(
+ (n % 100) * 1000000, (n / 100) % 100, (n / 10000) % 100,
+ n / 1000000, false);
+ }
+ else if ( *pType == cppu::UnoType< css::uno::Sequence< OUString> >::get() )
+ {
+ tools::Long nEntries = InStream->readLong();
+ css::uno::Sequence< OUString> aSeq( nEntries );
+ for ( tools::Long n = 0; n < nEntries; n++ )
+ aSeq.getArray()[n] = InStream->readUTF();
+ aValue <<= aSeq;
+
+ }
+ else if ( *pType == cppu::UnoType< cppu::UnoSequenceType<cppu::UnoUnsignedShortType> >::get() )
+
+ {
+ tools::Long nEntries = InStream->readLong();
+ css::uno::Sequence<sal_uInt16> aSeq( nEntries );
+ for ( tools::Long n = 0; n < nEntries; n++ )
+ aSeq.getArray()[n] = static_cast<sal_uInt16>(InStream->readShort());
+ aValue <<= aSeq;
+ }
+ else if ( *pType == cppu::UnoType< css::uno::Sequence<sal_Int16> >::get() )
+ {
+ tools::Long nEntries = InStream->readLong();
+ css::uno::Sequence<sal_Int16> aSeq( nEntries );
+ for ( tools::Long n = 0; n < nEntries; n++ )
+ aSeq.getArray()[n] = InStream->readShort();
+ aValue <<= aSeq;
+ }
+ else if ( pType->getTypeClass() == TypeClass_ENUM )
+ {
+ sal_Int32 nAsInt = InStream->readLong();
+ aValue = ::cppu::int2enum( nAsInt, *pType );
+ }
+ else
+ {
+ SAL_WARN( "toolkit", "UnoControlModel::read: don't know how to handle a property of type '"
+ << pType->getTypeName()
+ << "'.\n(Currently handling property '"
+ << GetPropertyName( nPropId )
+ << "'.)");
+ }
+ }
+ else
+ {
+ // Old trash from 5.0
+ if ( nPropId == BASEPROPERTY_FONT_TYPE )
+ {
+ // Redundant information for older versions
+ // is skipped by MarkableStream
+ if ( nVersion < 2 )
+ {
+ if ( !pFD )
+ {
+ pFD.reset(new css::awt::FontDescriptor);
+ if ( maData.find( BASEPROPERTY_FONTDESCRIPTOR ) != maData.end() ) // due to defaults...
+ maData[ BASEPROPERTY_FONTDESCRIPTOR ] >>= *pFD;
+ }
+ pFD->Name = InStream->readUTF();
+ pFD->StyleName = InStream->readUTF();
+ pFD->Family = InStream->readShort();
+ pFD->CharSet = InStream->readShort();
+ pFD->Pitch = InStream->readShort();
+ }
+ }
+ else if ( nPropId == BASEPROPERTY_FONT_SIZE )
+ {
+ if ( nVersion < 2 )
+ {
+ if ( !pFD )
+ {
+ pFD.reset(new css::awt::FontDescriptor);
+ if ( maData.find(BASEPROPERTY_FONTDESCRIPTOR) != maData.end() ) // due to defaults...
+ maData[BASEPROPERTY_FONTDESCRIPTOR] >>= *pFD;
+ }
+ pFD->Width = static_cast<sal_Int16>(InStream->readLong());
+ pFD->Height = static_cast<sal_Int16>(InStream->readLong());
+ InStream->readShort(); // ignore css::awt::FontWidth - it was
+ // misspelled and is no longer needed
+ pFD->CharacterWidth = css::awt::FontWidth::DONTKNOW;
+ }
+ }
+ else if ( nPropId == BASEPROPERTY_FONT_ATTRIBS )
+ {
+ if ( nVersion < 2 )
+ {
+ if ( !pFD )
+ {
+ pFD.reset(new css::awt::FontDescriptor);
+ if ( maData.find(BASEPROPERTY_FONTDESCRIPTOR) != maData.end() ) // due to defaults...
+ maData[BASEPROPERTY_FONTDESCRIPTOR] >>= *pFD;
+ }
+ pFD->Weight = vcl::unohelper::ConvertFontWeight(static_cast<FontWeight>(InStream->readShort()));
+ pFD->Slant = static_cast<css::awt::FontSlant>(InStream->readShort());
+ pFD->Underline = InStream->readShort();
+ pFD->Strikeout = InStream->readShort();
+ pFD->Orientation = static_cast<float>(static_cast<double>(InStream->readShort())) / 10;
+ pFD->Kerning = InStream->readBoolean() != 0;
+ pFD->WordLineMode = InStream->readBoolean() != 0;
+ }
+ }
+ else
+ {
+ OSL_FAIL( "read: unknown Property!" );
+ }
+ }
+ }
+ else // bVoid
+ {
+ if ( nPropId == BASEPROPERTY_FONTDESCRIPTOR )
+ {
+ EmptyFontDescriptor aFD;
+ aValue <<= aFD;
+ }
+ }
+
+ if ( maData.find( nPropId ) != maData.end() )
+ {
+ aProps.getArray()[i] = GetPropertyName( nPropId );
+ aValues.getArray()[i] = aValue;
+ }
+ else
+ {
+ bInvalidEntries = true;
+ }
+
+ // Skip rest of input if there is more data in stream than this version can handle
+ xMark->jumpToMark( nPropDataBeginMark );
+ InStream->skipBytes( nPropDataLen );
+ xMark->deleteMark(nPropDataBeginMark);
+ }
+ if ( bInvalidEntries )
+ {
+ for ( sal_Int32 i = 0; i < aProps.getLength(); i++ )
+ {
+ if ( aProps.getConstArray()[i].isEmpty() )
+ {
+ ::comphelper::removeElementAt( aProps, i );
+ ::comphelper::removeElementAt( aValues, i );
+ i--;
+ }
+ }
+ }
+
+ try
+ {
+ setPropertyValues( aProps, aValues );
+ }
+ catch ( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+
+ if ( pFD )
+ {
+ css::uno::Any aValue;
+ aValue <<= *pFD;
+ setPropertyValue( GetPropertyName( BASEPROPERTY_FONTDESCRIPTOR ), aValue );
+ }
+}
+
+
+// css::lang::XServiceInfo
+OUString UnoControlModel::getImplementationName( )
+{
+ OSL_FAIL( "This method should be overridden!" );
+ return OUString();
+
+}
+
+sal_Bool UnoControlModel::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > UnoControlModel::getSupportedServiceNames( )
+{
+ return { "com.sun.star.awt.UnoControlModel" };
+}
+
+sal_Bool UnoControlModel::convertFastPropertyValue( Any & rConvertedValue, Any & rOldValue, sal_Int32 nPropId, const Any& rValue )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ bool bVoid = rValue.getValueType().getTypeClass() == css::uno::TypeClass_VOID;
+ if ( bVoid )
+ {
+ rConvertedValue.clear();
+ }
+ else
+ {
+ const css::uno::Type* pDestType = GetPropertyType( static_cast<sal_uInt16>(nPropId) );
+ if ( pDestType->getTypeClass() == TypeClass_ANY )
+ {
+ rConvertedValue = rValue;
+ }
+ else
+ {
+ if ( pDestType->equals( rValue.getValueType() ) )
+ {
+ rConvertedValue = rValue;
+ }
+ else
+ {
+ bool bConverted = false;
+ // 13.03.2001 - 84923 - frank.schoenheit@germany.sun.com
+
+ switch (pDestType->getTypeClass())
+ {
+ case TypeClass_DOUBLE:
+ {
+ // try as double
+ double nAsDouble = 0;
+ bConverted = ( rValue >>= nAsDouble );
+ if ( bConverted )
+ rConvertedValue <<= nAsDouble;
+ else
+ { // try as integer
+ sal_Int32 nAsInteger = 0;
+ bConverted = ( rValue >>= nAsInteger );
+ if ( bConverted )
+ rConvertedValue <<= static_cast<double>(nAsInteger);
+ }
+ }
+ break;
+ case TypeClass_SHORT:
+ {
+ sal_Int16 n;
+ bConverted = ( rValue >>= n );
+ if ( bConverted )
+ rConvertedValue <<= n;
+ }
+ break;
+ case TypeClass_UNSIGNED_SHORT:
+ {
+ sal_uInt16 n;
+ bConverted = ( rValue >>= n );
+ if ( bConverted )
+ rConvertedValue <<= n;
+ }
+ break;
+ case TypeClass_LONG:
+ {
+ sal_Int32 n;
+ bConverted = ( rValue >>= n );
+ if ( bConverted )
+ rConvertedValue <<= n;
+ }
+ break;
+ case TypeClass_UNSIGNED_LONG:
+ {
+ sal_uInt32 n;
+ bConverted = ( rValue >>= n );
+ if ( bConverted )
+ rConvertedValue <<= n;
+ }
+ break;
+ case TypeClass_INTERFACE:
+ {
+ if ( rValue.getValueType().getTypeClass() == TypeClass_INTERFACE )
+ {
+ Reference< XInterface > xPure( rValue, UNO_QUERY );
+ if ( xPure.is() )
+ rConvertedValue = xPure->queryInterface( *pDestType );
+ else
+ rConvertedValue.setValue( nullptr, *pDestType );
+ bConverted = true;
+ }
+ }
+ break;
+ case TypeClass_ENUM:
+ {
+ sal_Int32 nValue = 0;
+ bConverted = ( rValue >>= nValue );
+ if ( bConverted )
+ rConvertedValue = ::cppu::int2enum( nValue, *pDestType );
+ }
+ break;
+ default: ; // avoid compiler warning
+ }
+
+ if (!bConverted)
+ {
+ throw css::lang::IllegalArgumentException(
+ "Unable to convert the given value for the property "
+ + GetPropertyName( static_cast<sal_uInt16>(nPropId) )
+ + ".\nExpected type: " + pDestType->getTypeName()
+ + "\nFound type: " + rValue.getValueType().getTypeName(),
+ static_cast< css::beans::XPropertySet* >(this),
+ 1);
+ }
+ }
+ }
+ }
+
+ // the current value
+ getFastPropertyValue( rOldValue, nPropId );
+ return !CompareProperties( rConvertedValue, rOldValue );
+}
+
+void UnoControlModel::setFastPropertyValue_NoBroadcast( sal_Int32 nPropId, const css::uno::Any& rValue )
+{
+ // Missing: the fake solo properties of the FontDescriptor
+
+ ImplPropertyTable::const_iterator it = maData.find( nPropId );
+ const css::uno::Any* pProp = it == maData.end() ? nullptr : &(it->second);
+ ENSURE_OR_RETURN_VOID( pProp, "UnoControlModel::setFastPropertyValue_NoBroadcast: invalid property id!" );
+
+ DBG_ASSERT( ( rValue.getValueType().getTypeClass() != css::uno::TypeClass_VOID ) || ( GetPropertyAttribs( static_cast<sal_uInt16>(nPropId) ) & css::beans::PropertyAttribute::MAYBEVOID ), "Property should not be VOID!" );
+ maData[ nPropId ] = rValue;
+}
+
+void UnoControlModel::getFastPropertyValue( css::uno::Any& rValue, sal_Int32 nPropId ) const
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( const_cast<UnoControlModel*>(this)->GetMutex() );
+
+ ImplPropertyTable::const_iterator it = maData.find( nPropId );
+ const css::uno::Any* pProp = it == maData.end() ? nullptr : &(it->second);
+
+ if ( pProp )
+ rValue = *pProp;
+ else if ( ( nPropId >= BASEPROPERTY_FONTDESCRIPTORPART_START ) && ( nPropId <= BASEPROPERTY_FONTDESCRIPTORPART_END ) )
+ {
+ pProp = &( maData.find( BASEPROPERTY_FONTDESCRIPTOR )->second );
+ css::awt::FontDescriptor aFD;
+ (*pProp) >>= aFD;
+ switch ( nPropId )
+ {
+ case BASEPROPERTY_FONTDESCRIPTORPART_NAME: rValue <<= aFD.Name;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_STYLENAME: rValue <<= aFD.StyleName;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_FAMILY: rValue <<= aFD.Family;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_CHARSET: rValue <<= aFD.CharSet;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_HEIGHT: rValue <<= static_cast<float>(aFD.Height);
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_WEIGHT: rValue <<= aFD.Weight;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_SLANT: rValue <<= static_cast<sal_Int16>(aFD.Slant);
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_UNDERLINE: rValue <<= aFD.Underline;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_STRIKEOUT: rValue <<= aFD.Strikeout;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_WIDTH: rValue <<= aFD.Width;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_PITCH: rValue <<= aFD.Pitch;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_CHARWIDTH: rValue <<= aFD.CharacterWidth;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_ORIENTATION: rValue <<= aFD.Orientation;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_KERNING: rValue <<= aFD.Kerning;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_WORDLINEMODE: rValue <<= aFD.WordLineMode;
+ break;
+ case BASEPROPERTY_FONTDESCRIPTORPART_TYPE: rValue <<= aFD.Type;
+ break;
+ default: OSL_FAIL( "FontProperty?!" );
+ }
+ }
+ else
+ {
+ OSL_FAIL( "getFastPropertyValue - invalid Property!" );
+ }
+}
+
+// css::beans::XPropertySet
+void UnoControlModel::setPropertyValue( const OUString& rPropertyName, const css::uno::Any& rValue )
+{
+ sal_Int32 nPropId = 0;
+ {
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+ nPropId = static_cast<sal_Int32>(GetPropertyId( rPropertyName ));
+ DBG_ASSERT( nPropId, "Invalid ID in UnoControlModel::setPropertyValue" );
+ }
+ if( !nPropId )
+ throw css::beans::UnknownPropertyException(rPropertyName);
+
+ setFastPropertyValue( nPropId, rValue );
+
+}
+
+// css::beans::XFastPropertySet
+void UnoControlModel::setFastPropertyValue( sal_Int32 nPropId, const css::uno::Any& rValue )
+{
+ if ( ( nPropId >= BASEPROPERTY_FONTDESCRIPTORPART_START ) && ( nPropId <= BASEPROPERTY_FONTDESCRIPTORPART_END ) )
+ {
+ ::osl::ClearableMutexGuard aGuard( GetMutex() );
+
+ Any aOldSingleValue;
+ getFastPropertyValue( aOldSingleValue, BASEPROPERTY_FONTDESCRIPTORPART_START );
+
+ css::uno::Any* pProp = &maData[ BASEPROPERTY_FONTDESCRIPTOR ];
+ FontDescriptor aOldFontDescriptor;
+ (*pProp) >>= aOldFontDescriptor;
+
+ FontDescriptor aNewFontDescriptor( aOldFontDescriptor );
+ lcl_ImplMergeFontProperty( aNewFontDescriptor, static_cast<sal_uInt16>(nPropId), rValue );
+
+ Any aNewValue;
+ aNewValue <<= aNewFontDescriptor;
+ sal_Int32 nDescriptorId = BASEPROPERTY_FONTDESCRIPTOR;
+
+ // also, we need fire a propertyChange event for the single property, since with
+ // the above line, only an event for the FontDescriptor property will be fired
+ Any aNewSingleValue;
+ getFastPropertyValue( aNewSingleValue, BASEPROPERTY_FONTDESCRIPTORPART_START );
+
+ aGuard.clear();
+ setFastPropertyValues( 1, &nDescriptorId, &aNewValue, 1 );
+ fire( &nPropId, &aNewSingleValue, &aOldSingleValue, 1, false );
+ }
+ else
+ setFastPropertyValues( 1, &nPropId, &rValue, 1 );
+}
+
+// css::beans::XMultiPropertySet
+css::uno::Reference< css::beans::XPropertySetInfo > UnoControlModel::getPropertySetInfo( )
+{
+ OSL_FAIL( "UnoControlModel::getPropertySetInfo() not possible!" );
+ return css::uno::Reference< css::beans::XPropertySetInfo >();
+}
+
+void UnoControlModel::setPropertyValues( const css::uno::Sequence< OUString >& rPropertyNames, const css::uno::Sequence< css::uno::Any >& Values )
+{
+ ::osl::ClearableMutexGuard aGuard( GetMutex() );
+
+ sal_Int32 nProps = rPropertyNames.getLength();
+
+// sal_Int32* pHandles = new sal_Int32[nProps];
+ // don't do this - it leaks in case of an exception
+ Sequence< sal_Int32 > aHandles( nProps );
+ sal_Int32* pHandles = aHandles.getArray();
+
+ // may need to change the order in the sequence, for this we need a non-const value sequence
+ uno::Sequence< uno::Any > aValues( Values );
+ uno::Any* pValues = aValues.getArray();
+
+ sal_Int32 nValidHandles = getInfoHelper().fillHandles( pHandles, rPropertyNames );
+
+ if ( !nValidHandles )
+ return;
+
+ // if somebody sets properties which are single aspects of a font descriptor,
+ // remove them, and build a font descriptor instead
+ std::unique_ptr< awt::FontDescriptor > pFD;
+ for ( sal_Int32 n = 0; n < nProps; ++n )
+ {
+ if ( ( pHandles[n] >= BASEPROPERTY_FONTDESCRIPTORPART_START ) && ( pHandles[n] <= BASEPROPERTY_FONTDESCRIPTORPART_END ) )
+ {
+ if (!pFD)
+ {
+ css::uno::Any* pProp = &maData[ BASEPROPERTY_FONTDESCRIPTOR ];
+ pFD.reset( new awt::FontDescriptor );
+ (*pProp) >>= *pFD;
+ }
+ lcl_ImplMergeFontProperty( *pFD, static_cast<sal_uInt16>(pHandles[n]), pValues[n] );
+ pHandles[n] = -1;
+ nValidHandles--;
+ }
+ }
+
+ if ( nValidHandles )
+ {
+ ImplNormalizePropertySequence( nProps, pHandles, pValues, &nValidHandles );
+ aGuard.clear();
+ // clear our guard before calling into setFastPropertyValues - this method
+ // will implicitly call property listeners, and this should not happen with
+ // our mutex locked
+ // #i23451#
+ setFastPropertyValues( nProps, pHandles, pValues, nValidHandles );
+ }
+ else
+ aGuard.clear();
+ // same as a few lines above
+
+ // Don't merge FD property into array, as it is sorted
+ if (pFD)
+ {
+ css::uno::Any aValue;
+ aValue <<= *pFD;
+ sal_Int32 nHandle = BASEPROPERTY_FONTDESCRIPTOR;
+ setFastPropertyValues( 1, &nHandle, &aValue, 1 );
+ }
+}
+
+
+void UnoControlModel::ImplNormalizePropertySequence( const sal_Int32, sal_Int32*,
+ uno::Any*, sal_Int32* ) const
+{
+ // nothing to do here
+}
+
+void UnoControlModel::ImplEnsureHandleOrder( const sal_Int32 _nCount, sal_Int32* _pHandles,
+ uno::Any* _pValues, sal_Int32 _nFirstHandle, sal_Int32 _nSecondHandle )
+{
+ for ( sal_Int32 i=0; i < _nCount; ++_pHandles, ++_pValues, ++i )
+ {
+ if ( _nSecondHandle == *_pHandles )
+ {
+ sal_Int32* pLaterHandles = _pHandles + 1;
+ uno::Any* pLaterValues = _pValues + 1;
+ for ( sal_Int32 j = i + 1; j < _nCount; ++j, ++pLaterHandles, ++pLaterValues )
+ {
+ if ( _nFirstHandle == *pLaterHandles )
+ {
+ // indeed it is -> exchange the both places in the sequences
+ sal_Int32 nHandle( *_pHandles );
+ *_pHandles = *pLaterHandles;
+ *pLaterHandles = nHandle;
+
+ uno::Any aValue( *_pValues );
+ *_pValues = *pLaterValues;
+ *pLaterValues = aValue;
+
+ break;
+ // this will leave the inner loop, and continue with the outer loop.
+ // Note that this means we will encounter the _nSecondHandle handle, again, once we reached
+ // (in the outer loop) the place where we just put it.
+ }
+ }
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/unocontrols.cxx b/toolkit/source/controls/unocontrols.cxx
new file mode 100644
index 000000000..260fc1301
--- /dev/null
+++ b/toolkit/source/controls/unocontrols.cxx
@@ -0,0 +1,4760 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/awt/XTextArea.hpp>
+#include <com/sun/star/awt/XVclWindowPeer.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/awt/VisualEffect.hpp>
+#include <com/sun/star/awt/LineEndFormat.hpp>
+#include <com/sun/star/graphic/GraphicProvider.hpp>
+#include <com/sun/star/graphic/XGraphicProvider.hpp>
+#include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/awt/ImageScaleMode.hpp>
+
+#include <o3tl/safeint.hxx>
+#include <controls/formattedcontrol.hxx>
+#include <toolkit/controls/unocontrols.hxx>
+#include <toolkit/helper/property.hxx>
+#include <toolkit/helper/macros.hxx>
+
+// for introspection
+#include <awt/vclxwindows.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <tools/debug.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <algorithm>
+
+#include <helper/imagealign.hxx>
+#include <helper/unopropertyarrayhelper.hxx>
+
+using namespace css;
+using namespace css::awt;
+using namespace css::lang;
+using namespace css::uno;
+using ::com::sun::star::graphic::XGraphic;
+using ::com::sun::star::uno::Reference;
+using namespace ::toolkit;
+
+uno::Reference< graphic::XGraphic >
+ImageHelper::getGraphicAndGraphicObjectFromURL_nothrow( uno::Reference< graphic::XGraphicObject >& xOutGraphicObj, const OUString& _rURL )
+{
+ xOutGraphicObj = nullptr;
+ return ImageHelper::getGraphicFromURL_nothrow( _rURL );
+}
+
+css::uno::Reference< css::graphic::XGraphic >
+ImageHelper::getGraphicFromURL_nothrow( const OUString& _rURL )
+{
+ uno::Reference< graphic::XGraphic > xGraphic;
+ if ( _rURL.isEmpty() )
+ return xGraphic;
+
+ try
+ {
+ uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
+ uno::Reference< graphic::XGraphicProvider > xProvider( graphic::GraphicProvider::create(xContext) );
+ xGraphic = xProvider->queryGraphic({ comphelper::makePropertyValue("URL", _rURL) });
+ }
+ catch (const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+
+ return xGraphic;
+}
+
+
+UnoControlEditModel::UnoControlEditModel( const Reference< XComponentContext >& rxContext )
+ :UnoControlModel( rxContext )
+{
+ UNO_CONTROL_MODEL_REGISTER_PROPERTIES<VCLXEdit>();
+}
+
+OUString UnoControlEditModel::getServiceName( )
+{
+ return "stardiv.vcl.controlmodel.Edit";
+}
+
+uno::Any UnoControlEditModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ uno::Any aReturn;
+
+ switch ( nPropId )
+ {
+ case BASEPROPERTY_LINE_END_FORMAT:
+ aReturn <<= sal_Int16(awt::LineEndFormat::LINE_FEED); // LF
+ break;
+ case BASEPROPERTY_DEFAULTCONTROL:
+ aReturn <<= OUString( "stardiv.vcl.control.Edit" );
+ break;
+ default:
+ aReturn = UnoControlModel::ImplGetDefaultValue( nPropId );
+ break;
+ }
+ return aReturn;
+}
+
+::cppu::IPropertyArrayHelper& UnoControlEditModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+// beans::XMultiPropertySet
+uno::Reference< beans::XPropertySetInfo > UnoControlEditModel::getPropertySetInfo( )
+{
+ static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+OUString UnoControlEditModel::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoControlEditModel";
+}
+
+css::uno::Sequence<OUString> UnoControlEditModel::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlEditModel", "stardiv.vcl.controlmodel.Edit" };
+ return comphelper::concatSequences(UnoControlModel::getSupportedServiceNames(), vals);
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlEditModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoControlEditModel(context));
+}
+
+
+
+UnoEditControl::UnoEditControl()
+ :maTextListeners( *this )
+ ,mnMaxTextLen( 0 )
+ ,mbSetTextInPeer( false )
+ ,mbSetMaxTextLenInPeer( false )
+ ,mbHasTextProperty( false )
+{
+ maComponentInfos.nWidth = 100;
+ maComponentInfos.nHeight = 12;
+}
+
+uno::Any SAL_CALL UnoEditControl::queryAggregation( const uno::Type & rType )
+{
+ uno::Any aReturn = UnoControlBase::queryAggregation( rType );
+ if ( !aReturn.hasValue() )
+ aReturn = UnoEditControl_Base::queryInterface( rType );
+ return aReturn;
+}
+
+uno::Any SAL_CALL UnoEditControl::queryInterface( const uno::Type & rType )
+{
+ return UnoControlBase::queryInterface( rType );
+}
+
+void SAL_CALL UnoEditControl::acquire( ) noexcept
+{
+ UnoControlBase::acquire();
+}
+
+void SAL_CALL UnoEditControl::release( ) noexcept
+{
+ UnoControlBase::release();
+}
+
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( UnoEditControl, UnoControlBase, UnoEditControl_Base )
+
+OUString UnoEditControl::GetComponentServiceName() const
+{
+ // by default, we want a simple edit field
+ OUString sName( "Edit" );
+
+ // but maybe we are to display multi-line text?
+ uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_MULTILINE ) );
+ bool b = bool();
+ if ( ( aVal >>= b ) && b )
+ sName = "MultiLineEdit";
+
+ return sName;
+}
+
+sal_Bool SAL_CALL UnoEditControl::setModel(const uno::Reference< awt::XControlModel >& _rModel)
+{
+ bool bReturn = UnoControlBase::setModel( _rModel );
+ mbHasTextProperty = ImplHasProperty( BASEPROPERTY_TEXT );
+ return bReturn;
+}
+
+void UnoEditControl::ImplSetPeerProperty( const OUString& rPropName, const uno::Any& rVal )
+{
+ bool bDone = false;
+ if ( GetPropertyId( rPropName ) == BASEPROPERTY_TEXT )
+ {
+ // #96986# use setText(), or text listener will not be called.
+ uno::Reference < awt::XTextComponent > xTextComponent( getPeer(), uno::UNO_QUERY );
+ if ( xTextComponent.is() )
+ {
+ OUString sText;
+ rVal >>= sText;
+ ImplCheckLocalize( sText );
+ xTextComponent->setText( sText );
+ bDone = true;
+ }
+ }
+
+ if ( !bDone )
+ UnoControlBase::ImplSetPeerProperty( rPropName, rVal );
+}
+
+void UnoEditControl::dispose()
+{
+ lang::EventObject aEvt( *this );
+ maTextListeners.disposeAndClear( aEvt );
+ UnoControl::dispose();
+}
+
+void UnoEditControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer > & rParentPeer )
+{
+ UnoControl::createPeer( rxToolkit, rParentPeer );
+
+ uno::Reference< awt::XTextComponent > xText( getPeer(), uno::UNO_QUERY );
+ if ( xText.is() )
+ {
+ xText->addTextListener( this );
+
+ if ( mbSetMaxTextLenInPeer )
+ xText->setMaxTextLen( mnMaxTextLen );
+ if ( mbSetTextInPeer )
+ xText->setText( maText );
+ }
+}
+
+void UnoEditControl::textChanged(const awt::TextEvent& e)
+{
+ uno::Reference< awt::XTextComponent > xText( getPeer(), uno::UNO_QUERY );
+
+ if ( mbHasTextProperty )
+ {
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_TEXT ), uno::Any(xText->getText()), false );
+ }
+ else
+ {
+ maText = xText->getText();
+ }
+
+ if ( maTextListeners.getLength() )
+ maTextListeners.textChanged( e );
+}
+
+void UnoEditControl::addTextListener(const uno::Reference< awt::XTextListener > & l)
+{
+ // tdf#150974 some extensions pass null
+ if (!l)
+ {
+ SAL_WARN("toolkit", "null XTextListener");
+ return;
+ }
+ maTextListeners.addInterface( l );
+}
+
+void UnoEditControl::removeTextListener(const uno::Reference< awt::XTextListener > & l)
+{
+ // tdf#150974 some extensions pass null
+ if (!l)
+ {
+ SAL_WARN("toolkit", "null XTextListener");
+ return;
+ }
+ maTextListeners.removeInterface( l );
+}
+
+void UnoEditControl::setText( const OUString& aText )
+{
+ if ( mbHasTextProperty )
+ {
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_TEXT ), uno::Any(aText), true );
+ }
+ else
+ {
+ maText = aText;
+ mbSetTextInPeer = true;
+ uno::Reference < awt::XTextComponent > xText( getPeer(), uno::UNO_QUERY );
+ if ( xText.is() )
+ xText->setText( maText );
+ }
+
+ // Setting the property to the VCLXWindow doesn't call textChanged
+ if ( maTextListeners.getLength() )
+ {
+ awt::TextEvent aEvent;
+ aEvent.Source = *this;
+ maTextListeners.textChanged( aEvent );
+ }
+}
+
+namespace
+{
+ void lcl_normalize( awt::Selection& _rSel )
+ {
+ if ( _rSel.Min > _rSel.Max )
+ ::std::swap( _rSel.Min, _rSel.Max );
+ }
+}
+
+void UnoEditControl::insertText( const awt::Selection& rSel, const OUString& rNewText )
+{
+ // normalize the selection - OUString::replaceAt has a strange behaviour if the min is greater than the max
+ awt::Selection aSelection( rSel );
+ lcl_normalize( aSelection );
+
+ OUString aOldText = getText();
+ if (aSelection.Min < 0 || aOldText.getLength() < aSelection.Max)
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ // preserve the selection resp. cursor position
+ awt::Selection aNewSelection( getSelection() );
+#ifdef ALSO_PRESERVE_COMPLETE_SELECTION
+ // (not sure - looks uglier ...)
+ sal_Int32 nDeletedCharacters = ( aSelection.Max - aSelection.Min ) - rNewText.getLength();
+ if ( aNewSelection.Min > aSelection.Min )
+ aNewSelection.Min -= nDeletedCharacters;
+ if ( aNewSelection.Max > aSelection.Max )
+ aNewSelection.Max -= nDeletedCharacters;
+#else
+ aNewSelection.Max = ::std::min( aNewSelection.Min, aNewSelection.Max ) + rNewText.getLength();
+ aNewSelection.Min = aNewSelection.Max;
+#endif
+
+ OUString aNewText = aOldText.replaceAt( aSelection.Min, aSelection.Max - aSelection.Min, rNewText );
+ setText( aNewText );
+
+ setSelection( aNewSelection );
+}
+
+OUString UnoEditControl::getText()
+{
+ OUString aText = maText;
+
+ if ( mbHasTextProperty )
+ aText = ImplGetPropertyValue_UString( BASEPROPERTY_TEXT );
+ else
+ {
+ uno::Reference< awt::XTextComponent > xText( getPeer(), uno::UNO_QUERY );
+ if ( xText.is() )
+ aText = xText->getText();
+ }
+
+ return aText;
+}
+
+OUString UnoEditControl::getSelectedText()
+{
+ OUString sSelected;
+ uno::Reference< awt::XTextComponent > xText( getPeer(), uno::UNO_QUERY );
+ if ( xText.is() )
+ sSelected = xText->getSelectedText();
+
+ return sSelected;
+}
+
+void UnoEditControl::setSelection( const awt::Selection& aSelection )
+{
+ uno::Reference< awt::XTextComponent > xText( getPeer(), uno::UNO_QUERY );
+ if ( xText.is() )
+ xText->setSelection( aSelection );
+}
+
+awt::Selection UnoEditControl::getSelection()
+{
+ awt::Selection aSel;
+ uno::Reference< awt::XTextComponent > xText( getPeer(), uno::UNO_QUERY );
+ if ( xText.is() )
+ aSel = xText->getSelection();
+ return aSel;
+}
+
+sal_Bool UnoEditControl::isEditable()
+{
+ return !ImplGetPropertyValue_BOOL( BASEPROPERTY_READONLY );
+}
+
+void UnoEditControl::setEditable( sal_Bool bEditable )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_READONLY ), uno::Any(!bEditable), true );
+}
+
+sal_Int16 UnoEditControl::getMaxTextLen()
+{
+ sal_Int16 nMaxLen = mnMaxTextLen;
+
+ if ( ImplHasProperty( BASEPROPERTY_MAXTEXTLEN ) )
+ nMaxLen = ImplGetPropertyValue_INT16( BASEPROPERTY_MAXTEXTLEN );
+
+ return nMaxLen;
+}
+
+void UnoEditControl::setMaxTextLen( sal_Int16 nLen )
+{
+ if ( ImplHasProperty( BASEPROPERTY_MAXTEXTLEN) )
+ {
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_MAXTEXTLEN ), uno::Any(nLen), true );
+ }
+ else
+ {
+ mnMaxTextLen = nLen;
+ mbSetMaxTextLenInPeer = true;
+ uno::Reference < awt::XTextComponent > xText( getPeer(), uno::UNO_QUERY );
+ if ( xText.is() )
+ xText->setMaxTextLen( mnMaxTextLen );
+ }
+}
+
+awt::Size UnoEditControl::getMinimumSize( )
+{
+ return Impl_getMinimumSize();
+}
+
+awt::Size UnoEditControl::getPreferredSize( )
+{
+ return Impl_getPreferredSize();
+}
+
+awt::Size UnoEditControl::calcAdjustedSize( const awt::Size& rNewSize )
+{
+ return Impl_calcAdjustedSize( rNewSize );
+}
+
+awt::Size UnoEditControl::getMinimumSize( sal_Int16 nCols, sal_Int16 nLines )
+{
+ return Impl_getMinimumSize( nCols, nLines );
+}
+
+void UnoEditControl::getColumnsAndLines( sal_Int16& nCols, sal_Int16& nLines )
+{
+ Impl_getColumnsAndLines( nCols, nLines );
+}
+
+OUString UnoEditControl::getImplementationName( )
+{
+ return "stardiv.Toolkit.UnoEditControl";
+}
+
+uno::Sequence< OUString > UnoEditControl::getSupportedServiceNames()
+{
+ css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlEdit", "stardiv.vcl.control.Edit" };
+ return comphelper::concatSequences( UnoControlBase::getSupportedServiceNames( ), vals);
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoEditControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoEditControl());
+}
+
+
+
+UnoControlFileControlModel::UnoControlFileControlModel( const Reference< XComponentContext >& rxContext )
+ :UnoControlModel( rxContext )
+{
+ ImplRegisterProperty( BASEPROPERTY_ALIGN );
+ ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_BORDER );
+ ImplRegisterProperty( BASEPROPERTY_BORDERCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
+ ImplRegisterProperty( BASEPROPERTY_ENABLED );
+ ImplRegisterProperty( BASEPROPERTY_ENABLEVISIBLE );
+ ImplRegisterProperty( BASEPROPERTY_FONTDESCRIPTOR );
+ ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
+ ImplRegisterProperty( BASEPROPERTY_HELPURL );
+ ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
+ ImplRegisterProperty( BASEPROPERTY_READONLY );
+ ImplRegisterProperty( BASEPROPERTY_TABSTOP );
+ ImplRegisterProperty( BASEPROPERTY_TEXT );
+ ImplRegisterProperty( BASEPROPERTY_VERTICALALIGN );
+ ImplRegisterProperty( BASEPROPERTY_WRITING_MODE );
+ ImplRegisterProperty( BASEPROPERTY_CONTEXT_WRITING_MODE );
+ ImplRegisterProperty( BASEPROPERTY_HIDEINACTIVESELECTION );
+}
+
+OUString UnoControlFileControlModel::getServiceName()
+{
+ return "stardiv.vcl.controlmodel.FileControl";
+}
+
+uno::Any UnoControlFileControlModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
+ {
+ return uno::Any( OUString( "stardiv.vcl.control.FileControl" ) );
+ }
+ return UnoControlModel::ImplGetDefaultValue( nPropId );
+}
+
+::cppu::IPropertyArrayHelper& UnoControlFileControlModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+// beans::XMultiPropertySet
+uno::Reference< beans::XPropertySetInfo > UnoControlFileControlModel::getPropertySetInfo( )
+{
+ static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+OUString UnoControlFileControlModel::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoControlFileControlModel";
+}
+
+css::uno::Sequence<OUString>
+UnoControlFileControlModel::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlFileControlModel", "stardiv.vcl.controlmodel.FileControl" };
+ return comphelper::concatSequences( UnoControlModel::getSupportedServiceNames(), vals);
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlFileControlModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoControlFileControlModel(context));
+}
+
+
+
+UnoFileControl::UnoFileControl()
+{
+}
+
+OUString UnoFileControl::GetComponentServiceName() const
+{
+ return "filecontrol";
+}
+
+OUString UnoFileControl::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoFileControl";
+}
+
+css::uno::Sequence<OUString> UnoFileControl::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlFileControl", "stardiv.vcl.control.FileControl" };
+ return comphelper::concatSequences( UnoEditControl::getSupportedServiceNames(), vals );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoFileControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoFileControl());
+}
+
+
+
+uno::Any GraphicControlModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ if ( nPropId == BASEPROPERTY_GRAPHIC )
+ return uno::Any( uno::Reference< graphic::XGraphic >() );
+
+ return UnoControlModel::ImplGetDefaultValue( nPropId );
+}
+
+void SAL_CALL GraphicControlModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const css::uno::Any& rValue )
+{
+ UnoControlModel::setFastPropertyValue_NoBroadcast( nHandle, rValue );
+
+ // - ImageAlign and ImagePosition need to correspond to each other
+ // - Graphic and ImageURL need to correspond to each other
+ try
+ {
+ switch ( nHandle )
+ {
+ case BASEPROPERTY_IMAGEURL:
+ if ( !mbAdjustingGraphic && ImplHasProperty( BASEPROPERTY_GRAPHIC ) )
+ {
+ mbAdjustingGraphic = true;
+ OUString sImageURL;
+ OSL_VERIFY( rValue >>= sImageURL );
+ setDependentFastPropertyValue( BASEPROPERTY_GRAPHIC, uno::Any( ImageHelper::getGraphicFromURL_nothrow( sImageURL ) ) );
+ mbAdjustingGraphic = false;
+ }
+ break;
+
+ case BASEPROPERTY_GRAPHIC:
+ if ( !mbAdjustingGraphic && ImplHasProperty( BASEPROPERTY_IMAGEURL ) )
+ {
+ mbAdjustingGraphic = true;
+ setDependentFastPropertyValue( BASEPROPERTY_IMAGEURL, uno::Any( OUString() ) );
+ mbAdjustingGraphic = false;
+ }
+ break;
+
+ case BASEPROPERTY_IMAGEALIGN:
+ if ( !mbAdjustingImagePosition && ImplHasProperty( BASEPROPERTY_IMAGEPOSITION ) )
+ {
+ mbAdjustingImagePosition = true;
+ sal_Int16 nUNOValue = 0;
+ OSL_VERIFY( rValue >>= nUNOValue );
+ setDependentFastPropertyValue( BASEPROPERTY_IMAGEPOSITION, uno::Any( getExtendedImagePosition( nUNOValue ) ) );
+ mbAdjustingImagePosition = false;
+ }
+ break;
+ case BASEPROPERTY_IMAGEPOSITION:
+ if ( !mbAdjustingImagePosition && ImplHasProperty( BASEPROPERTY_IMAGEALIGN ) )
+ {
+ mbAdjustingImagePosition = true;
+ sal_Int16 nUNOValue = 0;
+ OSL_VERIFY( rValue >>= nUNOValue );
+ setDependentFastPropertyValue( BASEPROPERTY_IMAGEALIGN, uno::Any( getCompatibleImageAlign( translateImagePosition( nUNOValue ) ) ) );
+ mbAdjustingImagePosition = false;
+ }
+ break;
+ }
+ }
+ catch( const css::uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ OSL_FAIL( "GraphicControlModel::setFastPropertyValue_NoBroadcast: caught an exception while aligning the ImagePosition/ImageAlign properties!" );
+ mbAdjustingImagePosition = false;
+ }
+}
+
+
+
+UnoControlButtonModel::UnoControlButtonModel( const Reference< XComponentContext >& rxContext )
+ :GraphicControlModel( rxContext )
+{
+ UNO_CONTROL_MODEL_REGISTER_PROPERTIES<VCLXButton>();
+
+ osl_atomic_increment( &m_refCount );
+ {
+ setFastPropertyValue_NoBroadcast( BASEPROPERTY_IMAGEPOSITION, ImplGetDefaultValue( BASEPROPERTY_IMAGEPOSITION ) );
+ // this ensures that our ImagePosition is consistent with our ImageAlign property (since both
+ // defaults are not per se consistent), since both are coupled in setFastPropertyValue_NoBroadcast
+ }
+ osl_atomic_decrement( &m_refCount );
+}
+
+OUString UnoControlButtonModel::getServiceName()
+{
+ return "stardiv.vcl.controlmodel.Button";
+}
+
+uno::Any UnoControlButtonModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ switch ( nPropId )
+ {
+ case BASEPROPERTY_DEFAULTCONTROL:
+ return uno::Any( OUString( "stardiv.vcl.control.Button" ) );
+ case BASEPROPERTY_TOGGLE:
+ return uno::Any( false );
+ case BASEPROPERTY_ALIGN:
+ return uno::Any( sal_Int16(PROPERTY_ALIGN_CENTER) );
+ case BASEPROPERTY_FOCUSONCLICK:
+ return uno::Any( true );
+ }
+
+ return GraphicControlModel::ImplGetDefaultValue( nPropId );
+}
+
+::cppu::IPropertyArrayHelper& UnoControlButtonModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+// beans::XMultiPropertySet
+uno::Reference< beans::XPropertySetInfo > UnoControlButtonModel::getPropertySetInfo( )
+{
+ static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+OUString UnoControlButtonModel::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoControlButtonModel";
+}
+
+css::uno::Sequence<OUString> UnoControlButtonModel::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlButtonModel", "stardiv.vcl.controlmodel.Button" };
+ return comphelper::concatSequences( GraphicControlModel::getSupportedServiceNames(), vals );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlButtonModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoControlButtonModel(context));
+}
+
+
+
+UnoButtonControl::UnoButtonControl()
+ :maActionListeners( *this )
+ ,maItemListeners( *this )
+{
+ maComponentInfos.nWidth = 50;
+ maComponentInfos.nHeight = 14;
+}
+
+OUString UnoButtonControl::GetComponentServiceName() const
+{
+ OUString aName( "pushbutton" );
+ uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_PUSHBUTTONTYPE ) );
+ sal_Int16 n = sal_Int16();
+ if ( ( aVal >>= n ) && n )
+ {
+ // Use PushButtonType later when available...
+ switch ( n )
+ {
+ case 1 /*PushButtonType::OK*/: aName = "okbutton";
+ break;
+ case 2 /*PushButtonType::CANCEL*/: aName = "cancelbutton";
+ break;
+ case 3 /*PushButtonType::HELP*/: aName = "helpbutton";
+ break;
+ default:
+ {
+ OSL_FAIL( "Unknown Button Type!" );
+ }
+ }
+ }
+ return aName;
+}
+
+void UnoButtonControl::dispose()
+{
+ lang::EventObject aEvt;
+ aEvt.Source = static_cast<cppu::OWeakObject*>(this);
+ maActionListeners.disposeAndClear( aEvt );
+ maItemListeners.disposeAndClear( aEvt );
+ UnoControlBase::dispose();
+}
+
+void UnoButtonControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer > & rParentPeer )
+{
+ UnoControlBase::createPeer( rxToolkit, rParentPeer );
+
+ uno::Reference < awt::XButton > xButton( getPeer(), uno::UNO_QUERY );
+ xButton->setActionCommand( maActionCommand );
+ if ( maActionListeners.getLength() )
+ xButton->addActionListener( &maActionListeners );
+
+ uno::Reference< XToggleButton > xPushButton( getPeer(), uno::UNO_QUERY );
+ if ( xPushButton.is() )
+ xPushButton->addItemListener( this );
+}
+
+void UnoButtonControl::addActionListener(const uno::Reference< awt::XActionListener > & l)
+{
+ // tdf#150974 some extensions pass null
+ if (!l)
+ {
+ SAL_WARN("toolkit", "null XActionListener");
+ return;
+ }
+
+ maActionListeners.addInterface( l );
+ if( getPeer().is() && maActionListeners.getLength() == 1 )
+ {
+ uno::Reference < awt::XButton > xButton( getPeer(), uno::UNO_QUERY );
+ xButton->addActionListener( &maActionListeners );
+ }
+}
+
+void UnoButtonControl::removeActionListener(const uno::Reference< awt::XActionListener > & l)
+{
+ // tdf#150974 some extensions pass null
+ if (!l)
+ {
+ SAL_WARN("toolkit", "null XActionListener");
+ return;
+ }
+
+ if( getPeer().is() && maActionListeners.getLength() == 1 )
+ {
+ uno::Reference < awt::XButton > xButton( getPeer(), uno::UNO_QUERY );
+ xButton->removeActionListener( &maActionListeners );
+ }
+ maActionListeners.removeInterface( l );
+}
+
+void UnoButtonControl::addItemListener(const uno::Reference< awt::XItemListener > & l)
+{
+ maItemListeners.addInterface( l );
+}
+
+void UnoButtonControl::removeItemListener(const uno::Reference< awt::XItemListener > & l)
+{
+ maItemListeners.removeInterface( l );
+}
+
+void SAL_CALL UnoButtonControl::disposing( const lang::EventObject& Source )
+{
+ UnoControlBase::disposing( Source );
+}
+
+void SAL_CALL UnoButtonControl::itemStateChanged( const awt::ItemEvent& rEvent )
+{
+ // forward to model
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STATE ), uno::Any(static_cast<sal_Int16>(rEvent.Selected)), false );
+
+ // multiplex
+ ItemEvent aEvent( rEvent );
+ aEvent.Source = *this;
+ maItemListeners.itemStateChanged( aEvent );
+}
+
+void UnoButtonControl::setLabel( const OUString& rLabel )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_LABEL ), uno::Any(rLabel), true );
+}
+
+void UnoButtonControl::setActionCommand( const OUString& rCommand )
+{
+ maActionCommand = rCommand;
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XButton > xButton( getPeer(), uno::UNO_QUERY );
+ xButton->setActionCommand( rCommand );
+ }
+}
+
+awt::Size UnoButtonControl::getMinimumSize( )
+{
+ return Impl_getMinimumSize();
+}
+
+awt::Size UnoButtonControl::getPreferredSize( )
+{
+ return Impl_getPreferredSize();
+}
+
+awt::Size UnoButtonControl::calcAdjustedSize( const awt::Size& rNewSize )
+{
+ return Impl_calcAdjustedSize( rNewSize );
+}
+
+OUString UnoButtonControl::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoButtonControl";
+}
+
+css::uno::Sequence<OUString> UnoButtonControl::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlButton", "stardiv.vcl.control.Button" };
+ return comphelper::concatSequences( UnoControlBase::getSupportedServiceNames(), vals);
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoButtonControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoButtonControl());
+}
+
+
+
+UnoControlImageControlModel::UnoControlImageControlModel( const Reference< XComponentContext >& rxContext )
+ :GraphicControlModel( rxContext )
+ ,mbAdjustingImageScaleMode( false )
+{
+ UNO_CONTROL_MODEL_REGISTER_PROPERTIES<VCLXImageControl>();
+}
+
+OUString UnoControlImageControlModel::getServiceName()
+{
+ return "stardiv.vcl.controlmodel.ImageControl";
+}
+
+OUString UnoControlImageControlModel::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoControlImageControlModel";
+}
+
+css::uno::Sequence<OUString>
+UnoControlImageControlModel::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals {
+ "com.sun.star.awt.UnoControlImageButtonModel",
+ "com.sun.star.awt.UnoControlImageControlModel",
+ "stardiv.vcl.controlmodel.ImageButton",
+ "stardiv.vcl.controlmodel.ImageControl"
+ };
+ return comphelper::concatSequences( GraphicControlModel::getSupportedServiceNames(), vals);
+}
+
+uno::Any UnoControlImageControlModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
+ return uno::Any( OUString( "stardiv.vcl.control.ImageControl" ) );
+
+ if ( nPropId == BASEPROPERTY_IMAGE_SCALE_MODE )
+ return Any( awt::ImageScaleMode::ANISOTROPIC );
+
+ return GraphicControlModel::ImplGetDefaultValue( nPropId );
+}
+
+::cppu::IPropertyArrayHelper& UnoControlImageControlModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+// beans::XMultiPropertySet
+uno::Reference< beans::XPropertySetInfo > UnoControlImageControlModel::getPropertySetInfo( )
+{
+ static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+void SAL_CALL UnoControlImageControlModel::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const css::uno::Any& _rValue )
+{
+ GraphicControlModel::setFastPropertyValue_NoBroadcast( _nHandle, _rValue );
+
+ // ScaleImage is an older (and less powerful) version of ScaleMode, but keep both in sync as far as possible
+ try
+ {
+ switch ( _nHandle )
+ {
+ case BASEPROPERTY_IMAGE_SCALE_MODE:
+ if ( !mbAdjustingImageScaleMode && ImplHasProperty( BASEPROPERTY_SCALEIMAGE ) )
+ {
+ mbAdjustingImageScaleMode = true;
+ sal_Int16 nScaleMode( awt::ImageScaleMode::ANISOTROPIC );
+ OSL_VERIFY( _rValue >>= nScaleMode );
+ setDependentFastPropertyValue( BASEPROPERTY_SCALEIMAGE, uno::Any( nScaleMode != awt::ImageScaleMode::NONE ) );
+ mbAdjustingImageScaleMode = false;
+ }
+ break;
+ case BASEPROPERTY_SCALEIMAGE:
+ if ( !mbAdjustingImageScaleMode && ImplHasProperty( BASEPROPERTY_IMAGE_SCALE_MODE ) )
+ {
+ mbAdjustingImageScaleMode = true;
+ bool bScale = true;
+ OSL_VERIFY( _rValue >>= bScale );
+ setDependentFastPropertyValue( BASEPROPERTY_IMAGE_SCALE_MODE, uno::Any( bScale ? awt::ImageScaleMode::ANISOTROPIC : awt::ImageScaleMode::NONE ) );
+ mbAdjustingImageScaleMode = false;
+ }
+ break;
+ }
+ }
+ catch( const Exception& )
+ {
+ mbAdjustingImageScaleMode = false;
+ throw;
+ }
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlImageControlModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoControlImageControlModel(context));
+}
+
+
+
+UnoImageControlControl::UnoImageControlControl()
+ :maActionListeners( *this )
+{
+ // TODO: Where should I look for defaults?
+ maComponentInfos.nWidth = 100;
+ maComponentInfos.nHeight = 100;
+}
+
+OUString UnoImageControlControl::GetComponentServiceName() const
+{
+ return "fixedimage";
+}
+
+void UnoImageControlControl::dispose()
+{
+ lang::EventObject aEvt;
+ aEvt.Source = static_cast<cppu::OWeakObject*>(this);
+ maActionListeners.disposeAndClear( aEvt );
+ UnoControl::dispose();
+}
+
+sal_Bool UnoImageControlControl::isTransparent()
+{
+ return true;
+}
+
+awt::Size UnoImageControlControl::getMinimumSize( )
+{
+ return Impl_getMinimumSize();
+}
+
+awt::Size UnoImageControlControl::getPreferredSize( )
+{
+ return Impl_getPreferredSize();
+}
+
+awt::Size UnoImageControlControl::calcAdjustedSize( const awt::Size& rNewSize )
+{
+ return Impl_calcAdjustedSize( rNewSize );
+}
+
+OUString UnoImageControlControl::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoImageControlControl";
+}
+
+css::uno::Sequence<OUString> UnoImageControlControl::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals {
+ "com.sun.star.awt.UnoControlImageButton",
+ "com.sun.star.awt.UnoControlImageControl",
+ "stardiv.vcl.control.ImageButton",
+ "stardiv.vcl.control.ImageControl"
+ };
+ return comphelper::concatSequences( UnoControlBase::getSupportedServiceNames(), vals);
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoImageControlControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoImageControlControl());
+}
+
+
+
+UnoControlRadioButtonModel::UnoControlRadioButtonModel( const Reference< XComponentContext >& rxContext )
+ :GraphicControlModel( rxContext )
+{
+ UNO_CONTROL_MODEL_REGISTER_PROPERTIES<VCLXRadioButton>();
+}
+
+OUString UnoControlRadioButtonModel::getServiceName()
+{
+ return "stardiv.vcl.controlmodel.RadioButton";
+}
+
+uno::Any UnoControlRadioButtonModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ switch ( nPropId )
+ {
+ case BASEPROPERTY_DEFAULTCONTROL:
+ return uno::Any( OUString( "stardiv.vcl.control.RadioButton" ) );
+
+ case BASEPROPERTY_VISUALEFFECT:
+ return uno::Any( sal_Int16(awt::VisualEffect::LOOK3D) );
+ }
+
+ return GraphicControlModel::ImplGetDefaultValue( nPropId );
+}
+
+::cppu::IPropertyArrayHelper& UnoControlRadioButtonModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+// beans::XMultiPropertySet
+uno::Reference< beans::XPropertySetInfo > UnoControlRadioButtonModel::getPropertySetInfo( )
+{
+ static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+OUString UnoControlRadioButtonModel::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoControlRadioButtonModel";
+}
+
+css::uno::Sequence<OUString>
+UnoControlRadioButtonModel::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlRadioButtonModel", "stardiv.vcl.controlmodel.RadioButton" };
+ return comphelper::concatSequences( GraphicControlModel::getSupportedServiceNames(), vals);
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlRadioButtonModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoControlRadioButtonModel(context));
+}
+
+
+
+UnoRadioButtonControl::UnoRadioButtonControl()
+ :maItemListeners( *this )
+ ,maActionListeners( *this )
+{
+ maComponentInfos.nWidth = 100;
+ maComponentInfos.nHeight = 12;
+}
+
+OUString UnoRadioButtonControl::GetComponentServiceName() const
+{
+ return "radiobutton";
+}
+
+void UnoRadioButtonControl::dispose()
+{
+ lang::EventObject aEvt;
+ aEvt.Source = static_cast<cppu::OWeakObject*>(this);
+ maItemListeners.disposeAndClear( aEvt );
+ UnoControlBase::dispose();
+}
+
+
+sal_Bool UnoRadioButtonControl::isTransparent()
+{
+ return true;
+}
+
+void UnoRadioButtonControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer > & rParentPeer )
+{
+ UnoControlBase::createPeer( rxToolkit, rParentPeer );
+
+ uno::Reference < awt::XRadioButton > xRadioButton( getPeer(), uno::UNO_QUERY );
+ xRadioButton->addItemListener( this );
+
+ uno::Reference < awt::XButton > xButton( getPeer(), uno::UNO_QUERY );
+ xButton->setActionCommand( maActionCommand );
+ if ( maActionListeners.getLength() )
+ xButton->addActionListener( &maActionListeners );
+
+ // as default, set the "AutoToggle" to true
+ // (it is set to false in VCLXToolkit::ImplCreateWindow because of #87254#, but we want to
+ // have it enabled by default because of 85071)
+ uno::Reference< awt::XVclWindowPeer > xVclWindowPeer( getPeer(), uno::UNO_QUERY );
+ if ( xVclWindowPeer.is() )
+ xVclWindowPeer->setProperty( GetPropertyName( BASEPROPERTY_AUTOTOGGLE ), css::uno::Any(true) );
+}
+
+void UnoRadioButtonControl::addItemListener(const uno::Reference < awt::XItemListener > & l)
+{
+ maItemListeners.addInterface( l );
+}
+
+void UnoRadioButtonControl::removeItemListener(const uno::Reference < awt::XItemListener > & l)
+{
+ maItemListeners.removeInterface( l );
+}
+
+void UnoRadioButtonControl::addActionListener(const uno::Reference< awt::XActionListener > & l)
+{
+ maActionListeners.addInterface( l );
+ if( getPeer().is() && maActionListeners.getLength() == 1 )
+ {
+ uno::Reference < awt::XButton > xButton( getPeer(), uno::UNO_QUERY );
+ xButton->addActionListener( &maActionListeners );
+ }
+}
+
+void UnoRadioButtonControl::removeActionListener(const uno::Reference< awt::XActionListener > & l)
+{
+ if( getPeer().is() && maActionListeners.getLength() == 1 )
+ {
+ uno::Reference < awt::XButton > xButton( getPeer(), uno::UNO_QUERY );
+ xButton->removeActionListener( &maActionListeners );
+ }
+ maActionListeners.removeInterface( l );
+}
+
+void UnoRadioButtonControl::setLabel( const OUString& rLabel )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_LABEL ), uno::Any(rLabel), true );
+}
+
+void UnoRadioButtonControl::setActionCommand( const OUString& rCommand )
+{
+ maActionCommand = rCommand;
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XButton > xButton( getPeer(), uno::UNO_QUERY );
+ xButton->setActionCommand( rCommand );
+ }
+}
+
+void UnoRadioButtonControl::setState( sal_Bool bOn )
+{
+ sal_Int16 nState = bOn ? 1 : 0;
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STATE ), uno::Any(nState), true );
+}
+
+sal_Bool UnoRadioButtonControl::getState()
+{
+ sal_Int16 nState = 0;
+ uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_STATE ) );
+ aVal >>= nState;
+ return nState != 0;
+}
+
+void UnoRadioButtonControl::itemStateChanged( const awt::ItemEvent& rEvent )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STATE ), uno::Any(static_cast<sal_Int16>(rEvent.Selected)), false );
+
+ // compatibility:
+ // in OOo 1.0.x, when the user clicked a radio button in a group of buttons, this resulted
+ // in _one_ itemStateChanged call for exactly the radio button which's state changed from
+ // "0" to "1".
+ // Nowadays, since the listener handling changed a lot towards 1.1 (the VCLXWindow reacts on more
+ // basic events from the VCL-windows, not anymore on the Link-based events like in 1.0.x), this
+ // isn't the case anymore: For instance, this method here gets called for the radio button
+ // which is being implicitly _de_selected, too. This is pretty bad for compatibility.
+ // Thus, we suppress all events with a new state other than "1". This is unlogical, and weird, when looking
+ // from a pure API perspective, but it's _compatible_ with older product versions, and this is
+ // all which matters here.
+ // #i14703#
+ if ( 1 == rEvent.Selected )
+ {
+ if ( maItemListeners.getLength() )
+ maItemListeners.itemStateChanged( rEvent );
+ }
+ // note that speaking strictly, this is wrong: When in 1.0.x, the user would have de-selected
+ // a radio button _without_ selecting another one, this would have caused a notification.
+ // With the change done here, this today won't cause a notification anymore.
+
+ // Fortunately, it's not possible for the user to de-select a radio button without selecting another on,
+ // at least not via the regular UI. It _would_ be possible via the Accessibility API, which
+ // counts as "user input", too. But in 1.0.x, there was no Accessibility API, so there is nothing
+ // to be inconsistent with.
+}
+
+awt::Size UnoRadioButtonControl::getMinimumSize( )
+{
+ return Impl_getMinimumSize();
+}
+
+awt::Size UnoRadioButtonControl::getPreferredSize( )
+{
+ return Impl_getPreferredSize();
+}
+
+awt::Size UnoRadioButtonControl::calcAdjustedSize( const awt::Size& rNewSize )
+{
+ return Impl_calcAdjustedSize( rNewSize );
+}
+
+OUString UnoRadioButtonControl::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoRadioButtonControl";
+}
+
+css::uno::Sequence<OUString> UnoRadioButtonControl::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlRadioButton", "stardiv.vcl.control.RadioButton" };
+ return comphelper::concatSequences( UnoControlBase::getSupportedServiceNames(), vals );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoRadioButtonControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoRadioButtonControl());
+}
+
+
+
+UnoControlCheckBoxModel::UnoControlCheckBoxModel( const Reference< XComponentContext >& rxContext )
+ :GraphicControlModel( rxContext )
+{
+ UNO_CONTROL_MODEL_REGISTER_PROPERTIES<VCLXCheckBox>();
+}
+
+OUString UnoControlCheckBoxModel::getServiceName()
+{
+ return "stardiv.vcl.controlmodel.CheckBox";
+}
+
+uno::Any UnoControlCheckBoxModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ switch ( nPropId )
+ {
+ case BASEPROPERTY_DEFAULTCONTROL:
+ return uno::Any( OUString( "stardiv.vcl.control.CheckBox" ) );
+
+ case BASEPROPERTY_VISUALEFFECT:
+ return uno::Any( sal_Int16(awt::VisualEffect::LOOK3D) );
+ }
+
+ return GraphicControlModel::ImplGetDefaultValue( nPropId );
+}
+
+::cppu::IPropertyArrayHelper& UnoControlCheckBoxModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+// beans::XMultiPropertySet
+uno::Reference< beans::XPropertySetInfo > UnoControlCheckBoxModel::getPropertySetInfo( )
+{
+ static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+OUString UnoControlCheckBoxModel::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoControlCheckBoxModel";
+}
+
+css::uno::Sequence<OUString> UnoControlCheckBoxModel::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlCheckBoxModel", "stardiv.vcl.controlmodel.CheckBox" };
+ return comphelper::concatSequences( GraphicControlModel::getSupportedServiceNames(), vals );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlCheckBoxModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoControlCheckBoxModel(context));
+}
+
+
+
+UnoCheckBoxControl::UnoCheckBoxControl()
+ :maItemListeners( *this ), maActionListeners( *this )
+{
+ maComponentInfos.nWidth = 100;
+ maComponentInfos.nHeight = 12;
+}
+
+OUString UnoCheckBoxControl::GetComponentServiceName() const
+{
+ return "checkbox";
+}
+
+void UnoCheckBoxControl::dispose()
+{
+ lang::EventObject aEvt;
+ aEvt.Source = static_cast<cppu::OWeakObject*>(this);
+ maItemListeners.disposeAndClear( aEvt );
+ UnoControlBase::dispose();
+}
+
+sal_Bool UnoCheckBoxControl::isTransparent()
+{
+ return true;
+}
+
+void UnoCheckBoxControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer > & rParentPeer )
+{
+ UnoControlBase::createPeer( rxToolkit, rParentPeer );
+
+ uno::Reference < awt::XCheckBox > xCheckBox( getPeer(), uno::UNO_QUERY );
+ xCheckBox->addItemListener( this );
+
+ uno::Reference < awt::XButton > xButton( getPeer(), uno::UNO_QUERY );
+ xButton->setActionCommand( maActionCommand );
+ if ( maActionListeners.getLength() )
+ xButton->addActionListener( &maActionListeners );
+}
+
+void UnoCheckBoxControl::addItemListener(const uno::Reference < awt::XItemListener > & l)
+{
+ maItemListeners.addInterface( l );
+}
+
+void UnoCheckBoxControl::removeItemListener(const uno::Reference < awt::XItemListener > & l)
+{
+ maItemListeners.removeInterface( l );
+}
+
+void UnoCheckBoxControl::addActionListener(const uno::Reference< awt::XActionListener > & l)
+{
+ maActionListeners.addInterface( l );
+ if( getPeer().is() && maActionListeners.getLength() == 1 )
+ {
+ uno::Reference < awt::XButton > xButton( getPeer(), uno::UNO_QUERY );
+ xButton->addActionListener( &maActionListeners );
+ }
+}
+
+void UnoCheckBoxControl::removeActionListener(const uno::Reference< awt::XActionListener > & l)
+{
+ if( getPeer().is() && maActionListeners.getLength() == 1 )
+ {
+ uno::Reference < awt::XButton > xButton( getPeer(), uno::UNO_QUERY );
+ xButton->removeActionListener( &maActionListeners );
+ }
+ maActionListeners.removeInterface( l );
+}
+
+void UnoCheckBoxControl::setActionCommand( const OUString& rCommand )
+{
+ maActionCommand = rCommand;
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XButton > xButton( getPeer(), uno::UNO_QUERY );
+ xButton->setActionCommand( rCommand );
+ }
+}
+
+
+void UnoCheckBoxControl::setLabel( const OUString& rLabel )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_LABEL ), uno::Any(rLabel), true );
+}
+
+void UnoCheckBoxControl::setState( sal_Int16 n )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STATE ), uno::Any(n), true );
+}
+
+sal_Int16 UnoCheckBoxControl::getState()
+{
+ sal_Int16 nState = 0;
+ uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_STATE ) );
+ aVal >>= nState;
+ return nState;
+}
+
+void UnoCheckBoxControl::enableTriState( sal_Bool b )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_TRISTATE ), uno::Any(b), true );
+}
+
+void UnoCheckBoxControl::itemStateChanged( const awt::ItemEvent& rEvent )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STATE ), uno::Any(static_cast<sal_Int16>(rEvent.Selected)), false );
+
+ if ( maItemListeners.getLength() )
+ maItemListeners.itemStateChanged( rEvent );
+}
+
+awt::Size UnoCheckBoxControl::getMinimumSize( )
+{
+ return Impl_getMinimumSize();
+}
+
+awt::Size UnoCheckBoxControl::getPreferredSize( )
+{
+ return Impl_getPreferredSize();
+}
+
+awt::Size UnoCheckBoxControl::calcAdjustedSize( const awt::Size& rNewSize )
+{
+ return Impl_calcAdjustedSize( rNewSize );
+}
+
+OUString UnoCheckBoxControl::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoCheckBoxControl";
+}
+
+css::uno::Sequence<OUString> UnoCheckBoxControl::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlCheckBox", "stardiv.vcl.control.CheckBox" };
+ return comphelper::concatSequences( UnoControlBase::getSupportedServiceNames(), vals );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoCheckBoxControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoCheckBoxControl());
+}
+
+
+
+UnoControlFixedHyperlinkModel::UnoControlFixedHyperlinkModel( const Reference< XComponentContext >& rxContext )
+ :UnoControlModel( rxContext )
+{
+ UNO_CONTROL_MODEL_REGISTER_PROPERTIES<VCLXFixedHyperlink>();
+}
+
+OUString UnoControlFixedHyperlinkModel::getServiceName()
+{
+ return "com.sun.star.awt.UnoControlFixedHyperlinkModel";
+}
+
+uno::Any UnoControlFixedHyperlinkModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
+ {
+ return uno::Any( OUString( "com.sun.star.awt.UnoControlFixedHyperlink" ) );
+ }
+ else if ( nPropId == BASEPROPERTY_BORDER )
+ {
+ return uno::Any(sal_Int16(0));
+ }
+ else if ( nPropId == BASEPROPERTY_URL )
+ {
+ return uno::Any( OUString() );
+ }
+
+ return UnoControlModel::ImplGetDefaultValue( nPropId );
+}
+
+::cppu::IPropertyArrayHelper& UnoControlFixedHyperlinkModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+// beans::XMultiPropertySet
+uno::Reference< beans::XPropertySetInfo > UnoControlFixedHyperlinkModel::getPropertySetInfo( )
+{
+ static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlFixedHyperlinkModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoControlFixedHyperlinkModel(context));
+}
+
+
+
+UnoFixedHyperlinkControl::UnoFixedHyperlinkControl()
+ :maActionListeners( *this )
+{
+ maComponentInfos.nWidth = 100;
+ maComponentInfos.nHeight = 12;
+}
+
+OUString UnoFixedHyperlinkControl::GetComponentServiceName() const
+{
+ return "fixedhyperlink";
+}
+
+// uno::XInterface
+uno::Any UnoFixedHyperlinkControl::queryAggregation( const uno::Type & rType )
+{
+ uno::Any aRet = ::cppu::queryInterface( rType,
+ static_cast< awt::XFixedHyperlink* >(this),
+ static_cast< awt::XLayoutConstrains* >(this) );
+ return (aRet.hasValue() ? aRet : UnoControlBase::queryAggregation( rType ));
+}
+
+IMPL_IMPLEMENTATION_ID( UnoFixedHyperlinkControl )
+
+// lang::XTypeProvider
+css::uno::Sequence< css::uno::Type > UnoFixedHyperlinkControl::getTypes()
+{
+ static const ::cppu::OTypeCollection aTypeList(
+ cppu::UnoType<css::lang::XTypeProvider>::get(),
+ cppu::UnoType<awt::XFixedHyperlink>::get(),
+ cppu::UnoType<awt::XLayoutConstrains>::get(),
+ UnoControlBase::getTypes()
+ );
+ return aTypeList.getTypes();
+}
+
+sal_Bool UnoFixedHyperlinkControl::isTransparent()
+{
+ return true;
+}
+
+void UnoFixedHyperlinkControl::setText( const OUString& Text )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_LABEL ), uno::Any(Text), true );
+}
+
+OUString UnoFixedHyperlinkControl::getText()
+{
+ return ImplGetPropertyValue_UString( BASEPROPERTY_LABEL );
+}
+
+void UnoFixedHyperlinkControl::setURL( const OUString& URL )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_URL ), uno::Any(URL), true );
+}
+
+OUString UnoFixedHyperlinkControl::getURL( )
+{
+ return ImplGetPropertyValue_UString( BASEPROPERTY_URL );
+}
+
+void UnoFixedHyperlinkControl::setAlignment( sal_Int16 nAlign )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_ALIGN ), uno::Any(nAlign), true );
+}
+
+sal_Int16 UnoFixedHyperlinkControl::getAlignment()
+{
+ sal_Int16 nAlign = 0;
+ if ( mxModel.is() )
+ {
+ uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_ALIGN ) );
+ aVal >>= nAlign;
+ }
+ return nAlign;
+}
+
+awt::Size UnoFixedHyperlinkControl::getMinimumSize( )
+{
+ return Impl_getMinimumSize();
+}
+
+awt::Size UnoFixedHyperlinkControl::getPreferredSize( )
+{
+ return Impl_getPreferredSize();
+}
+
+awt::Size UnoFixedHyperlinkControl::calcAdjustedSize( const awt::Size& rNewSize )
+{
+ return Impl_calcAdjustedSize( rNewSize );
+}
+
+void UnoFixedHyperlinkControl::dispose()
+{
+ lang::EventObject aEvt;
+ aEvt.Source = static_cast<cppu::OWeakObject*>(this);
+ maActionListeners.disposeAndClear( aEvt );
+ UnoControlBase::dispose();
+}
+
+void UnoFixedHyperlinkControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer > & rParentPeer )
+{
+ UnoControlBase::createPeer( rxToolkit, rParentPeer );
+
+ uno::Reference < awt::XFixedHyperlink > xFixedHyperlink( getPeer(), uno::UNO_QUERY );
+ if ( maActionListeners.getLength() )
+ xFixedHyperlink->addActionListener( &maActionListeners );
+}
+
+void UnoFixedHyperlinkControl::addActionListener(const uno::Reference< awt::XActionListener > & l)
+{
+ maActionListeners.addInterface( l );
+ if( getPeer().is() && maActionListeners.getLength() == 1 )
+ {
+ uno::Reference < awt::XFixedHyperlink > xFixedHyperlink( getPeer(), uno::UNO_QUERY );
+ xFixedHyperlink->addActionListener( &maActionListeners );
+ }
+}
+
+void UnoFixedHyperlinkControl::removeActionListener(const uno::Reference< awt::XActionListener > & l)
+{
+ if( getPeer().is() && maActionListeners.getLength() == 1 )
+ {
+ uno::Reference < awt::XFixedHyperlink > xFixedHyperlink( getPeer(), uno::UNO_QUERY );
+ xFixedHyperlink->removeActionListener( &maActionListeners );
+ }
+ maActionListeners.removeInterface( l );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoFixedHyperlinkControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoFixedHyperlinkControl());
+}
+
+
+
+UnoControlFixedTextModel::UnoControlFixedTextModel( const Reference< XComponentContext >& rxContext )
+ :UnoControlModel( rxContext )
+{
+ UNO_CONTROL_MODEL_REGISTER_PROPERTIES<VCLXFixedText>();
+}
+
+OUString UnoControlFixedTextModel::getServiceName()
+{
+ return "stardiv.vcl.controlmodel.FixedText";
+}
+
+uno::Any UnoControlFixedTextModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
+ {
+ return uno::Any( OUString( "stardiv.vcl.control.FixedText" ) );
+ }
+ else if ( nPropId == BASEPROPERTY_BORDER )
+ {
+ return uno::Any(sal_Int16(0));
+ }
+
+ return UnoControlModel::ImplGetDefaultValue( nPropId );
+}
+
+::cppu::IPropertyArrayHelper& UnoControlFixedTextModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+// beans::XMultiPropertySet
+uno::Reference< beans::XPropertySetInfo > UnoControlFixedTextModel::getPropertySetInfo( )
+{
+ static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+OUString UnoControlFixedTextModel::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoControlFixedTextModel";
+}
+
+css::uno::Sequence<OUString>
+UnoControlFixedTextModel::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlFixedTextModel", "stardiv.vcl.controlmodel.FixedText" };
+ return comphelper::concatSequences( UnoControlModel::getSupportedServiceNames(), vals );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlFixedTextModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoControlFixedTextModel(context));
+}
+
+
+
+UnoFixedTextControl::UnoFixedTextControl()
+{
+ maComponentInfos.nWidth = 100;
+ maComponentInfos.nHeight = 12;
+}
+
+OUString UnoFixedTextControl::GetComponentServiceName() const
+{
+ return "fixedtext";
+}
+
+// uno::XInterface
+uno::Any UnoFixedTextControl::queryAggregation( const uno::Type & rType )
+{
+ uno::Any aRet = ::cppu::queryInterface( rType,
+ static_cast< awt::XFixedText* >(this),
+ static_cast< awt::XLayoutConstrains* >(this) );
+ return (aRet.hasValue() ? aRet : UnoControlBase::queryAggregation( rType ));
+}
+
+IMPL_IMPLEMENTATION_ID( UnoFixedTextControl )
+
+// lang::XTypeProvider
+css::uno::Sequence< css::uno::Type > UnoFixedTextControl::getTypes()
+{
+ static const ::cppu::OTypeCollection aTypeList(
+ cppu::UnoType<css::lang::XTypeProvider>::get(),
+ cppu::UnoType<awt::XFixedText>::get(),
+ cppu::UnoType<awt::XLayoutConstrains>::get(),
+ UnoControlBase::getTypes()
+ );
+ return aTypeList.getTypes();
+}
+
+sal_Bool UnoFixedTextControl::isTransparent()
+{
+ return true;
+}
+
+void UnoFixedTextControl::setText( const OUString& Text )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_LABEL ), uno::Any(Text), true );
+}
+
+OUString UnoFixedTextControl::getText()
+{
+ return ImplGetPropertyValue_UString( BASEPROPERTY_LABEL );
+}
+
+void UnoFixedTextControl::setAlignment( sal_Int16 nAlign )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_ALIGN ), uno::Any(nAlign), true );
+}
+
+sal_Int16 UnoFixedTextControl::getAlignment()
+{
+ sal_Int16 nAlign = 0;
+ if ( mxModel.is() )
+ {
+ uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_ALIGN ) );
+ aVal >>= nAlign;
+ }
+ return nAlign;
+}
+
+awt::Size UnoFixedTextControl::getMinimumSize( )
+{
+ return Impl_getMinimumSize();
+}
+
+awt::Size UnoFixedTextControl::getPreferredSize( )
+{
+ return Impl_getPreferredSize();
+}
+
+awt::Size UnoFixedTextControl::calcAdjustedSize( const awt::Size& rNewSize )
+{
+ return Impl_calcAdjustedSize( rNewSize );
+}
+
+OUString UnoFixedTextControl::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoFixedTextControl";
+}
+
+css::uno::Sequence<OUString> UnoFixedTextControl::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlFixedText", "stardiv.vcl.control.FixedText" };
+ return comphelper::concatSequences( UnoControlBase::getSupportedServiceNames(), vals );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoFixedTextControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoFixedTextControl());
+}
+
+
+
+UnoControlGroupBoxModel::UnoControlGroupBoxModel( const Reference< XComponentContext >& rxContext )
+ :UnoControlModel( rxContext )
+{
+ ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
+ ImplRegisterProperty( BASEPROPERTY_ENABLED );
+ ImplRegisterProperty( BASEPROPERTY_ENABLEVISIBLE );
+ ImplRegisterProperty( BASEPROPERTY_FONTDESCRIPTOR );
+ ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
+ ImplRegisterProperty( BASEPROPERTY_HELPURL );
+ ImplRegisterProperty( BASEPROPERTY_LABEL );
+ ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
+ ImplRegisterProperty( BASEPROPERTY_WRITING_MODE );
+ ImplRegisterProperty( BASEPROPERTY_CONTEXT_WRITING_MODE );
+}
+
+OUString UnoControlGroupBoxModel::getServiceName()
+{
+ return "stardiv.vcl.controlmodel.GroupBox";
+}
+
+uno::Any UnoControlGroupBoxModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
+ {
+ return uno::Any(OUString( "stardiv.vcl.control.GroupBox" ) );
+ }
+ return UnoControlModel::ImplGetDefaultValue( nPropId );
+}
+
+::cppu::IPropertyArrayHelper& UnoControlGroupBoxModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+// beans::XMultiPropertySet
+uno::Reference< beans::XPropertySetInfo > UnoControlGroupBoxModel::getPropertySetInfo( )
+{
+ static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+OUString UnoControlGroupBoxModel::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoControlGroupBoxModel";
+}
+
+css::uno::Sequence<OUString> UnoControlGroupBoxModel::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlGroupBoxModel", "stardiv.vcl.controlmodel.GroupBox" };
+ return comphelper::concatSequences( UnoControlModel::getSupportedServiceNames(), vals );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlGroupBoxModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoControlGroupBoxModel(context));
+}
+
+
+
+UnoGroupBoxControl::UnoGroupBoxControl()
+{
+ maComponentInfos.nWidth = 100;
+ maComponentInfos.nHeight = 100;
+}
+
+OUString UnoGroupBoxControl::GetComponentServiceName() const
+{
+ return "groupbox";
+}
+
+sal_Bool UnoGroupBoxControl::isTransparent()
+{
+ return true;
+}
+
+OUString UnoGroupBoxControl::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoGroupBoxControl";
+}
+
+css::uno::Sequence<OUString> UnoGroupBoxControl::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlGroupBox", "stardiv.vcl.control.GroupBox" };
+ return comphelper::concatSequences( UnoControlBase::getSupportedServiceNames(), vals );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoGroupBoxControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoGroupBoxControl());
+}
+
+
+// = UnoControlListBoxModel_Data
+
+namespace {
+
+struct ListItem
+{
+ OUString ItemText;
+ OUString ItemImageURL;
+ Any ItemData;
+
+ ListItem()
+ {
+ }
+
+ explicit ListItem( const OUString& i_rItemText )
+ :ItemText( i_rItemText )
+ {
+ }
+};
+
+}
+
+typedef beans::Pair< OUString, OUString > UnoListItem;
+
+namespace {
+
+struct StripItemData
+{
+ UnoListItem operator()( const ListItem& i_rItem )
+ {
+ return UnoListItem( i_rItem.ItemText, i_rItem.ItemImageURL );
+ }
+};
+
+}
+
+struct UnoControlListBoxModel_Data
+{
+ explicit UnoControlListBoxModel_Data( UnoControlListBoxModel& i_rAntiImpl )
+ :m_bSettingLegacyProperty( false )
+ ,m_rAntiImpl( i_rAntiImpl )
+ {
+ }
+
+ sal_Int32 getItemCount() const { return sal_Int32( m_aListItems.size() ); }
+
+ const ListItem& getItem( const sal_Int32 i_nIndex ) const
+ {
+ if ( ( i_nIndex < 0 ) || ( o3tl::make_unsigned(i_nIndex) >= m_aListItems.size() ) )
+ throw IndexOutOfBoundsException( OUString(), m_rAntiImpl );
+ return m_aListItems[ i_nIndex ];
+ }
+
+ ListItem& getItem( const sal_Int32 i_nIndex )
+ {
+ return const_cast< ListItem& >( static_cast< const UnoControlListBoxModel_Data* >( this )->getItem( i_nIndex ) );
+ }
+
+ ListItem& insertItem( const sal_Int32 i_nIndex )
+ {
+ if ( ( i_nIndex < 0 ) || ( o3tl::make_unsigned(i_nIndex) > m_aListItems.size() ) )
+ throw IndexOutOfBoundsException( OUString(), m_rAntiImpl );
+ return *m_aListItems.insert( m_aListItems.begin() + i_nIndex, ListItem() );
+ }
+
+ Sequence< UnoListItem > getAllItems() const
+ {
+ Sequence< UnoListItem > aItems( sal_Int32( m_aListItems.size() ) );
+ ::std::transform( m_aListItems.begin(), m_aListItems.end(), aItems.getArray(), StripItemData() );
+ return aItems;
+ }
+
+ void copyItems( const UnoControlListBoxModel_Data& i_copySource )
+ {
+ m_aListItems = i_copySource.m_aListItems;
+ }
+
+ void setAllItems( ::std::vector< ListItem >&& i_rItems )
+ {
+ m_aListItems = std::move(i_rItems);
+ }
+
+ void removeItem( const sal_Int32 i_nIndex )
+ {
+ if ( ( i_nIndex < 0 ) || ( o3tl::make_unsigned(i_nIndex) >= m_aListItems.size() ) )
+ throw IndexOutOfBoundsException( OUString(), m_rAntiImpl );
+ m_aListItems.erase( m_aListItems.begin() + i_nIndex );
+ }
+
+ void removeAllItems()
+ {
+ std::vector<ListItem>().swap(m_aListItems);
+ }
+
+public:
+ bool m_bSettingLegacyProperty;
+
+private:
+ UnoControlListBoxModel& m_rAntiImpl;
+ ::std::vector< ListItem > m_aListItems;
+};
+
+
+// = UnoControlListBoxModel
+
+
+UnoControlListBoxModel::UnoControlListBoxModel( const Reference< XComponentContext >& rxContext, ConstructorMode const i_mode )
+ :UnoControlListBoxModel_Base( rxContext )
+ ,m_xData( new UnoControlListBoxModel_Data( *this ) )
+ ,m_aItemListListeners( GetMutex() )
+{
+ if ( i_mode == ConstructDefault )
+ {
+ UNO_CONTROL_MODEL_REGISTER_PROPERTIES<VCLXListBox>();
+ }
+}
+
+UnoControlListBoxModel::UnoControlListBoxModel( const UnoControlListBoxModel& i_rSource )
+ :UnoControlListBoxModel_Base( i_rSource )
+ ,m_xData( new UnoControlListBoxModel_Data( *this ) )
+ ,m_aItemListListeners( GetMutex() )
+{
+ m_xData->copyItems( *i_rSource.m_xData );
+}
+UnoControlListBoxModel::~UnoControlListBoxModel()
+{
+}
+
+OUString UnoControlListBoxModel::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoControlListBoxModel";
+}
+
+css::uno::Sequence<OUString> UnoControlListBoxModel::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlListBoxModel", "stardiv.vcl.controlmodel.ListBox" };
+ return comphelper::concatSequences( UnoControlModel::getSupportedServiceNames(), vals );
+}
+
+OUString UnoControlListBoxModel::getServiceName()
+{
+ return "stardiv.vcl.controlmodel.ListBox";
+}
+
+
+uno::Any UnoControlListBoxModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
+ {
+ return uno::Any( OUString( "stardiv.vcl.control.ListBox" ) );
+ }
+ return UnoControlModel::ImplGetDefaultValue( nPropId );
+}
+
+
+::cppu::IPropertyArrayHelper& UnoControlListBoxModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+
+// beans::XMultiPropertySet
+uno::Reference< beans::XPropertySetInfo > UnoControlListBoxModel::getPropertySetInfo( )
+{
+ static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+
+namespace
+{
+ struct CreateListItem
+ {
+ ListItem operator()( const OUString& i_rItemText )
+ {
+ return ListItem( i_rItemText );
+ }
+ };
+}
+
+
+void SAL_CALL UnoControlListBoxModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const uno::Any& rValue )
+{
+ UnoControlModel::setFastPropertyValue_NoBroadcast( nHandle, rValue );
+
+ if ( nHandle != BASEPROPERTY_STRINGITEMLIST )
+ return;
+
+ // reset selection
+ uno::Sequence<sal_Int16> aSeq;
+ setDependentFastPropertyValue( BASEPROPERTY_SELECTEDITEMS, uno::Any(aSeq) );
+
+ if ( m_xData->m_bSettingLegacyProperty )
+ return;
+
+ // synchronize the legacy StringItemList property with our list items
+ Sequence< OUString > aStringItemList;
+ Any aPropValue;
+ getFastPropertyValue( aPropValue, BASEPROPERTY_STRINGITEMLIST );
+ OSL_VERIFY( aPropValue >>= aStringItemList );
+
+ ::std::vector< ListItem > aItems( aStringItemList.getLength() );
+ ::std::transform(
+ std::cbegin(aStringItemList),
+ std::cend(aStringItemList),
+ aItems.begin(),
+ CreateListItem()
+ );
+ m_xData->setAllItems( std::move(aItems) );
+
+ // since an XItemListListener does not have a "all items modified" or some such method,
+ // we simulate this by notifying removal of all items, followed by insertion of all new
+ // items
+ lang::EventObject aEvent;
+ aEvent.Source = *this;
+ m_aItemListListeners.notifyEach( &XItemListListener::itemListChanged, aEvent );
+ // TODO: OPropertySetHelper calls into this method with the mutex locked ...
+ // which is wrong for the above notifications ...
+}
+
+
+void UnoControlListBoxModel::ImplNormalizePropertySequence( const sal_Int32 _nCount, sal_Int32* _pHandles,
+ uno::Any* _pValues, sal_Int32* _pValidHandles ) const
+{
+ // dependencies we know:
+ // BASEPROPERTY_STRINGITEMLIST->BASEPROPERTY_SELECTEDITEMS
+ ImplEnsureHandleOrder( _nCount, _pHandles, _pValues, BASEPROPERTY_STRINGITEMLIST, BASEPROPERTY_SELECTEDITEMS );
+ // BASEPROPERTY_STRINGITEMLIST->BASEPROPERTY_TYPEDITEMLIST
+ ImplEnsureHandleOrder( _nCount, _pHandles, _pValues, BASEPROPERTY_STRINGITEMLIST, BASEPROPERTY_TYPEDITEMLIST );
+
+ UnoControlModel::ImplNormalizePropertySequence( _nCount, _pHandles, _pValues, _pValidHandles );
+}
+
+
+::sal_Int32 SAL_CALL UnoControlListBoxModel::getItemCount()
+{
+ ::osl::MutexGuard aGuard( GetMutex() );
+ return m_xData->getItemCount();
+}
+
+
+void SAL_CALL UnoControlListBoxModel::insertItem( ::sal_Int32 i_nPosition, const OUString& i_rItemText, const OUString& i_rItemImageURL )
+{
+ ::osl::ClearableMutexGuard aGuard( GetMutex() );
+ // SYNCHRONIZED ----->
+ ListItem& rItem( m_xData->insertItem( i_nPosition ) );
+ rItem.ItemText = i_rItemText;
+ rItem.ItemImageURL = i_rItemImageURL;
+
+ impl_handleInsert( i_nPosition, i_rItemText, i_rItemImageURL, aGuard );
+ // <----- SYNCHRONIZED
+}
+
+
+void SAL_CALL UnoControlListBoxModel::insertItemText( ::sal_Int32 i_nPosition, const OUString& i_rItemText )
+{
+ ::osl::ClearableMutexGuard aGuard( GetMutex() );
+ // SYNCHRONIZED ----->
+ ListItem& rItem( m_xData->insertItem( i_nPosition ) );
+ rItem.ItemText = i_rItemText;
+
+ impl_handleInsert( i_nPosition, i_rItemText, ::std::optional< OUString >(), aGuard );
+ // <----- SYNCHRONIZED
+}
+
+
+void SAL_CALL UnoControlListBoxModel::insertItemImage( ::sal_Int32 i_nPosition, const OUString& i_rItemImageURL )
+{
+ ::osl::ClearableMutexGuard aGuard( GetMutex() );
+ // SYNCHRONIZED ----->
+ ListItem& rItem( m_xData->insertItem( i_nPosition ) );
+ rItem.ItemImageURL = i_rItemImageURL;
+
+ impl_handleInsert( i_nPosition, ::std::optional< OUString >(), i_rItemImageURL, aGuard );
+ // <----- SYNCHRONIZED
+}
+
+
+void SAL_CALL UnoControlListBoxModel::removeItem( ::sal_Int32 i_nPosition )
+{
+ ::osl::ClearableMutexGuard aGuard( GetMutex() );
+ // SYNCHRONIZED ----->
+ m_xData->removeItem( i_nPosition );
+
+ impl_handleRemove( i_nPosition, aGuard );
+ // <----- SYNCHRONIZED
+}
+
+
+void SAL_CALL UnoControlListBoxModel::removeAllItems( )
+{
+ ::osl::ClearableMutexGuard aGuard( GetMutex() );
+ // SYNCHRONIZED ----->
+ m_xData->removeAllItems();
+
+ impl_handleRemove( -1, aGuard );
+ // <----- SYNCHRONIZED
+}
+
+
+void SAL_CALL UnoControlListBoxModel::setItemText( ::sal_Int32 i_nPosition, const OUString& i_rItemText )
+{
+ ::osl::ClearableMutexGuard aGuard( GetMutex() );
+ // SYNCHRONIZED ----->
+ ListItem& rItem( m_xData->getItem( i_nPosition ) );
+ rItem.ItemText = i_rItemText;
+
+ impl_handleModify( i_nPosition, i_rItemText, ::std::optional< OUString >(), aGuard );
+ // <----- SYNCHRONIZED
+}
+
+
+void SAL_CALL UnoControlListBoxModel::setItemImage( ::sal_Int32 i_nPosition, const OUString& i_rItemImageURL )
+{
+ ::osl::ClearableMutexGuard aGuard( GetMutex() );
+ // SYNCHRONIZED ----->
+ ListItem& rItem( m_xData->getItem( i_nPosition ) );
+ rItem.ItemImageURL = i_rItemImageURL;
+
+ impl_handleModify( i_nPosition, ::std::optional< OUString >(), i_rItemImageURL, aGuard );
+ // <----- SYNCHRONIZED
+}
+
+
+void SAL_CALL UnoControlListBoxModel::setItemTextAndImage( ::sal_Int32 i_nPosition, const OUString& i_rItemText, const OUString& i_rItemImageURL )
+{
+ ::osl::ClearableMutexGuard aGuard( GetMutex() );
+ // SYNCHRONIZED ----->
+ ListItem& rItem( m_xData->getItem( i_nPosition ) );
+ rItem.ItemText = i_rItemText;
+ rItem.ItemImageURL = i_rItemImageURL;
+
+ impl_handleModify( i_nPosition, i_rItemText, i_rItemImageURL, aGuard );
+ // <----- SYNCHRONIZED
+}
+
+
+void SAL_CALL UnoControlListBoxModel::setItemData( ::sal_Int32 i_nPosition, const Any& i_rDataValue )
+{
+ osl::MutexGuard aGuard( GetMutex() );
+ ListItem& rItem( m_xData->getItem( i_nPosition ) );
+ rItem.ItemData = i_rDataValue;
+}
+
+
+OUString SAL_CALL UnoControlListBoxModel::getItemText( ::sal_Int32 i_nPosition )
+{
+ ::osl::MutexGuard aGuard( GetMutex() );
+ const ListItem& rItem( m_xData->getItem( i_nPosition ) );
+ return rItem.ItemText;
+}
+
+
+OUString SAL_CALL UnoControlListBoxModel::getItemImage( ::sal_Int32 i_nPosition )
+{
+ ::osl::MutexGuard aGuard( GetMutex() );
+ const ListItem& rItem( m_xData->getItem( i_nPosition ) );
+ return rItem.ItemImageURL;
+}
+
+
+beans::Pair< OUString, OUString > SAL_CALL UnoControlListBoxModel::getItemTextAndImage( ::sal_Int32 i_nPosition )
+{
+ ::osl::MutexGuard aGuard( GetMutex() );
+ const ListItem& rItem( m_xData->getItem( i_nPosition ) );
+ return beans::Pair< OUString, OUString >( rItem.ItemText, rItem.ItemImageURL );
+}
+
+
+Any SAL_CALL UnoControlListBoxModel::getItemData( ::sal_Int32 i_nPosition )
+{
+ osl::MutexGuard aGuard( GetMutex() );
+ const ListItem& rItem( m_xData->getItem( i_nPosition ) );
+ return rItem.ItemData;
+}
+
+
+Sequence< beans::Pair< OUString, OUString > > SAL_CALL UnoControlListBoxModel::getAllItems( )
+{
+ ::osl::MutexGuard aGuard( GetMutex() );
+ return m_xData->getAllItems();
+}
+
+
+void SAL_CALL UnoControlListBoxModel::addItemListListener( const uno::Reference< awt::XItemListListener >& i_Listener )
+{
+ if ( i_Listener.is() )
+ m_aItemListListeners.addInterface( i_Listener );
+}
+
+
+void SAL_CALL UnoControlListBoxModel::removeItemListListener( const uno::Reference< awt::XItemListListener >& i_Listener )
+{
+ if ( i_Listener.is() )
+ m_aItemListListeners.removeInterface( i_Listener );
+}
+
+
+void UnoControlListBoxModel::impl_getStringItemList( ::std::vector< OUString >& o_rStringItems ) const
+{
+ Sequence< OUString > aStringItemList;
+ Any aPropValue;
+ getFastPropertyValue( aPropValue, BASEPROPERTY_STRINGITEMLIST );
+ OSL_VERIFY( aPropValue >>= aStringItemList );
+
+ comphelper::sequenceToContainer(o_rStringItems, aStringItemList);
+}
+
+
+void UnoControlListBoxModel::impl_setStringItemList_nolck( const ::std::vector< OUString >& i_rStringItems )
+{
+ Sequence< OUString > aStringItems( comphelper::containerToSequence(i_rStringItems) );
+ m_xData->m_bSettingLegacyProperty = true;
+ try
+ {
+ setFastPropertyValue( BASEPROPERTY_STRINGITEMLIST, uno::Any( aStringItems ) );
+ }
+ catch( const Exception& )
+ {
+ m_xData->m_bSettingLegacyProperty = false;
+ throw;
+ }
+ m_xData->m_bSettingLegacyProperty = false;
+}
+
+
+void UnoControlListBoxModel::impl_handleInsert( const sal_Int32 i_nItemPosition, const ::std::optional< OUString >& i_rItemText,
+ const ::std::optional< OUString >& i_rItemImageURL, ::osl::ClearableMutexGuard& i_rClearBeforeNotify )
+{
+ // SYNCHRONIZED ----->
+ // sync with legacy StringItemList property
+ ::std::vector< OUString > aStringItems;
+ impl_getStringItemList( aStringItems );
+ OSL_ENSURE( o3tl::make_unsigned( i_nItemPosition ) <= aStringItems.size(), "UnoControlListBoxModel::impl_handleInsert" );
+ if ( o3tl::make_unsigned( i_nItemPosition ) <= aStringItems.size() )
+ {
+ const OUString sItemText( !!i_rItemText ? *i_rItemText : OUString() );
+ aStringItems.insert( aStringItems.begin() + i_nItemPosition, sItemText );
+ }
+
+ i_rClearBeforeNotify.clear();
+ // <----- SYNCHRONIZED
+ impl_setStringItemList_nolck( aStringItems );
+
+ // notify ItemListListeners
+ impl_notifyItemListEvent_nolck( i_nItemPosition, i_rItemText, i_rItemImageURL, &XItemListListener::listItemInserted );
+}
+
+
+void UnoControlListBoxModel::impl_handleRemove( const sal_Int32 i_nItemPosition, ::osl::ClearableMutexGuard& i_rClearBeforeNotify )
+{
+ // SYNCHRONIZED ----->
+ const bool bAllItems = ( i_nItemPosition < 0 );
+ // sync with legacy StringItemList property
+ ::std::vector< OUString > aStringItems;
+ impl_getStringItemList( aStringItems );
+ if ( !bAllItems )
+ {
+ OSL_ENSURE( o3tl::make_unsigned( i_nItemPosition ) < aStringItems.size(), "UnoControlListBoxModel::impl_handleRemove" );
+ if ( o3tl::make_unsigned( i_nItemPosition ) < aStringItems.size() )
+ {
+ aStringItems.erase( aStringItems.begin() + i_nItemPosition );
+ }
+ }
+ else
+ {
+ aStringItems.resize(0);
+ }
+
+ i_rClearBeforeNotify.clear();
+ // <----- SYNCHRONIZED
+ impl_setStringItemList_nolck( aStringItems );
+
+ // notify ItemListListeners
+ if ( bAllItems )
+ {
+ EventObject aEvent( *this );
+ m_aItemListListeners.notifyEach( &XItemListListener::allItemsRemoved, aEvent );
+ }
+ else
+ {
+ impl_notifyItemListEvent_nolck( i_nItemPosition, ::std::optional< OUString >(), ::std::optional< OUString >(),
+ &XItemListListener::listItemRemoved );
+ }
+}
+
+
+void UnoControlListBoxModel::impl_handleModify( const sal_Int32 i_nItemPosition, const ::std::optional< OUString >& i_rItemText,
+ const ::std::optional< OUString >& i_rItemImageURL, ::osl::ClearableMutexGuard& i_rClearBeforeNotify )
+{
+ // SYNCHRONIZED ----->
+ if ( !!i_rItemText )
+ {
+ // sync with legacy StringItemList property
+ ::std::vector< OUString > aStringItems;
+ impl_getStringItemList( aStringItems );
+ OSL_ENSURE( o3tl::make_unsigned( i_nItemPosition ) < aStringItems.size(), "UnoControlListBoxModel::impl_handleModify" );
+ if ( o3tl::make_unsigned( i_nItemPosition ) < aStringItems.size() )
+ {
+ aStringItems[ i_nItemPosition] = *i_rItemText;
+ }
+
+ i_rClearBeforeNotify.clear();
+ // <----- SYNCHRONIZED
+ impl_setStringItemList_nolck( aStringItems );
+ }
+ else
+ {
+ i_rClearBeforeNotify.clear();
+ // <----- SYNCHRONIZED
+ }
+
+ // notify ItemListListeners
+ impl_notifyItemListEvent_nolck( i_nItemPosition, i_rItemText, i_rItemImageURL, &XItemListListener::listItemModified );
+}
+
+
+void UnoControlListBoxModel::impl_notifyItemListEvent_nolck( const sal_Int32 i_nItemPosition, const ::std::optional< OUString >& i_rItemText,
+ const ::std::optional< OUString >& i_rItemImageURL,
+ void ( SAL_CALL XItemListListener::*NotificationMethod )( const ItemListEvent& ) )
+{
+ ItemListEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.ItemPosition = i_nItemPosition;
+ if ( !!i_rItemText )
+ {
+ aEvent.ItemText.IsPresent = true;
+ aEvent.ItemText.Value = *i_rItemText;
+ }
+ if ( !!i_rItemImageURL )
+ {
+ aEvent.ItemImageURL.IsPresent = true;
+ aEvent.ItemImageURL.Value = *i_rItemImageURL;
+ }
+
+ m_aItemListListeners.notifyEach( NotificationMethod, aEvent );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlListBoxModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoControlListBoxModel(context));
+}
+
+
+
+UnoListBoxControl::UnoListBoxControl()
+ :maActionListeners( *this )
+ ,maItemListeners( *this )
+{
+ maComponentInfos.nWidth = 100;
+ maComponentInfos.nHeight = 12;
+}
+
+OUString UnoListBoxControl::GetComponentServiceName() const
+{
+ return "listbox";
+}
+
+OUString UnoListBoxControl::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoListBoxControl";
+}
+
+css::uno::Sequence<OUString> UnoListBoxControl::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlListBox", "stardiv.vcl.control.ListBox" };
+ return comphelper::concatSequences( UnoControlBase::getSupportedServiceNames(), vals);
+}
+
+void UnoListBoxControl::dispose()
+{
+ lang::EventObject aEvt;
+ aEvt.Source = static_cast<cppu::OWeakObject*>(this);
+ maActionListeners.disposeAndClear( aEvt );
+ maItemListeners.disposeAndClear( aEvt );
+ UnoControl::dispose();
+}
+
+void UnoListBoxControl::ImplUpdateSelectedItemsProperty()
+{
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XListBox > xListBox( getPeer(), uno::UNO_QUERY );
+ DBG_ASSERT( xListBox.is(), "XListBox?" );
+
+ uno::Sequence<sal_Int16> aSeq = xListBox->getSelectedItemsPos();
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_SELECTEDITEMS ), uno::Any(aSeq), false );
+ }
+}
+
+void UnoListBoxControl::updateFromModel()
+{
+ UnoControlBase::updateFromModel();
+
+ Reference< XItemListListener > xItemListListener( getPeer(), UNO_QUERY );
+ ENSURE_OR_RETURN_VOID( xItemListListener.is(), "UnoListBoxControl::updateFromModel: a peer which is no ItemListListener?!" );
+
+ EventObject aEvent( getModel() );
+ xItemListListener->itemListChanged( aEvent );
+
+ // notify the change of the SelectedItems property, again. While our base class, in updateFromModel,
+ // already did this, our peer(s) can only legitimately set the selection after they have the string
+ // item list, which we just notified with the itemListChanged call.
+ const OUString& sSelectedItemsPropName( GetPropertyName( BASEPROPERTY_SELECTEDITEMS ) );
+ ImplSetPeerProperty( sSelectedItemsPropName, ImplGetPropertyValue( sSelectedItemsPropName ) );
+}
+
+void UnoListBoxControl::ImplSetPeerProperty( const OUString& rPropName, const uno::Any& rVal )
+{
+ if ( rPropName == GetPropertyName( BASEPROPERTY_STRINGITEMLIST ) )
+ // do not forward this to our peer. We are a XItemListListener at our model, and changes in the string item
+ // list (which is a legacy property) will, later, arrive as changes in the ItemList. Those latter changes
+ // will be forwarded to the peer, which will update itself accordingly.
+ return;
+
+ UnoControl::ImplSetPeerProperty( rPropName, rVal );
+}
+
+void UnoListBoxControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer > & rParentPeer )
+{
+ UnoControl::createPeer( rxToolkit, rParentPeer );
+
+ uno::Reference < awt::XListBox > xListBox( getPeer(), uno::UNO_QUERY );
+ xListBox->addItemListener( this );
+
+ if ( maActionListeners.getLength() )
+ xListBox->addActionListener( &maActionListeners );
+}
+
+void UnoListBoxControl::addActionListener(const uno::Reference< awt::XActionListener > & l)
+{
+ maActionListeners.addInterface( l );
+ if( getPeer().is() && maActionListeners.getLength() == 1 )
+ {
+ uno::Reference < awt::XListBox > xListBox( getPeer(), uno::UNO_QUERY );
+ xListBox->addActionListener( &maActionListeners );
+ }
+}
+
+void UnoListBoxControl::removeActionListener(const uno::Reference< awt::XActionListener > & l)
+{
+ if( getPeer().is() && maActionListeners.getLength() == 1 )
+ {
+ uno::Reference < awt::XListBox > xListBox( getPeer(), uno::UNO_QUERY );
+ xListBox->removeActionListener( &maActionListeners );
+ }
+ maActionListeners.removeInterface( l );
+}
+
+void UnoListBoxControl::addItemListener(const uno::Reference < awt::XItemListener > & l)
+{
+ maItemListeners.addInterface( l );
+}
+
+void UnoListBoxControl::removeItemListener(const uno::Reference < awt::XItemListener > & l)
+{
+ maItemListeners.removeInterface( l );
+}
+
+void UnoListBoxControl::addItem( const OUString& aItem, sal_Int16 nPos )
+{
+ uno::Sequence<OUString> aSeq { aItem };
+ addItems( aSeq, nPos );
+}
+
+void UnoListBoxControl::addItems( const uno::Sequence< OUString>& aItems, sal_Int16 nPos )
+{
+ uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ) );
+ uno::Sequence< OUString> aSeq;
+ aVal >>= aSeq;
+ sal_uInt16 nNewItems = static_cast<sal_uInt16>(aItems.getLength());
+ sal_uInt16 nOldLen = static_cast<sal_uInt16>(aSeq.getLength());
+ sal_uInt16 nNewLen = nOldLen + nNewItems;
+
+ uno::Sequence< OUString> aNewSeq( nNewLen );
+
+ if ( ( nPos < 0 ) || ( nPos > nOldLen ) )
+ nPos = nOldLen;
+
+ // Items before the Paste-Position
+ auto it = std::copy(std::cbegin(aSeq), std::next(std::cbegin(aSeq), nPos), aNewSeq.getArray());
+
+ // New Items
+ it = std::copy(aItems.begin(), aItems.end(), it);
+
+ // Rest of old Items
+ std::copy(std::next(std::cbegin(aSeq), nPos), std::cend(aSeq), it);
+
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ), uno::Any(aNewSeq), true );
+}
+
+void UnoListBoxControl::removeItems( sal_Int16 nPos, sal_Int16 nCount )
+{
+ uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ) );
+ uno::Sequence< OUString> aSeq;
+ aVal >>= aSeq;
+ sal_uInt16 nOldLen = static_cast<sal_uInt16>(aSeq.getLength());
+ if ( !(nOldLen && ( nPos < nOldLen )) )
+ return;
+
+ if ( nCount > ( nOldLen-nPos ) )
+ nCount = nOldLen-nPos;
+
+ sal_uInt16 nNewLen = nOldLen - nCount;
+
+ uno::Sequence< OUString> aNewSeq( nNewLen );
+
+ // Items before the Remove-Position
+ auto it = std::copy(std::cbegin(aSeq), std::next(std::cbegin(aSeq), nPos), aNewSeq.getArray());
+
+ // Rest of Items
+ std::copy(std::next(std::cbegin(aSeq), nPos + nCount), std::cend(aSeq), it);
+
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ), uno::Any(aNewSeq), true );
+}
+
+sal_Int16 UnoListBoxControl::getItemCount()
+{
+ uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ) );
+ uno::Sequence< OUString> aSeq;
+ aVal >>= aSeq;
+ return static_cast<sal_Int16>(aSeq.getLength());
+}
+
+OUString UnoListBoxControl::getItem( sal_Int16 nPos )
+{
+ OUString aItem;
+ uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ) );
+ uno::Sequence< OUString> aSeq;
+ aVal >>= aSeq;
+ if ( nPos < aSeq.getLength() )
+ aItem = aSeq[nPos];
+ return aItem;
+}
+
+uno::Sequence< OUString> UnoListBoxControl::getItems()
+{
+ uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ) );
+ uno::Sequence< OUString> aSeq;
+ aVal >>= aSeq;
+ return aSeq;
+}
+
+sal_Int16 UnoListBoxControl::getSelectedItemPos()
+{
+ sal_Int16 n = -1;
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XListBox > xListBox( getPeer(), uno::UNO_QUERY );
+ n = xListBox->getSelectedItemPos();
+ }
+ return n;
+}
+
+uno::Sequence<sal_Int16> UnoListBoxControl::getSelectedItemsPos()
+{
+ uno::Sequence<sal_Int16> aSeq;
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XListBox > xListBox( getPeer(), uno::UNO_QUERY );
+ aSeq = xListBox->getSelectedItemsPos();
+ }
+ return aSeq;
+}
+
+OUString UnoListBoxControl::getSelectedItem()
+{
+ OUString aItem;
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XListBox > xListBox( getPeer(), uno::UNO_QUERY );
+ aItem = xListBox->getSelectedItem();
+ }
+ return aItem;
+}
+
+uno::Sequence< OUString> UnoListBoxControl::getSelectedItems()
+{
+ uno::Sequence< OUString> aSeq;
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XListBox > xListBox( getPeer(), uno::UNO_QUERY );
+ aSeq = xListBox->getSelectedItems();
+ }
+ return aSeq;
+}
+
+void UnoListBoxControl::selectItemPos( sal_Int16 nPos, sal_Bool bSelect )
+{
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XListBox > xListBox( getPeer(), uno::UNO_QUERY );
+ xListBox->selectItemPos( nPos, bSelect );
+ }
+ ImplUpdateSelectedItemsProperty();
+}
+
+void UnoListBoxControl::selectItemsPos( const uno::Sequence<sal_Int16>& aPositions, sal_Bool bSelect )
+{
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XListBox > xListBox( getPeer(), uno::UNO_QUERY );
+ xListBox->selectItemsPos( aPositions, bSelect );
+ }
+ ImplUpdateSelectedItemsProperty();
+}
+
+void UnoListBoxControl::selectItem( const OUString& aItem, sal_Bool bSelect )
+{
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XListBox > xListBox( getPeer(), uno::UNO_QUERY );
+ xListBox->selectItem( aItem, bSelect );
+ }
+ ImplUpdateSelectedItemsProperty();
+}
+
+void UnoListBoxControl::makeVisible( sal_Int16 nEntry )
+{
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XListBox > xListBox( getPeer(), uno::UNO_QUERY );
+ xListBox->makeVisible( nEntry );
+ }
+}
+
+void UnoListBoxControl::setDropDownLineCount( sal_Int16 nLines )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_LINECOUNT ), uno::Any(nLines), true );
+}
+
+sal_Int16 UnoListBoxControl::getDropDownLineCount()
+{
+ return ImplGetPropertyValue_INT16( BASEPROPERTY_LINECOUNT );
+}
+
+sal_Bool UnoListBoxControl::isMutipleMode()
+{
+ return ImplGetPropertyValue_BOOL( BASEPROPERTY_MULTISELECTION );
+}
+
+void UnoListBoxControl::setMultipleMode( sal_Bool bMulti )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_MULTISELECTION ), uno::Any(bMulti), true );
+}
+
+void UnoListBoxControl::itemStateChanged( const awt::ItemEvent& rEvent )
+{
+ ImplUpdateSelectedItemsProperty();
+ if ( maItemListeners.getLength() )
+ {
+ try
+ {
+ maItemListeners.itemStateChanged( rEvent );
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "toolkit", "UnoListBoxControl::itemStateChanged");
+ }
+ }
+}
+
+awt::Size UnoListBoxControl::getMinimumSize( )
+{
+ return Impl_getMinimumSize();
+}
+
+awt::Size UnoListBoxControl::getPreferredSize( )
+{
+ return Impl_getPreferredSize();
+}
+
+awt::Size UnoListBoxControl::calcAdjustedSize( const awt::Size& rNewSize )
+{
+ return Impl_calcAdjustedSize( rNewSize );
+}
+
+awt::Size UnoListBoxControl::getMinimumSize( sal_Int16 nCols, sal_Int16 nLines )
+{
+ return Impl_getMinimumSize( nCols, nLines );
+}
+
+void UnoListBoxControl::getColumnsAndLines( sal_Int16& nCols, sal_Int16& nLines )
+{
+ Impl_getColumnsAndLines( nCols, nLines );
+}
+
+sal_Bool SAL_CALL UnoListBoxControl::setModel( const uno::Reference< awt::XControlModel >& i_rModel )
+{
+ ::osl::MutexGuard aGuard( GetMutex() );
+
+ const Reference< XItemList > xOldItems( getModel(), UNO_QUERY );
+ OSL_ENSURE( xOldItems.is() || !getModel().is(), "UnoListBoxControl::setModel: illegal old model!" );
+ const Reference< XItemList > xNewItems( i_rModel, UNO_QUERY );
+ OSL_ENSURE( xNewItems.is() || !i_rModel.is(), "UnoListBoxControl::setModel: illegal new model!" );
+
+ if ( !UnoListBoxControl_Base::setModel( i_rModel ) )
+ return false;
+
+ if ( xOldItems.is() )
+ xOldItems->removeItemListListener( this );
+ if ( xNewItems.is() )
+ xNewItems->addItemListListener( this );
+
+ return true;
+}
+
+void SAL_CALL UnoListBoxControl::listItemInserted( const awt::ItemListEvent& i_rEvent )
+{
+ const Reference< XItemListListener > xPeerListener( getPeer(), UNO_QUERY );
+ OSL_ENSURE( xPeerListener.is() || !getPeer().is(), "UnoListBoxControl::listItemInserted: invalid peer!" );
+ if ( xPeerListener.is() )
+ xPeerListener->listItemInserted( i_rEvent );
+}
+
+void SAL_CALL UnoListBoxControl::listItemRemoved( const awt::ItemListEvent& i_rEvent )
+{
+ const Reference< XItemListListener > xPeerListener( getPeer(), UNO_QUERY );
+ OSL_ENSURE( xPeerListener.is() || !getPeer().is(), "UnoListBoxControl::listItemRemoved: invalid peer!" );
+ if ( xPeerListener.is() )
+ xPeerListener->listItemRemoved( i_rEvent );
+}
+
+void SAL_CALL UnoListBoxControl::listItemModified( const awt::ItemListEvent& i_rEvent )
+{
+ const Reference< XItemListListener > xPeerListener( getPeer(), UNO_QUERY );
+ OSL_ENSURE( xPeerListener.is() || !getPeer().is(), "UnoListBoxControl::listItemModified: invalid peer!" );
+ if ( xPeerListener.is() )
+ xPeerListener->listItemModified( i_rEvent );
+}
+
+void SAL_CALL UnoListBoxControl::allItemsRemoved( const lang::EventObject& i_rEvent )
+{
+ const Reference< XItemListListener > xPeerListener( getPeer(), UNO_QUERY );
+ OSL_ENSURE( xPeerListener.is() || !getPeer().is(), "UnoListBoxControl::allItemsRemoved: invalid peer!" );
+ if ( xPeerListener.is() )
+ xPeerListener->allItemsRemoved( i_rEvent );
+}
+
+void SAL_CALL UnoListBoxControl::itemListChanged( const lang::EventObject& i_rEvent )
+{
+ const Reference< XItemListListener > xPeerListener( getPeer(), UNO_QUERY );
+ OSL_ENSURE( xPeerListener.is() || !getPeer().is(), "UnoListBoxControl::itemListChanged: invalid peer!" );
+ if ( xPeerListener.is() )
+ xPeerListener->itemListChanged( i_rEvent );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoListBoxControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoListBoxControl());
+}
+
+
+
+UnoControlComboBoxModel::UnoControlComboBoxModel( const Reference< XComponentContext >& rxContext )
+ :UnoControlListBoxModel( rxContext, ConstructWithoutProperties )
+{
+ UNO_CONTROL_MODEL_REGISTER_PROPERTIES<VCLXComboBox>();
+}
+
+OUString UnoControlComboBoxModel::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoControlComboBoxModel";
+}
+
+css::uno::Sequence<OUString> UnoControlComboBoxModel::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlComboBoxModel", "stardiv.vcl.controlmodel.ComboBox" };
+ return comphelper::concatSequences( UnoControlModel::getSupportedServiceNames(), vals);
+}
+
+uno::Reference< beans::XPropertySetInfo > UnoControlComboBoxModel::getPropertySetInfo( )
+{
+ static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+::cppu::IPropertyArrayHelper& UnoControlComboBoxModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+
+OUString UnoControlComboBoxModel::getServiceName()
+{
+ return "stardiv.vcl.controlmodel.ComboBox";
+}
+
+void SAL_CALL UnoControlComboBoxModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const uno::Any& rValue )
+{
+ UnoControlModel::setFastPropertyValue_NoBroadcast( nHandle, rValue );
+
+ if (nHandle != BASEPROPERTY_STRINGITEMLIST || m_xData->m_bSettingLegacyProperty)
+ return;
+
+ // synchronize the legacy StringItemList property with our list items
+ Sequence< OUString > aStringItemList;
+ Any aPropValue;
+ getFastPropertyValue( aPropValue, BASEPROPERTY_STRINGITEMLIST );
+ OSL_VERIFY( aPropValue >>= aStringItemList );
+
+ ::std::vector< ListItem > aItems( aStringItemList.getLength() );
+ ::std::transform(
+ std::cbegin(aStringItemList),
+ std::cend(aStringItemList),
+ aItems.begin(),
+ CreateListItem()
+ );
+ m_xData->setAllItems( std::move(aItems) );
+
+ // since an XItemListListener does not have a "all items modified" or some such method,
+ // we simulate this by notifying removal of all items, followed by insertion of all new
+ // items
+ lang::EventObject aEvent;
+ aEvent.Source = *this;
+ m_aItemListListeners.notifyEach( &XItemListListener::itemListChanged, aEvent );
+ // TODO: OPropertySetHelper calls into this method with the mutex locked ...
+ // which is wrong for the above notifications ...
+}
+
+uno::Any UnoControlComboBoxModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
+ {
+ return uno::Any( OUString( "stardiv.vcl.control.ComboBox" ) );
+ }
+ return UnoControlModel::ImplGetDefaultValue( nPropId );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlComboBoxModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoControlComboBoxModel(context));
+}
+
+
+
+UnoComboBoxControl::UnoComboBoxControl()
+ :maActionListeners( *this )
+ ,maItemListeners( *this )
+{
+ maComponentInfos.nWidth = 100;
+ maComponentInfos.nHeight = 12;
+}
+
+OUString UnoComboBoxControl::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoComboBoxControl";
+}
+
+css::uno::Sequence<OUString> UnoComboBoxControl::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlComboBox", "stardiv.vcl.control.ComboBox" };
+ return comphelper::concatSequences( UnoEditControl::getSupportedServiceNames(), vals);
+}
+
+OUString UnoComboBoxControl::GetComponentServiceName() const
+{
+ return "combobox";
+}
+
+void UnoComboBoxControl::dispose()
+{
+ lang::EventObject aEvt;
+ aEvt.Source = static_cast<cppu::OWeakObject*>(this);
+ maActionListeners.disposeAndClear( aEvt );
+ maItemListeners.disposeAndClear( aEvt );
+ UnoControl::dispose();
+}
+uno::Any UnoComboBoxControl::queryAggregation( const uno::Type & rType )
+{
+ uno::Any aRet = ::cppu::queryInterface( rType,
+ static_cast< awt::XComboBox* >(this) );
+ if ( !aRet.hasValue() )
+ {
+ aRet = ::cppu::queryInterface( rType,
+ static_cast< awt::XItemListener* >(this) );
+ if ( !aRet.hasValue() )
+ {
+ aRet = ::cppu::queryInterface( rType,
+ static_cast< awt::XItemListListener* >(this) );
+ }
+ }
+ return (aRet.hasValue() ? aRet : UnoEditControl::queryAggregation( rType ));
+}
+
+IMPL_IMPLEMENTATION_ID( UnoComboBoxControl )
+
+// lang::XTypeProvider
+css::uno::Sequence< css::uno::Type > UnoComboBoxControl::getTypes()
+{
+ static const ::cppu::OTypeCollection aTypeList(
+ cppu::UnoType<awt::XComboBox>::get(),
+ cppu::UnoType<awt::XItemListener>::get(),
+ cppu::UnoType<awt::XItemListListener>::get(),
+ UnoEditControl::getTypes()
+ );
+ return aTypeList.getTypes();
+}
+
+void UnoComboBoxControl::updateFromModel()
+{
+ UnoEditControl::updateFromModel();
+
+ Reference< XItemListListener > xItemListListener( getPeer(), UNO_QUERY );
+ ENSURE_OR_RETURN_VOID( xItemListListener.is(), "UnoComboBoxControl::updateFromModel: a peer which is no ItemListListener?!" );
+
+ EventObject aEvent( getModel() );
+ xItemListListener->itemListChanged( aEvent );
+}
+void UnoComboBoxControl::ImplSetPeerProperty( const OUString& rPropName, const uno::Any& rVal )
+{
+ if ( rPropName == GetPropertyName( BASEPROPERTY_STRINGITEMLIST ) )
+ // do not forward this to our peer. We are a XItemListListener at our model, and changes in the string item
+ // list (which is a legacy property) will, later, arrive as changes in the ItemList. Those latter changes
+ // will be forwarded to the peer, which will update itself accordingly.
+ return;
+
+ UnoEditControl::ImplSetPeerProperty( rPropName, rVal );
+}
+void UnoComboBoxControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer > & rParentPeer )
+{
+ UnoEditControl::createPeer( rxToolkit, rParentPeer );
+
+ uno::Reference < awt::XComboBox > xComboBox( getPeer(), uno::UNO_QUERY );
+ if ( maActionListeners.getLength() )
+ xComboBox->addActionListener( &maActionListeners );
+ if ( maItemListeners.getLength() )
+ xComboBox->addItemListener( &maItemListeners );
+}
+
+void UnoComboBoxControl::addActionListener(const uno::Reference< awt::XActionListener > & l)
+{
+ maActionListeners.addInterface( l );
+ if( getPeer().is() && maActionListeners.getLength() == 1 )
+ {
+ uno::Reference < awt::XComboBox > xComboBox( getPeer(), uno::UNO_QUERY );
+ xComboBox->addActionListener( &maActionListeners );
+ }
+}
+
+void UnoComboBoxControl::removeActionListener(const uno::Reference< awt::XActionListener > & l)
+{
+ if( getPeer().is() && maActionListeners.getLength() == 1 )
+ {
+ uno::Reference < awt::XComboBox > xComboBox( getPeer(), uno::UNO_QUERY );
+ xComboBox->removeActionListener( &maActionListeners );
+ }
+ maActionListeners.removeInterface( l );
+}
+
+void UnoComboBoxControl::addItemListener(const uno::Reference < awt::XItemListener > & l)
+{
+ maItemListeners.addInterface( l );
+ if( getPeer().is() && maItemListeners.getLength() == 1 )
+ {
+ uno::Reference < awt::XComboBox > xComboBox( getPeer(), uno::UNO_QUERY );
+ xComboBox->addItemListener( &maItemListeners );
+ }
+}
+
+void UnoComboBoxControl::removeItemListener(const uno::Reference < awt::XItemListener > & l)
+{
+ if( getPeer().is() && maItemListeners.getLength() == 1 )
+ {
+ // This call is prettier than creating a Ref and calling query
+ uno::Reference < awt::XComboBox > xComboBox( getPeer(), uno::UNO_QUERY );
+ xComboBox->removeItemListener( &maItemListeners );
+ }
+ maItemListeners.removeInterface( l );
+}
+void UnoComboBoxControl::itemStateChanged( const awt::ItemEvent& rEvent )
+{
+ if ( maItemListeners.getLength() )
+ {
+ try
+ {
+ maItemListeners.itemStateChanged( rEvent );
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "toolkit", "UnoComboBoxControl::itemStateChanged");
+ }
+ }
+}
+sal_Bool SAL_CALL UnoComboBoxControl::setModel( const uno::Reference< awt::XControlModel >& i_rModel )
+{
+ ::osl::MutexGuard aGuard( GetMutex() );
+
+ const Reference< XItemList > xOldItems( getModel(), UNO_QUERY );
+ OSL_ENSURE( xOldItems.is() || !getModel().is(), "UnoComboBoxControl::setModel: illegal old model!" );
+ const Reference< XItemList > xNewItems( i_rModel, UNO_QUERY );
+ OSL_ENSURE( xNewItems.is() || !i_rModel.is(), "UnoComboBoxControl::setModel: illegal new model!" );
+
+ if ( !UnoEditControl::setModel( i_rModel ) )
+ return false;
+
+ if ( xOldItems.is() )
+ xOldItems->removeItemListListener( this );
+ if ( xNewItems.is() )
+ xNewItems->addItemListListener( this );
+
+ return true;
+}
+
+void SAL_CALL UnoComboBoxControl::listItemInserted( const awt::ItemListEvent& i_rEvent )
+{
+ const Reference< XItemListListener > xPeerListener( getPeer(), UNO_QUERY );
+ OSL_ENSURE( xPeerListener.is() || !getPeer().is(), "UnoComboBoxControl::listItemInserted: invalid peer!" );
+ if ( xPeerListener.is() )
+ xPeerListener->listItemInserted( i_rEvent );
+}
+
+void SAL_CALL UnoComboBoxControl::listItemRemoved( const awt::ItemListEvent& i_rEvent )
+{
+ const Reference< XItemListListener > xPeerListener( getPeer(), UNO_QUERY );
+ OSL_ENSURE( xPeerListener.is() || !getPeer().is(), "UnoComboBoxControl::listItemRemoved: invalid peer!" );
+ if ( xPeerListener.is() )
+ xPeerListener->listItemRemoved( i_rEvent );
+}
+
+void SAL_CALL UnoComboBoxControl::listItemModified( const awt::ItemListEvent& i_rEvent )
+{
+ const Reference< XItemListListener > xPeerListener( getPeer(), UNO_QUERY );
+ OSL_ENSURE( xPeerListener.is() || !getPeer().is(), "UnoComboBoxControl::listItemModified: invalid peer!" );
+ if ( xPeerListener.is() )
+ xPeerListener->listItemModified( i_rEvent );
+}
+
+void SAL_CALL UnoComboBoxControl::allItemsRemoved( const lang::EventObject& i_rEvent )
+{
+ const Reference< XItemListListener > xPeerListener( getPeer(), UNO_QUERY );
+ OSL_ENSURE( xPeerListener.is() || !getPeer().is(), "UnoComboBoxControl::allItemsRemoved: invalid peer!" );
+ if ( xPeerListener.is() )
+ xPeerListener->allItemsRemoved( i_rEvent );
+}
+
+void SAL_CALL UnoComboBoxControl::itemListChanged( const lang::EventObject& i_rEvent )
+{
+ const Reference< XItemListListener > xPeerListener( getPeer(), UNO_QUERY );
+ OSL_ENSURE( xPeerListener.is() || !getPeer().is(), "UnoComboBoxControl::itemListChanged: invalid peer!" );
+ if ( xPeerListener.is() )
+ xPeerListener->itemListChanged( i_rEvent );
+}
+
+void UnoComboBoxControl::addItem( const OUString& aItem, sal_Int16 nPos )
+{
+ uno::Sequence<OUString> aSeq { aItem };
+ addItems( aSeq, nPos );
+}
+
+void UnoComboBoxControl::addItems( const uno::Sequence< OUString>& aItems, sal_Int16 nPos )
+{
+ uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ) );
+ uno::Sequence< OUString> aSeq;
+ aVal >>= aSeq;
+ sal_uInt16 nNewItems = static_cast<sal_uInt16>(aItems.getLength());
+ sal_uInt16 nOldLen = static_cast<sal_uInt16>(aSeq.getLength());
+ sal_uInt16 nNewLen = nOldLen + nNewItems;
+
+ uno::Sequence< OUString> aNewSeq( nNewLen );
+
+ if ( ( nPos < 0 ) || ( nPos > nOldLen ) )
+ nPos = nOldLen;
+
+ // items before the insert position
+ auto it = std::copy(std::cbegin(aSeq), std::next(std::cbegin(aSeq), nPos), aNewSeq.getArray());
+
+ // New items
+ it = std::copy(aItems.begin(), aItems.end(), it);
+
+ // remainder of old items
+ std::copy(std::next(std::cbegin(aSeq), nPos), std::cend(aSeq), it);
+
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ), Any(aNewSeq), true );
+}
+
+void UnoComboBoxControl::removeItems( sal_Int16 nPos, sal_Int16 nCount )
+{
+ uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ) );
+ uno::Sequence< OUString> aSeq;
+ aVal >>= aSeq;
+ sal_uInt16 nOldLen = static_cast<sal_uInt16>(aSeq.getLength());
+ if ( !nOldLen || ( nPos >= nOldLen ) )
+ return;
+
+ if ( nCount > ( nOldLen-nPos ) )
+ nCount = nOldLen-nPos;
+
+ sal_uInt16 nNewLen = nOldLen - nCount;
+
+ uno::Sequence< OUString> aNewSeq( nNewLen );
+
+ // items before the deletion position
+ auto it = std::copy(std::cbegin(aSeq), std::next(std::cbegin(aSeq), nPos), aNewSeq.getArray());
+
+ // remainder of old items
+ std::copy(std::next(std::cbegin(aSeq), nPos + nCount), std::cend(aSeq), it);
+
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ), uno::Any(aNewSeq), true );
+}
+
+sal_Int16 UnoComboBoxControl::getItemCount()
+{
+ uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ) );
+ uno::Sequence< OUString> aSeq;
+ aVal >>= aSeq;
+ return static_cast<sal_Int16>(aSeq.getLength());
+}
+
+OUString UnoComboBoxControl::getItem( sal_Int16 nPos )
+{
+ OUString aItem;
+ uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ) );
+ uno::Sequence< OUString> aSeq;
+ aVal >>= aSeq;
+ if ( nPos < aSeq.getLength() )
+ aItem = aSeq[nPos];
+ return aItem;
+}
+
+uno::Sequence< OUString> UnoComboBoxControl::getItems()
+{
+ uno::Any aVal = ImplGetPropertyValue( GetPropertyName( BASEPROPERTY_STRINGITEMLIST ) );
+ uno::Sequence< OUString> aSeq;
+ aVal >>= aSeq;
+ return aSeq;
+}
+
+void UnoComboBoxControl::setDropDownLineCount( sal_Int16 nLines )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_LINECOUNT ), uno::Any(nLines), true );
+}
+
+sal_Int16 UnoComboBoxControl::getDropDownLineCount()
+{
+ return ImplGetPropertyValue_INT16( BASEPROPERTY_LINECOUNT );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoComboBoxControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoComboBoxControl());
+}
+
+
+// UnoSpinFieldControl
+
+UnoSpinFieldControl::UnoSpinFieldControl()
+ :maSpinListeners( *this )
+{
+ mbRepeat = false;
+}
+
+// uno::XInterface
+uno::Any UnoSpinFieldControl::queryAggregation( const uno::Type & rType )
+{
+ uno::Any aRet = ::cppu::queryInterface( rType,
+ static_cast< awt::XSpinField* >(this) );
+ return (aRet.hasValue() ? aRet : UnoEditControl::queryAggregation( rType ));
+}
+
+IMPL_IMPLEMENTATION_ID( UnoSpinFieldControl )
+
+// lang::XTypeProvider
+css::uno::Sequence< css::uno::Type > UnoSpinFieldControl::getTypes()
+{
+ static const ::cppu::OTypeCollection aTypeList(
+ cppu::UnoType<css::lang::XTypeProvider>::get(),
+ cppu::UnoType<awt::XSpinField>::get(),
+ UnoEditControl::getTypes()
+ );
+ return aTypeList.getTypes();
+}
+
+void UnoSpinFieldControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer > & rParentPeer )
+{
+ UnoEditControl::createPeer( rxToolkit, rParentPeer );
+
+ uno::Reference < awt::XSpinField > xField( getPeer(), uno::UNO_QUERY );
+ xField->enableRepeat( mbRepeat );
+ if ( maSpinListeners.getLength() )
+ xField->addSpinListener( &maSpinListeners );
+}
+
+ // css::awt::XSpinField
+void UnoSpinFieldControl::addSpinListener( const css::uno::Reference< css::awt::XSpinListener >& l )
+{
+ maSpinListeners.addInterface( l );
+ if( getPeer().is() && maSpinListeners.getLength() == 1 )
+ {
+ uno::Reference < awt::XSpinField > xField( getPeer(), uno::UNO_QUERY );
+ xField->addSpinListener( &maSpinListeners );
+ }
+}
+
+void UnoSpinFieldControl::removeSpinListener( const css::uno::Reference< css::awt::XSpinListener >& l )
+{
+ if( getPeer().is() && maSpinListeners.getLength() == 1 )
+ {
+ uno::Reference < awt::XSpinField > xField( getPeer(), uno::UNO_QUERY );
+ xField->removeSpinListener( &maSpinListeners );
+ }
+ maSpinListeners.removeInterface( l );
+}
+
+void UnoSpinFieldControl::up()
+{
+ uno::Reference < awt::XSpinField > xField( getPeer(), uno::UNO_QUERY );
+ if ( xField.is() )
+ xField->up();
+}
+
+void UnoSpinFieldControl::down()
+{
+ uno::Reference < awt::XSpinField > xField( getPeer(), uno::UNO_QUERY );
+ if ( xField.is() )
+ xField->down();
+}
+
+void UnoSpinFieldControl::first()
+{
+ uno::Reference < awt::XSpinField > xField( getPeer(), uno::UNO_QUERY );
+ if ( xField.is() )
+ xField->first();
+}
+
+void UnoSpinFieldControl::last()
+{
+ uno::Reference < awt::XSpinField > xField( getPeer(), uno::UNO_QUERY );
+ if ( xField.is() )
+ xField->last();
+}
+
+void UnoSpinFieldControl::enableRepeat( sal_Bool bRepeat )
+{
+ mbRepeat = bRepeat;
+
+ uno::Reference < awt::XSpinField > xField( getPeer(), uno::UNO_QUERY );
+ if ( xField.is() )
+ xField->enableRepeat( bRepeat );
+}
+
+
+
+UnoControlDateFieldModel::UnoControlDateFieldModel( const Reference< XComponentContext >& rxContext )
+ :UnoControlModel( rxContext )
+{
+ UNO_CONTROL_MODEL_REGISTER_PROPERTIES<VCLXDateField>();
+}
+
+OUString UnoControlDateFieldModel::getServiceName()
+{
+ return "stardiv.vcl.controlmodel.DateField";
+}
+
+uno::Any UnoControlDateFieldModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
+ {
+ return uno::Any( OUString( "stardiv.vcl.control.DateField" ) );
+ }
+ return UnoControlModel::ImplGetDefaultValue( nPropId );
+}
+
+
+::cppu::IPropertyArrayHelper& UnoControlDateFieldModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+// beans::XMultiPropertySet
+uno::Reference< beans::XPropertySetInfo > UnoControlDateFieldModel::getPropertySetInfo( )
+{
+ static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+OUString UnoControlDateFieldModel::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoControlDateFieldModel";
+}
+
+css::uno::Sequence<OUString>
+UnoControlDateFieldModel::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlDateFieldModel", "stardiv.vcl.controlmodel.DateField" };
+ return comphelper::concatSequences( UnoControlModel::getSupportedServiceNames(), vals );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlDateFieldModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoControlDateFieldModel(context));
+}
+
+
+
+UnoDateFieldControl::UnoDateFieldControl()
+{
+ mnFirst = util::Date( 1, 1, 1900 );
+ mnLast = util::Date( 31, 12, 2200 );
+ mbLongFormat = TRISTATE_INDET;
+}
+
+OUString UnoDateFieldControl::GetComponentServiceName() const
+{
+ return "datefield";
+}
+
+// uno::XInterface
+uno::Any UnoDateFieldControl::queryAggregation( const uno::Type & rType )
+{
+ uno::Any aRet = ::cppu::queryInterface( rType,
+ static_cast< awt::XDateField* >(this) );
+ return (aRet.hasValue() ? aRet : UnoSpinFieldControl::queryAggregation( rType ));
+}
+
+IMPL_IMPLEMENTATION_ID( UnoDateFieldControl )
+
+// lang::XTypeProvider
+css::uno::Sequence< css::uno::Type > UnoDateFieldControl::getTypes()
+{
+ static const ::cppu::OTypeCollection aTypeList(
+ cppu::UnoType<css::lang::XTypeProvider>::get(),
+ cppu::UnoType<awt::XDateField>::get(),
+ UnoSpinFieldControl::getTypes()
+ );
+ return aTypeList.getTypes();
+}
+
+void UnoDateFieldControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer > & rParentPeer )
+{
+ UnoSpinFieldControl::createPeer( rxToolkit, rParentPeer );
+
+ uno::Reference < awt::XDateField > xField( getPeer(), uno::UNO_QUERY );
+ xField->setFirst( mnFirst );
+ xField->setLast( mnLast );
+ if ( mbLongFormat != TRISTATE_INDET )
+ xField->setLongFormat( mbLongFormat != TRISTATE_FALSE);
+}
+
+
+void UnoDateFieldControl::textChanged( const awt::TextEvent& e )
+{
+ uno::Reference< awt::XVclWindowPeer > xPeer( getPeer(), uno::UNO_QUERY );
+
+ // also change the text property (#i25106#)
+ if ( xPeer.is() )
+ {
+ const OUString& sTextPropertyName = GetPropertyName( BASEPROPERTY_TEXT );
+ ImplSetPropertyValue( sTextPropertyName, xPeer->getProperty( sTextPropertyName ), false );
+ }
+
+ // re-calc the Date property
+ uno::Reference < awt::XDateField > xField( getPeer(), uno::UNO_QUERY );
+ uno::Any aValue;
+ if ( xField->isEmpty() )
+ {
+ // the field says it's empty
+ bool bEnforceFormat = true;
+ if ( xPeer.is() )
+ xPeer->getProperty( GetPropertyName( BASEPROPERTY_ENFORCE_FORMAT ) ) >>= bEnforceFormat;
+ if ( !bEnforceFormat )
+ {
+ // and it also says that it is currently accepting invalid inputs, without
+ // forcing it to a valid date
+ uno::Reference< awt::XTextComponent > xText( xPeer, uno::UNO_QUERY );
+ if ( xText.is() && xText->getText().getLength() )
+ // and in real, the text of the peer is *not* empty
+ // -> simulate an invalid date, which is different from "no date"
+ aValue <<= util::Date();
+ }
+ }
+ else
+ aValue <<= xField->getDate();
+
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_DATE ), aValue, false );
+
+ // multiplex the event
+ if ( GetTextListeners().getLength() )
+ GetTextListeners().textChanged( e );
+}
+
+void UnoDateFieldControl::setDate( const util::Date& Date )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_DATE ), uno::Any(Date), true );
+}
+
+util::Date UnoDateFieldControl::getDate()
+{
+ return ImplGetPropertyValue_Date( BASEPROPERTY_DATE );
+}
+
+void UnoDateFieldControl::setMin( const util::Date& Date )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_DATEMIN ), uno::Any(Date), true );
+}
+
+util::Date UnoDateFieldControl::getMin()
+{
+ return ImplGetPropertyValue_Date( BASEPROPERTY_DATEMIN );
+}
+
+void UnoDateFieldControl::setMax( const util::Date& Date )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_DATEMAX ), uno::Any(Date), true );
+}
+
+util::Date UnoDateFieldControl::getMax()
+{
+ return ImplGetPropertyValue_Date( BASEPROPERTY_DATEMAX );
+}
+
+void UnoDateFieldControl::setFirst( const util::Date& Date )
+{
+ mnFirst = Date;
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XDateField > xField( getPeer(), uno::UNO_QUERY );
+ xField->setFirst( Date );
+ }
+}
+
+util::Date UnoDateFieldControl::getFirst()
+{
+ return mnFirst;
+}
+
+void UnoDateFieldControl::setLast( const util::Date& Date )
+{
+ mnLast = Date;
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XDateField > xField( getPeer(), uno::UNO_QUERY );
+ xField->setLast( Date );
+ }
+}
+
+util::Date UnoDateFieldControl::getLast()
+{
+ return mnLast;
+}
+
+void UnoDateFieldControl::setLongFormat( sal_Bool bLong )
+{
+ mbLongFormat = bLong ? TRISTATE_TRUE : TRISTATE_FALSE;
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XDateField > xField( getPeer(), uno::UNO_QUERY );
+ xField->setLongFormat( bLong );
+ }
+}
+
+sal_Bool UnoDateFieldControl::isLongFormat()
+{
+ return mbLongFormat == TRISTATE_TRUE;
+}
+
+void UnoDateFieldControl::setEmpty()
+{
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XDateField > xField( getPeer(), uno::UNO_QUERY );
+ xField->setEmpty();
+ }
+}
+
+sal_Bool UnoDateFieldControl::isEmpty()
+{
+ bool bEmpty = false;
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XDateField > xField( getPeer(), uno::UNO_QUERY );
+ bEmpty = xField->isEmpty();
+ }
+ return bEmpty;
+}
+
+void UnoDateFieldControl::setStrictFormat( sal_Bool bStrict )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STRICTFORMAT ), uno::Any(bStrict), true );
+}
+
+sal_Bool UnoDateFieldControl::isStrictFormat()
+{
+ return ImplGetPropertyValue_BOOL( BASEPROPERTY_STRICTFORMAT );
+}
+
+OUString UnoDateFieldControl::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoDateFieldControl";
+}
+
+css::uno::Sequence<OUString> UnoDateFieldControl::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlDateField", "stardiv.vcl.control.DateField" };
+ return comphelper::concatSequences( UnoSpinFieldControl::getSupportedServiceNames(), vals );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoDateFieldControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoDateFieldControl());
+}
+
+
+
+UnoControlTimeFieldModel::UnoControlTimeFieldModel( const Reference< XComponentContext >& rxContext )
+ :UnoControlModel( rxContext )
+{
+ UNO_CONTROL_MODEL_REGISTER_PROPERTIES<VCLXTimeField>();
+}
+
+OUString UnoControlTimeFieldModel::getServiceName()
+{
+ return "stardiv.vcl.controlmodel.TimeField";
+}
+
+uno::Any UnoControlTimeFieldModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
+ {
+ return uno::Any( OUString( "stardiv.vcl.control.TimeField" ) );
+ }
+ return UnoControlModel::ImplGetDefaultValue( nPropId );
+}
+
+
+::cppu::IPropertyArrayHelper& UnoControlTimeFieldModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+// beans::XMultiPropertySet
+uno::Reference< beans::XPropertySetInfo > UnoControlTimeFieldModel::getPropertySetInfo( )
+{
+ static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+OUString UnoControlTimeFieldModel::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoControlTimeFieldModel";
+}
+
+css::uno::Sequence<OUString>
+UnoControlTimeFieldModel::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlTimeFieldModel", "stardiv.vcl.controlmodel.TimeField" };
+ return comphelper::concatSequences( UnoControlModel::getSupportedServiceNames(), vals );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlTimeFieldModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoControlTimeFieldModel(context));
+}
+
+
+
+UnoTimeFieldControl::UnoTimeFieldControl()
+{
+ mnFirst = util::Time( 0, 0, 0, 0, false );
+ mnLast = util::Time( 999999999, 59, 59, 23, false );
+}
+
+OUString UnoTimeFieldControl::GetComponentServiceName() const
+{
+ return "timefield";
+}
+
+// uno::XInterface
+uno::Any UnoTimeFieldControl::queryAggregation( const uno::Type & rType )
+{
+ uno::Any aRet = ::cppu::queryInterface( rType,
+ static_cast< awt::XTimeField* >(this) );
+ return (aRet.hasValue() ? aRet : UnoSpinFieldControl::queryAggregation( rType ));
+}
+
+IMPL_IMPLEMENTATION_ID( UnoTimeFieldControl )
+
+// lang::XTypeProvider
+css::uno::Sequence< css::uno::Type > UnoTimeFieldControl::getTypes()
+{
+ static const ::cppu::OTypeCollection aTypeList(
+ cppu::UnoType<css::lang::XTypeProvider>::get(),
+ cppu::UnoType<awt::XTimeField>::get(),
+ UnoSpinFieldControl::getTypes()
+ );
+ return aTypeList.getTypes();
+}
+
+void UnoTimeFieldControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer > & rParentPeer )
+{
+ UnoSpinFieldControl::createPeer( rxToolkit, rParentPeer );
+
+ uno::Reference < awt::XTimeField > xField( getPeer(), uno::UNO_QUERY );
+ xField->setFirst( mnFirst );
+ xField->setLast( mnLast );
+}
+
+void UnoTimeFieldControl::textChanged( const awt::TextEvent& e )
+{
+ // also change the text property (#i25106#)
+ uno::Reference< awt::XVclWindowPeer > xPeer( getPeer(), uno::UNO_QUERY );
+ const OUString& sTextPropertyName = GetPropertyName( BASEPROPERTY_TEXT );
+ ImplSetPropertyValue( sTextPropertyName, xPeer->getProperty( sTextPropertyName ), false );
+
+ // re-calc the Time property
+ uno::Reference < awt::XTimeField > xField( getPeer(), uno::UNO_QUERY );
+ uno::Any aValue;
+ if ( !xField->isEmpty() )
+ aValue <<= xField->getTime();
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_TIME ), aValue, false );
+
+ // multiplex the event
+ if ( GetTextListeners().getLength() )
+ GetTextListeners().textChanged( e );
+}
+
+void UnoTimeFieldControl::setTime( const util::Time& Time )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_TIME ), Any(Time), true );
+}
+
+util::Time UnoTimeFieldControl::getTime()
+{
+ return ImplGetPropertyValue_Time( BASEPROPERTY_TIME );
+}
+
+void UnoTimeFieldControl::setMin( const util::Time& Time )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_TIMEMIN ), uno::Any(Time), true );
+}
+
+util::Time UnoTimeFieldControl::getMin()
+{
+ return ImplGetPropertyValue_Time( BASEPROPERTY_TIMEMIN );
+}
+
+void UnoTimeFieldControl::setMax( const util::Time& Time )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_TIMEMAX ), uno::Any(Time), true );
+}
+
+util::Time UnoTimeFieldControl::getMax()
+{
+ return ImplGetPropertyValue_Time( BASEPROPERTY_TIMEMAX );
+}
+
+void UnoTimeFieldControl::setFirst( const util::Time& Time )
+{
+ mnFirst = Time;
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XTimeField > xField( getPeer(), uno::UNO_QUERY );
+ xField->setFirst( mnFirst );
+ }
+}
+
+util::Time UnoTimeFieldControl::getFirst()
+{
+ return mnFirst;
+}
+
+void UnoTimeFieldControl::setLast( const util::Time& Time )
+{
+ mnLast = Time;
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XTimeField > xField( getPeer(), uno::UNO_QUERY );
+ xField->setFirst( mnLast );
+ }
+}
+
+util::Time UnoTimeFieldControl::getLast()
+{
+ return mnLast;
+}
+
+void UnoTimeFieldControl::setEmpty()
+{
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XTimeField > xField( getPeer(), uno::UNO_QUERY );
+ xField->setEmpty();
+ }
+}
+
+sal_Bool UnoTimeFieldControl::isEmpty()
+{
+ bool bEmpty = false;
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XTimeField > xField( getPeer(), uno::UNO_QUERY );
+ bEmpty = xField->isEmpty();
+ }
+ return bEmpty;
+}
+
+void UnoTimeFieldControl::setStrictFormat( sal_Bool bStrict )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STRICTFORMAT ), uno::Any(bStrict), true );
+}
+
+sal_Bool UnoTimeFieldControl::isStrictFormat()
+{
+ return ImplGetPropertyValue_BOOL( BASEPROPERTY_STRICTFORMAT );
+}
+
+OUString UnoTimeFieldControl::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoTimeFieldControl";
+}
+
+css::uno::Sequence<OUString> UnoTimeFieldControl::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlTimeField", "stardiv.vcl.control.TimeField" };
+ return comphelper::concatSequences( UnoSpinFieldControl::getSupportedServiceNames(), vals );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoTimeFieldControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoTimeFieldControl());
+}
+
+
+
+UnoControlNumericFieldModel::UnoControlNumericFieldModel( const Reference< XComponentContext >& rxContext )
+ :UnoControlModel( rxContext )
+{
+ UNO_CONTROL_MODEL_REGISTER_PROPERTIES<VCLXNumericField>();
+}
+
+OUString UnoControlNumericFieldModel::getServiceName()
+{
+ return "stardiv.vcl.controlmodel.NumericField";
+}
+
+uno::Any UnoControlNumericFieldModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
+ {
+ return uno::Any( OUString( "stardiv.vcl.control.NumericField" ) );
+ }
+ return UnoControlModel::ImplGetDefaultValue( nPropId );
+}
+
+
+::cppu::IPropertyArrayHelper& UnoControlNumericFieldModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+// beans::XMultiPropertySet
+uno::Reference< beans::XPropertySetInfo > UnoControlNumericFieldModel::getPropertySetInfo( )
+{
+ static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+OUString UnoControlNumericFieldModel::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoControlNumericFieldModel";
+}
+
+css::uno::Sequence<OUString>
+UnoControlNumericFieldModel::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "stardiv.vcl.controlmodel.NumericField", "com.sun.star.awt.UnoControlNumericFieldModel" };
+ return comphelper::concatSequences( UnoControlModel::getSupportedServiceNames(), vals );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlNumericFieldModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoControlNumericFieldModel(context));
+}
+
+
+
+UnoNumericFieldControl::UnoNumericFieldControl()
+{
+ mnFirst = 0;
+ mnLast = 0x7FFFFFFF;
+}
+
+OUString UnoNumericFieldControl::GetComponentServiceName() const
+{
+ return "numericfield";
+}
+
+// uno::XInterface
+uno::Any UnoNumericFieldControl::queryAggregation( const uno::Type & rType )
+{
+ uno::Any aRet = ::cppu::queryInterface( rType,
+ static_cast< awt::XNumericField* >(this) );
+ return (aRet.hasValue() ? aRet : UnoSpinFieldControl::queryAggregation( rType ));
+}
+
+IMPL_IMPLEMENTATION_ID( UnoNumericFieldControl )
+
+// lang::XTypeProvider
+css::uno::Sequence< css::uno::Type > UnoNumericFieldControl::getTypes()
+{
+ static const ::cppu::OTypeCollection aTypeList(
+ cppu::UnoType<css::lang::XTypeProvider>::get(),
+ cppu::UnoType<awt::XNumericField>::get(),
+ UnoSpinFieldControl::getTypes()
+ );
+ return aTypeList.getTypes();
+}
+
+void UnoNumericFieldControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer > & rParentPeer )
+{
+ UnoSpinFieldControl::createPeer( rxToolkit, rParentPeer );
+
+ uno::Reference < awt::XNumericField > xField( getPeer(), uno::UNO_QUERY );
+ xField->setFirst( mnFirst );
+ xField->setLast( mnLast );
+}
+
+
+void UnoNumericFieldControl::textChanged( const awt::TextEvent& e )
+{
+ uno::Reference < awt::XNumericField > xField( getPeer(), uno::UNO_QUERY );
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_VALUE_DOUBLE ), uno::Any(xField->getValue()), false );
+
+ if ( GetTextListeners().getLength() )
+ GetTextListeners().textChanged( e );
+}
+
+void UnoNumericFieldControl::setValue( double Value )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_VALUE_DOUBLE ), uno::Any(Value), true );
+}
+
+double UnoNumericFieldControl::getValue()
+{
+ return ImplGetPropertyValue_DOUBLE( BASEPROPERTY_VALUE_DOUBLE );
+}
+
+void UnoNumericFieldControl::setMin( double Value )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_VALUEMIN_DOUBLE ), uno::Any(Value), true );
+}
+
+double UnoNumericFieldControl::getMin()
+{
+ return ImplGetPropertyValue_DOUBLE( BASEPROPERTY_VALUEMIN_DOUBLE );
+}
+
+void UnoNumericFieldControl::setMax( double Value )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_VALUEMAX_DOUBLE ), uno::Any(Value), true );
+}
+
+double UnoNumericFieldControl::getMax()
+{
+ return ImplGetPropertyValue_DOUBLE( BASEPROPERTY_VALUEMAX_DOUBLE );
+}
+
+void UnoNumericFieldControl::setFirst( double Value )
+{
+ mnFirst = Value;
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XNumericField > xField( getPeer(), uno::UNO_QUERY );
+ xField->setFirst( mnFirst );
+ }
+}
+
+double UnoNumericFieldControl::getFirst()
+{
+ return mnFirst;
+}
+
+void UnoNumericFieldControl::setLast( double Value )
+{
+ mnLast = Value;
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XNumericField > xField( getPeer(), uno::UNO_QUERY );
+ xField->setLast( mnLast );
+ }
+}
+
+double UnoNumericFieldControl::getLast()
+{
+ return mnLast;
+}
+
+void UnoNumericFieldControl::setStrictFormat( sal_Bool bStrict )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STRICTFORMAT ), uno::Any(bStrict), true );
+}
+
+sal_Bool UnoNumericFieldControl::isStrictFormat()
+{
+ return ImplGetPropertyValue_BOOL( BASEPROPERTY_STRICTFORMAT );
+}
+
+OUString UnoNumericFieldControl::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoNumericFieldControl";
+}
+
+css::uno::Sequence<OUString> UnoNumericFieldControl::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlNumericField", "stardiv.vcl.control.NumericField" };
+ return comphelper::concatSequences( UnoSpinFieldControl::getSupportedServiceNames(), vals );
+}
+
+void UnoNumericFieldControl::setSpinSize( double Digits )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_VALUESTEP_DOUBLE ), uno::Any(Digits), true );
+}
+
+double UnoNumericFieldControl::getSpinSize()
+{
+ return ImplGetPropertyValue_DOUBLE( BASEPROPERTY_VALUESTEP_DOUBLE );
+}
+
+void UnoNumericFieldControl::setDecimalDigits( sal_Int16 Digits )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_DECIMALACCURACY ), uno::Any(Digits), true );
+}
+
+sal_Int16 UnoNumericFieldControl::getDecimalDigits()
+{
+ return ImplGetPropertyValue_INT16( BASEPROPERTY_DECIMALACCURACY );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoNumericFieldControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoNumericFieldControl());
+}
+
+UnoControlCurrencyFieldModel::UnoControlCurrencyFieldModel( const Reference< XComponentContext >& rxContext )
+ :UnoControlModel( rxContext )
+{
+ UNO_CONTROL_MODEL_REGISTER_PROPERTIES<SVTXCurrencyField>();
+}
+
+OUString UnoControlCurrencyFieldModel::getServiceName()
+{
+ return "stardiv.vcl.controlmodel.CurrencyField";
+}
+
+uno::Any UnoControlCurrencyFieldModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
+ {
+ return uno::Any( OUString( "stardiv.vcl.control.CurrencyField" ) );
+ }
+ if ( nPropId == BASEPROPERTY_CURSYM_POSITION )
+ {
+ return uno::Any(false);
+ }
+
+ return UnoControlModel::ImplGetDefaultValue( nPropId );
+}
+
+::cppu::IPropertyArrayHelper& UnoControlCurrencyFieldModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+// beans::XMultiPropertySet
+uno::Reference< beans::XPropertySetInfo > UnoControlCurrencyFieldModel::getPropertySetInfo( )
+{
+ static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+OUString UnoControlCurrencyFieldModel::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoControlCurrencyFieldModel";
+}
+
+css::uno::Sequence<OUString>
+UnoControlCurrencyFieldModel::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlCurrencyFieldModel", "stardiv.vcl.controlmodel.CurrencyField" };
+ return comphelper::concatSequences( UnoControlModel::getSupportedServiceNames(), vals );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlCurrencyFieldModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoControlCurrencyFieldModel(context));
+}
+
+
+
+UnoCurrencyFieldControl::UnoCurrencyFieldControl()
+{
+ mnFirst = 0;
+ mnLast = 0x7FFFFFFF;
+}
+
+OUString UnoCurrencyFieldControl::GetComponentServiceName() const
+{
+ return "longcurrencyfield";
+}
+
+// uno::XInterface
+uno::Any UnoCurrencyFieldControl::queryAggregation( const uno::Type & rType )
+{
+ uno::Any aRet = ::cppu::queryInterface( rType,
+ static_cast< awt::XCurrencyField* >(this) );
+ return (aRet.hasValue() ? aRet : UnoSpinFieldControl::queryAggregation( rType ));
+}
+
+IMPL_IMPLEMENTATION_ID( UnoCurrencyFieldControl )
+
+// lang::XTypeProvider
+css::uno::Sequence< css::uno::Type > UnoCurrencyFieldControl::getTypes()
+{
+ static const ::cppu::OTypeCollection aTypeList(
+ cppu::UnoType<css::lang::XTypeProvider>::get(),
+ cppu::UnoType<awt::XCurrencyField>::get(),
+ UnoSpinFieldControl::getTypes()
+ );
+ return aTypeList.getTypes();
+}
+
+void UnoCurrencyFieldControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer > & rParentPeer )
+{
+ UnoSpinFieldControl::createPeer( rxToolkit, rParentPeer );
+
+ uno::Reference < awt::XCurrencyField > xField( getPeer(), uno::UNO_QUERY );
+ xField->setFirst( mnFirst );
+ xField->setLast( mnLast );
+}
+
+void UnoCurrencyFieldControl::textChanged( const awt::TextEvent& e )
+{
+ uno::Reference < awt::XCurrencyField > xField( getPeer(), uno::UNO_QUERY );
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_VALUE_DOUBLE ), uno::Any(xField->getValue()), false );
+
+ if ( GetTextListeners().getLength() )
+ GetTextListeners().textChanged( e );
+}
+
+void UnoCurrencyFieldControl::setValue( double Value )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_VALUE_DOUBLE ), Any(Value), true );
+}
+
+double UnoCurrencyFieldControl::getValue()
+{
+ return ImplGetPropertyValue_DOUBLE( BASEPROPERTY_VALUE_DOUBLE );
+}
+
+void UnoCurrencyFieldControl::setMin( double Value )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_VALUEMIN_DOUBLE ), uno::Any(Value), true );
+}
+
+double UnoCurrencyFieldControl::getMin()
+{
+ return ImplGetPropertyValue_DOUBLE( BASEPROPERTY_VALUEMIN_DOUBLE );
+}
+
+void UnoCurrencyFieldControl::setMax( double Value )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_VALUEMAX_DOUBLE ), uno::Any(Value), true );
+}
+
+double UnoCurrencyFieldControl::getMax()
+{
+ return ImplGetPropertyValue_DOUBLE( BASEPROPERTY_VALUEMAX_DOUBLE );
+}
+
+void UnoCurrencyFieldControl::setFirst( double Value )
+{
+ mnFirst = Value;
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XCurrencyField > xField( getPeer(), uno::UNO_QUERY );
+ xField->setFirst( mnFirst );
+ }
+}
+
+double UnoCurrencyFieldControl::getFirst()
+{
+ return mnFirst;
+}
+
+void UnoCurrencyFieldControl::setLast( double Value )
+{
+ mnLast = Value;
+ if ( getPeer().is() )
+ {
+ uno::Reference < awt::XCurrencyField > xField( getPeer(), uno::UNO_QUERY );
+ xField->setLast( mnLast );
+ }
+}
+
+double UnoCurrencyFieldControl::getLast()
+{
+ return mnLast;
+}
+
+void UnoCurrencyFieldControl::setStrictFormat( sal_Bool bStrict )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STRICTFORMAT ), uno::Any(bStrict), true );
+}
+
+sal_Bool UnoCurrencyFieldControl::isStrictFormat()
+{
+ return ImplGetPropertyValue_BOOL( BASEPROPERTY_STRICTFORMAT );
+}
+
+OUString UnoCurrencyFieldControl::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoCurrencyFieldControl";
+}
+
+css::uno::Sequence<OUString>
+UnoCurrencyFieldControl::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlCurrencyField", "stardiv.vcl.control.CurrencyField" };
+ return comphelper::concatSequences( UnoSpinFieldControl::getSupportedServiceNames(), vals );
+}
+
+void UnoCurrencyFieldControl::setSpinSize( double Digits )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_VALUESTEP_DOUBLE ), uno::Any(Digits), true );
+}
+
+double UnoCurrencyFieldControl::getSpinSize()
+{
+ return ImplGetPropertyValue_DOUBLE( BASEPROPERTY_VALUESTEP_DOUBLE );
+}
+
+void UnoCurrencyFieldControl::setDecimalDigits( sal_Int16 Digits )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_DECIMALACCURACY ), uno::Any(Digits), true );
+}
+
+sal_Int16 UnoCurrencyFieldControl::getDecimalDigits()
+{
+ return ImplGetPropertyValue_INT16( BASEPROPERTY_DECIMALACCURACY );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoCurrencyFieldControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoCurrencyFieldControl());
+}
+
+
+
+UnoControlPatternFieldModel::UnoControlPatternFieldModel( const Reference< XComponentContext >& rxContext )
+ :UnoControlModel( rxContext )
+{
+ UNO_CONTROL_MODEL_REGISTER_PROPERTIES<VCLXPatternField>();
+}
+
+OUString UnoControlPatternFieldModel::getServiceName()
+{
+ return "stardiv.vcl.controlmodel.PatternField";
+}
+
+uno::Any UnoControlPatternFieldModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
+ {
+ return uno::Any( OUString( "stardiv.vcl.control.PatternField" ) );
+ }
+ return UnoControlModel::ImplGetDefaultValue( nPropId );
+}
+
+::cppu::IPropertyArrayHelper& UnoControlPatternFieldModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+// beans::XMultiPropertySet
+uno::Reference< beans::XPropertySetInfo > UnoControlPatternFieldModel::getPropertySetInfo( )
+{
+ static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+OUString UnoControlPatternFieldModel::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoControlPatternFieldModel";
+}
+
+css::uno::Sequence<OUString>
+UnoControlPatternFieldModel::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlPatternFieldModel", "stardiv.vcl.controlmodel.PatternField" };
+ return comphelper::concatSequences( UnoControlModel::getSupportedServiceNames(), vals );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlPatternFieldModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoControlPatternFieldModel(context));
+}
+
+
+
+UnoPatternFieldControl::UnoPatternFieldControl()
+{
+}
+
+OUString UnoPatternFieldControl::GetComponentServiceName() const
+{
+ return "patternfield";
+}
+
+void UnoPatternFieldControl::ImplSetPeerProperty( const OUString& rPropName, const uno::Any& rVal )
+{
+ sal_uInt16 nType = GetPropertyId( rPropName );
+ if ( ( nType == BASEPROPERTY_TEXT ) || ( nType == BASEPROPERTY_EDITMASK ) || ( nType == BASEPROPERTY_LITERALMASK ) )
+ {
+ // These masks cannot be set consecutively
+ OUString Text = ImplGetPropertyValue_UString( BASEPROPERTY_TEXT );
+ OUString EditMask = ImplGetPropertyValue_UString( BASEPROPERTY_EDITMASK );
+ OUString LiteralMask = ImplGetPropertyValue_UString( BASEPROPERTY_LITERALMASK );
+
+ uno::Reference < awt::XPatternField > xPF( getPeer(), uno::UNO_QUERY );
+ if (xPF.is())
+ {
+ // same comment as in UnoControl::ImplSetPeerProperty - see there
+ OUString sText( Text );
+ ImplCheckLocalize( sText );
+ xPF->setString( sText );
+ xPF->setMasks( EditMask, LiteralMask );
+ }
+ }
+ else
+ UnoSpinFieldControl::ImplSetPeerProperty( rPropName, rVal );
+}
+
+
+// uno::XInterface
+uno::Any UnoPatternFieldControl::queryAggregation( const uno::Type & rType )
+{
+ uno::Any aRet = ::cppu::queryInterface( rType,
+ static_cast< awt::XPatternField* >(this) );
+ return (aRet.hasValue() ? aRet : UnoSpinFieldControl::queryAggregation( rType ));
+}
+
+IMPL_IMPLEMENTATION_ID( UnoPatternFieldControl )
+
+// lang::XTypeProvider
+css::uno::Sequence< css::uno::Type > UnoPatternFieldControl::getTypes()
+{
+ static const ::cppu::OTypeCollection aTypeList(
+ cppu::UnoType<css::lang::XTypeProvider>::get(),
+ cppu::UnoType<awt::XPatternField>::get(),
+ UnoSpinFieldControl::getTypes()
+ );
+ return aTypeList.getTypes();
+}
+
+void UnoPatternFieldControl::setString( const OUString& rString )
+{
+ setText( rString );
+}
+
+OUString UnoPatternFieldControl::getString()
+{
+ return getText();
+}
+
+void UnoPatternFieldControl::setMasks( const OUString& EditMask, const OUString& LiteralMask )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_EDITMASK ), uno::Any(EditMask), true );
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_LITERALMASK ), uno::Any(LiteralMask), true );
+}
+
+void UnoPatternFieldControl::getMasks( OUString& EditMask, OUString& LiteralMask )
+{
+ EditMask = ImplGetPropertyValue_UString( BASEPROPERTY_EDITMASK );
+ LiteralMask = ImplGetPropertyValue_UString( BASEPROPERTY_LITERALMASK );
+}
+
+void UnoPatternFieldControl::setStrictFormat( sal_Bool bStrict )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_STRICTFORMAT ), uno::Any(bStrict), true );
+}
+
+sal_Bool UnoPatternFieldControl::isStrictFormat()
+{
+ return ImplGetPropertyValue_BOOL( BASEPROPERTY_STRICTFORMAT );
+}
+
+OUString UnoPatternFieldControl::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoPatternFieldControl";
+}
+
+css::uno::Sequence<OUString> UnoPatternFieldControl::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlPatternField", "stardiv.vcl.control.PatternField" };
+ return comphelper::concatSequences( UnoSpinFieldControl::getSupportedServiceNames(), vals );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoPatternFieldControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoPatternFieldControl());
+}
+
+
+
+UnoControlProgressBarModel::UnoControlProgressBarModel( const Reference< XComponentContext >& rxContext )
+ :UnoControlModel( rxContext )
+{
+ ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_BORDER );
+ ImplRegisterProperty( BASEPROPERTY_BORDERCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
+ ImplRegisterProperty( BASEPROPERTY_ENABLED );
+ ImplRegisterProperty( BASEPROPERTY_ENABLEVISIBLE );
+ ImplRegisterProperty( BASEPROPERTY_FILLCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
+ ImplRegisterProperty( BASEPROPERTY_HELPURL );
+ ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
+ ImplRegisterProperty( BASEPROPERTY_PROGRESSVALUE );
+ ImplRegisterProperty( BASEPROPERTY_PROGRESSVALUE_MAX );
+ ImplRegisterProperty( BASEPROPERTY_PROGRESSVALUE_MIN );
+}
+
+OUString UnoControlProgressBarModel::getServiceName( )
+{
+ return "stardiv.vcl.controlmodel.ProgressBar";
+}
+
+uno::Any UnoControlProgressBarModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
+ {
+ return uno::Any( OUString( "stardiv.vcl.control.ProgressBar" ) );
+ }
+
+ return UnoControlModel::ImplGetDefaultValue( nPropId );
+}
+
+::cppu::IPropertyArrayHelper& UnoControlProgressBarModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+// beans::XMultiPropertySet
+uno::Reference< beans::XPropertySetInfo > UnoControlProgressBarModel::getPropertySetInfo( )
+{
+ static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+OUString UnoControlProgressBarModel::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoControlProgressBarModel";
+}
+
+css::uno::Sequence<OUString>
+UnoControlProgressBarModel::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlProgressBarModel", "stardiv.vcl.controlmodel.ProgressBar" };
+ return comphelper::concatSequences( UnoControlModel::getSupportedServiceNames(), vals );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlProgressBarModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoControlProgressBarModel(context));
+}
+
+
+
+UnoProgressBarControl::UnoProgressBarControl()
+{
+}
+
+OUString UnoProgressBarControl::GetComponentServiceName() const
+{
+ return "ProgressBar";
+}
+
+// uno::XInterface
+uno::Any UnoProgressBarControl::queryAggregation( const uno::Type & rType )
+{
+ uno::Any aRet = ::cppu::queryInterface( rType,
+ static_cast< awt::XProgressBar* >(this) );
+ return (aRet.hasValue() ? aRet : UnoControlBase::queryAggregation( rType ));
+}
+
+IMPL_IMPLEMENTATION_ID( UnoProgressBarControl )
+
+// lang::XTypeProvider
+css::uno::Sequence< css::uno::Type > UnoProgressBarControl::getTypes()
+{
+ static const ::cppu::OTypeCollection aTypeList(
+ cppu::UnoType<css::lang::XTypeProvider>::get(),
+ cppu::UnoType<awt::XProgressBar>::get(),
+ UnoControlBase::getTypes()
+ );
+ return aTypeList.getTypes();
+}
+
+// css::awt::XProgressBar
+void UnoProgressBarControl::setForegroundColor( sal_Int32 nColor )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_FILLCOLOR ), uno::Any(nColor), true );
+}
+
+void UnoProgressBarControl::setBackgroundColor( sal_Int32 nColor )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_BACKGROUNDCOLOR ), uno::Any(nColor), true );
+}
+
+void UnoProgressBarControl::setValue( sal_Int32 nValue )
+{
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_PROGRESSVALUE ), uno::Any(nValue), true );
+}
+
+void UnoProgressBarControl::setRange( sal_Int32 nMin, sal_Int32 nMax )
+{
+ uno::Any aMin;
+ uno::Any aMax;
+
+ if ( nMin < nMax )
+ {
+ // take correct min and max
+ aMin <<= nMin;
+ aMax <<= nMax;
+ }
+ else
+ {
+ // change min and max
+ aMin <<= nMax;
+ aMax <<= nMin;
+ }
+
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_PROGRESSVALUE_MIN ), aMin, true );
+ ImplSetPropertyValue( GetPropertyName( BASEPROPERTY_PROGRESSVALUE_MAX ), aMax, true );
+}
+
+sal_Int32 UnoProgressBarControl::getValue()
+{
+ return ImplGetPropertyValue_INT32( BASEPROPERTY_PROGRESSVALUE );
+}
+
+OUString UnoProgressBarControl::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoProgressBarControl";
+}
+
+css::uno::Sequence<OUString> UnoProgressBarControl::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlProgressBar", "stardiv.vcl.control.ProgressBar" };
+ return comphelper::concatSequences( UnoControlBase::getSupportedServiceNames(), vals );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoProgressBarControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoProgressBarControl());
+}
+
+
+
+UnoControlFixedLineModel::UnoControlFixedLineModel( const Reference< XComponentContext >& rxContext )
+ :UnoControlModel( rxContext )
+{
+ ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
+ ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
+ ImplRegisterProperty( BASEPROPERTY_ENABLED );
+ ImplRegisterProperty( BASEPROPERTY_ENABLEVISIBLE );
+ ImplRegisterProperty( BASEPROPERTY_FONTDESCRIPTOR );
+ ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
+ ImplRegisterProperty( BASEPROPERTY_HELPURL );
+ ImplRegisterProperty( BASEPROPERTY_LABEL );
+ ImplRegisterProperty( BASEPROPERTY_ORIENTATION );
+ ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
+}
+
+OUString UnoControlFixedLineModel::getServiceName( )
+{
+ return "stardiv.vcl.controlmodel.FixedLine";
+}
+
+uno::Any UnoControlFixedLineModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
+{
+ if ( nPropId == BASEPROPERTY_DEFAULTCONTROL )
+ {
+ return uno::Any( OUString( "stardiv.vcl.control.FixedLine" ) );
+ }
+ return UnoControlModel::ImplGetDefaultValue( nPropId );
+}
+
+::cppu::IPropertyArrayHelper& UnoControlFixedLineModel::getInfoHelper()
+{
+ static UnoPropertyArrayHelper aHelper( ImplGetPropertyIds() );
+ return aHelper;
+}
+
+// beans::XMultiPropertySet
+uno::Reference< beans::XPropertySetInfo > UnoControlFixedLineModel::getPropertySetInfo( )
+{
+ static uno::Reference< beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+OUString UnoControlFixedLineModel::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoControlFixedLineModel";
+}
+
+css::uno::Sequence<OUString>
+UnoControlFixedLineModel::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlFixedLineModel", "stardiv.vcl.controlmodel.FixedLine" };
+ return comphelper::concatSequences( UnoControlModel::getSupportedServiceNames(), vals );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoControlFixedLineModel_get_implementation(
+ css::uno::XComponentContext *context,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoControlFixedLineModel(context));
+}
+
+
+
+UnoFixedLineControl::UnoFixedLineControl()
+{
+ maComponentInfos.nWidth = 100; // ??
+ maComponentInfos.nHeight = 100; // ??
+}
+
+OUString UnoFixedLineControl::GetComponentServiceName() const
+{
+ return "FixedLine";
+}
+
+sal_Bool UnoFixedLineControl::isTransparent()
+{
+ return true;
+}
+
+OUString UnoFixedLineControl::getImplementationName()
+{
+ return "stardiv.Toolkit.UnoFixedLineControl";
+}
+
+css::uno::Sequence<OUString> UnoFixedLineControl::getSupportedServiceNames()
+{
+ const css::uno::Sequence<OUString> vals { "com.sun.star.awt.UnoControlFixedLine", "stardiv.vcl.control.FixedLine" };
+ return comphelper::concatSequences( UnoControlBase::getSupportedServiceNames(), vals );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_UnoFixedLineControl_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new UnoFixedLineControl());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */