summaryrefslogtreecommitdiffstats
path: root/toolkit/source
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /toolkit/source
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/source')
-rw-r--r--toolkit/source/awt/animatedimagespeer.cxx476
-rw-r--r--toolkit/source/awt/asynccallback.cxx122
-rw-r--r--toolkit/source/awt/non-interactable-containers.xml32
-rw-r--r--toolkit/source/awt/scrollabledialog.cxx173
-rw-r--r--toolkit/source/awt/stylesettings.cxx926
-rw-r--r--toolkit/source/awt/stylesettings.hxx181
-rw-r--r--toolkit/source/awt/vclxaccessiblecomponent.cxx854
-rw-r--r--toolkit/source/awt/vclxbitmap.cxx60
-rw-r--r--toolkit/source/awt/vclxcontainer.cxx264
-rw-r--r--toolkit/source/awt/vclxdevice.cxx251
-rw-r--r--toolkit/source/awt/vclxfont.cxx189
-rw-r--r--toolkit/source/awt/vclxgraphics.cxx487
-rw-r--r--toolkit/source/awt/vclxmenu.cxx869
-rw-r--r--toolkit/source/awt/vclxpointer.cxx70
-rw-r--r--toolkit/source/awt/vclxprinter.cxx379
-rw-r--r--toolkit/source/awt/vclxregion.cxx142
-rw-r--r--toolkit/source/awt/vclxspinbutton.cxx331
-rw-r--r--toolkit/source/awt/vclxsystemdependentwindow.cxx90
-rw-r--r--toolkit/source/awt/vclxtabpagecontainer.cxx233
-rw-r--r--toolkit/source/awt/vclxtoolkit.cxx2624
-rw-r--r--toolkit/source/awt/vclxtopwindow.cxx229
-rw-r--r--toolkit/source/awt/vclxwindow.cxx2611
-rw-r--r--toolkit/source/awt/vclxwindow1.cxx90
-rw-r--r--toolkit/source/awt/vclxwindows.cxx7877
-rw-r--r--toolkit/source/awt/vclxwindows_internal.hxx33
-rw-r--r--toolkit/source/controls/accessiblecontrolcontext.cxx343
-rw-r--r--toolkit/source/controls/animatedimages.cxx491
-rw-r--r--toolkit/source/controls/controlmodelcontainerbase.cxx1789
-rw-r--r--toolkit/source/controls/controlmodelcontainerbase_internal.hxx30
-rw-r--r--toolkit/source/controls/dialogcontrol.cxx1245
-rw-r--r--toolkit/source/controls/eventcontainer.cxx179
-rw-r--r--toolkit/source/controls/filectrl.cxx244
-rw-r--r--toolkit/source/controls/formattedcontrol.cxx478
-rw-r--r--toolkit/source/controls/geometrycontrolmodel.cxx609
-rw-r--r--toolkit/source/controls/grid/defaultgridcolumnmodel.cxx375
-rw-r--r--toolkit/source/controls/grid/defaultgriddatamodel.cxx512
-rw-r--r--toolkit/source/controls/grid/gridcolumn.cxx287
-rw-r--r--toolkit/source/controls/grid/gridcolumn.hxx122
-rw-r--r--toolkit/source/controls/grid/gridcontrol.cxx462
-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.cxx504
-rw-r--r--toolkit/source/controls/roadmapentry.cxx105
-rw-r--r--toolkit/source/controls/spinningprogress.cxx128
-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/svtxgridcontrol.cxx911
-rw-r--r--toolkit/source/controls/table/cellvalueconversion.cxx376
-rw-r--r--toolkit/source/controls/table/cellvalueconversion.hxx72
-rw-r--r--toolkit/source/controls/table/defaultinputhandler.cxx180
-rw-r--r--toolkit/source/controls/table/gridtablerenderer.cxx597
-rw-r--r--toolkit/source/controls/table/mousefunction.cxx273
-rw-r--r--toolkit/source/controls/table/tablecontrol.cxx642
-rw-r--r--toolkit/source/controls/table/tablecontrol_impl.cxx2551
-rw-r--r--toolkit/source/controls/table/tablecontrol_impl.hxx480
-rw-r--r--toolkit/source/controls/table/tabledatawindow.cxx201
-rw-r--r--toolkit/source/controls/table/tabledatawindow.hxx66
-rw-r--r--toolkit/source/controls/table/tablegeometry.cxx154
-rw-r--r--toolkit/source/controls/table/tablegeometry.hxx156
-rw-r--r--toolkit/source/controls/tabpagecontainer.cxx351
-rw-r--r--toolkit/source/controls/tabpagemodel.cxx295
-rw-r--r--toolkit/source/controls/tkscrollbar.cxx324
-rw-r--r--toolkit/source/controls/tkspinbutton.cxx422
-rw-r--r--toolkit/source/controls/tree/treecontrol.cxx524
-rw-r--r--toolkit/source/controls/tree/treecontrol.hxx69
-rw-r--r--toolkit/source/controls/tree/treecontrolpeer.cxx1579
-rw-r--r--toolkit/source/controls/tree/treedatamodel.cxx535
-rw-r--r--toolkit/source/controls/unocontrol.cxx1588
-rw-r--r--toolkit/source/controls/unocontrolbase.cxx253
-rw-r--r--toolkit/source/controls/unocontrolcontainer.cxx823
-rw-r--r--toolkit/source/controls/unocontrolcontainermodel.cxx93
-rw-r--r--toolkit/source/controls/unocontrolmodel.cxx1357
-rw-r--r--toolkit/source/controls/unocontrols.cxx4757
-rw-r--r--toolkit/source/controls/unocontroltablemodel.cxx834
-rw-r--r--toolkit/source/controls/unocontroltablemodel.hxx181
-rw-r--r--toolkit/source/controls/unogridcolumnfacade.cxx310
-rw-r--r--toolkit/source/controls/unogridcolumnfacade.hxx89
-rw-r--r--toolkit/source/hatchwindow/documentcloser.cxx229
-rw-r--r--toolkit/source/hatchwindow/hatchwindow.cxx159
-rw-r--r--toolkit/source/hatchwindow/hatchwindow.hxx60
-rw-r--r--toolkit/source/hatchwindow/hatchwindowfactory.cxx89
-rw-r--r--toolkit/source/hatchwindow/ipwin.cxx621
-rw-r--r--toolkit/source/hatchwindow/ipwin.hxx92
-rw-r--r--toolkit/source/helper/accessibilityclient.cxx235
-rw-r--r--toolkit/source/helper/btndlg.cxx304
-rw-r--r--toolkit/source/helper/imagealign.cxx128
-rw-r--r--toolkit/source/helper/listenermultiplexer.cxx247
-rw-r--r--toolkit/source/helper/property.cxx335
-rw-r--r--toolkit/source/helper/servicenames.cxx24
-rw-r--r--toolkit/source/helper/tkresmgr.cxx57
-rw-r--r--toolkit/source/helper/unopropertyarrayhelper.cxx148
-rw-r--r--toolkit/source/helper/unowrapper.cxx321
-rw-r--r--toolkit/source/helper/vclunohelper.cxx604
96 files changed, 54364 insertions, 0 deletions
diff --git a/toolkit/source/awt/animatedimagespeer.cxx b/toolkit/source/awt/animatedimagespeer.cxx
new file mode 100644
index 0000000000..379a82388b
--- /dev/null
+++ b/toolkit/source/awt/animatedimagespeer.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 <awt/animatedimagespeer.hxx>
+#include <helper/property.hxx>
+
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/graphic/GraphicProvider.hpp>
+#include <com/sun/star/graphic/XGraphicProvider.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/awt/ImageScaleMode.hpp>
+
+#include <comphelper/namedvaluecollection.hxx>
+#include <comphelper/processfactory.hxx>
+#include <o3tl/safeint.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <tools/urlobj.hxx>
+#include <vcl/toolkit/throbber.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+
+#include <limits>
+#include <string_view>
+
+namespace toolkit
+{
+
+
+ using ::com::sun::star::uno::XComponentContext;
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::XInterface;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::lang::EventObject;
+ using ::com::sun::star::container::ContainerEvent;
+ using ::com::sun::star::awt::XAnimatedImages;
+ using ::com::sun::star::awt::Size;
+ using ::com::sun::star::graphic::XGraphicProvider;
+ using ::com::sun::star::beans::XPropertySet;
+ using ::com::sun::star::graphic::XGraphic;
+
+ namespace ImageScaleMode = ::com::sun::star::awt::ImageScaleMode;
+
+ //= helper
+
+ namespace
+ {
+
+ OUString lcl_getHighContrastURL( OUString const& i_imageURL )
+ {
+ INetURLObject aURL( i_imageURL );
+ if ( aURL.GetProtocol() != INetProtocol::PrivSoffice )
+ {
+ OSL_VERIFY( aURL.insertName( u"sifr", false, 0 ) );
+ return aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+ }
+ // the private: scheme is not considered to be hierarchical by INetURLObject, so manually insert the
+ // segment
+ const sal_Int32 separatorPos = i_imageURL.indexOf( '/' );
+ ENSURE_OR_RETURN( separatorPos != -1, "lcl_getHighContrastURL: unsupported URL scheme - cannot automatically determine HC version!", i_imageURL );
+
+ OUString composer = OUString::Concat(i_imageURL.subView(0, separatorPos)) + "/sifr" +
+ i_imageURL.subView(separatorPos);
+ return composer;
+ }
+
+
+ bool lcl_ensureImage_throw( Reference< XGraphicProvider > const& i_graphicProvider, const bool i_isHighContrast, const AnimatedImagesPeer::CachedImage& i_cachedImage )
+ {
+ if ( !i_cachedImage.xGraphic.is() )
+ {
+ ::comphelper::NamedValueCollection aMediaProperties;
+ if ( i_isHighContrast )
+ {
+ // try (to find) the high-contrast version of the graphic first
+ aMediaProperties.put( "URL", lcl_getHighContrastURL( i_cachedImage.sImageURL ) );
+ i_cachedImage.xGraphic = i_graphicProvider->queryGraphic( aMediaProperties.getPropertyValues() );
+ }
+ if ( !i_cachedImage.xGraphic.is() )
+ {
+ aMediaProperties.put( "URL", i_cachedImage.sImageURL );
+ i_cachedImage.xGraphic = i_graphicProvider->queryGraphic( aMediaProperties.getPropertyValues() );
+ }
+ }
+ return i_cachedImage.xGraphic.is();
+ }
+
+
+ Size lcl_getGraphicSizePixel( Reference< XGraphic > const& i_graphic )
+ {
+ Size aSizePixel;
+ try
+ {
+ if ( i_graphic.is() )
+ {
+ const Reference< XPropertySet > xGraphicProps( i_graphic, UNO_QUERY_THROW );
+ OSL_VERIFY( xGraphicProps->getPropertyValue("SizePixel") >>= aSizePixel );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit");
+ }
+ return aSizePixel;
+ }
+
+
+ void lcl_init( Sequence< OUString > const& i_imageURLs, ::std::vector< AnimatedImagesPeer::CachedImage >& o_images )
+ {
+ o_images.resize(0);
+ size_t count = size_t( i_imageURLs.getLength() );
+ o_images.reserve( count );
+ for ( const auto& rImageURL : i_imageURLs )
+ {
+ o_images.emplace_back( AnimatedImagesPeer::CachedImage{ rImageURL, nullptr } );
+ }
+ }
+
+
+ }
+
+
+ //= AnimatedImagesPeer
+
+
+ AnimatedImagesPeer::AnimatedImagesPeer()
+ {
+ }
+
+
+ AnimatedImagesPeer::~AnimatedImagesPeer()
+ {
+ }
+
+
+ void SAL_CALL AnimatedImagesPeer::startAnimation()
+ {
+ SolarMutexGuard aGuard;
+ VclPtr<Throbber> pThrobber = GetAsDynamic<Throbber>();
+ if (pThrobber)
+ pThrobber->start();
+ }
+
+ void SAL_CALL AnimatedImagesPeer::stopAnimation()
+ {
+ SolarMutexGuard aGuard;
+ VclPtr<Throbber> pThrobber = GetAsDynamic<Throbber>();
+ if (pThrobber)
+ pThrobber->stop();
+ }
+
+ sal_Bool SAL_CALL AnimatedImagesPeer::isAnimationRunning()
+ {
+ SolarMutexGuard aGuard;
+ VclPtr<Throbber> pThrobber = GetAsDynamic<Throbber>();
+ if (pThrobber)
+ return pThrobber->isRunning();
+ return false;
+ }
+
+ void SAL_CALL AnimatedImagesPeer::setProperty( const OUString& i_propertyName, const Any& i_value )
+ {
+ SolarMutexGuard aGuard;
+
+ VclPtr<Throbber> pThrobber = GetAsDynamic<Throbber>();
+ if ( !pThrobber )
+ {
+ VCLXWindow::setProperty( i_propertyName, i_value );
+ return;
+ }
+
+ const sal_uInt16 nPropertyId = GetPropertyId( i_propertyName );
+ switch ( nPropertyId )
+ {
+ case BASEPROPERTY_STEP_TIME:
+ {
+ sal_Int32 nStepTime( 0 );
+ if ( i_value >>= nStepTime )
+ pThrobber->setStepTime( nStepTime );
+ break;
+ }
+ case BASEPROPERTY_AUTO_REPEAT:
+ {
+ bool bRepeat( true );
+ if ( i_value >>= bRepeat )
+ pThrobber->setRepeat( bRepeat );
+ break;
+ }
+
+ case BASEPROPERTY_IMAGE_SCALE_MODE:
+ {
+ sal_Int16 nScaleMode( ImageScaleMode::ANISOTROPIC );
+ VclPtr<ImageControl> pImageControl = GetAsDynamic< ImageControl >();
+ if ( pImageControl && ( i_value >>= nScaleMode ) )
+ pImageControl->SetScaleMode( nScaleMode );
+ }
+ break;
+
+ default:
+ AnimatedImagesPeer_Base::setProperty( i_propertyName, i_value );
+ break;
+ }
+ }
+
+
+ Any SAL_CALL AnimatedImagesPeer::getProperty( const OUString& i_propertyName )
+ {
+ SolarMutexGuard aGuard;
+
+ Any aReturn;
+
+ VclPtr<Throbber> pThrobber = GetAsDynamic<Throbber>();
+ if ( !pThrobber )
+ return VCLXWindow::getProperty( i_propertyName );
+
+ const sal_uInt16 nPropertyId = GetPropertyId( i_propertyName );
+ switch ( nPropertyId )
+ {
+ case BASEPROPERTY_STEP_TIME:
+ aReturn <<= pThrobber->getStepTime();
+ break;
+
+ case BASEPROPERTY_AUTO_REPEAT:
+ aReturn <<= pThrobber->getRepeat();
+ break;
+
+ case BASEPROPERTY_IMAGE_SCALE_MODE:
+ {
+ VclPtr<ImageControl> pImageControl = GetAsDynamic<ImageControl>();
+ aReturn <<= ( pImageControl ? pImageControl->GetScaleMode() : ImageScaleMode::ANISOTROPIC );
+ }
+ break;
+
+ default:
+ aReturn = AnimatedImagesPeer_Base::getProperty( i_propertyName );
+ break;
+ }
+
+ return aReturn;
+ }
+
+
+ void AnimatedImagesPeer::ProcessWindowEvent( const VclWindowEvent& i_windowEvent )
+ {
+ if ( i_windowEvent.GetId() == VclEventId::WindowResize )
+ {
+ updateImageList_nothrow();
+ }
+
+ AnimatedImagesPeer_Base::ProcessWindowEvent( i_windowEvent );
+ }
+
+
+ void AnimatedImagesPeer::impl_updateImages_nolck( const Reference< XInterface >& i_animatedImages )
+ {
+ SolarMutexGuard aGuard;
+
+ updateImageList_nothrow( Reference< XAnimatedImages >( i_animatedImages, UNO_QUERY_THROW ) );
+ }
+
+
+ void SAL_CALL AnimatedImagesPeer::elementInserted( const ContainerEvent& i_event )
+ {
+ SolarMutexGuard aGuard;
+ Reference< XAnimatedImages > xAnimatedImages( i_event.Source, UNO_QUERY_THROW );
+
+ sal_Int32 nPosition(0);
+ OSL_VERIFY( i_event.Accessor >>= nPosition );
+ size_t position = size_t( nPosition );
+ if ( position > maCachedImageSets.size() )
+ {
+ OSL_ENSURE( false, "AnimatedImagesPeer::elementInserted: illegal accessor/index!" );
+ updateImageList_nothrow( xAnimatedImages );
+ }
+
+ Sequence< OUString > aImageURLs;
+ OSL_VERIFY( i_event.Element >>= aImageURLs );
+ ::std::vector< CachedImage > aImages;
+ lcl_init( aImageURLs, aImages );
+ maCachedImageSets.insert( maCachedImageSets.begin() + position, aImages );
+ updateImageList_nothrow();
+ }
+
+
+ void SAL_CALL AnimatedImagesPeer::elementRemoved( const ContainerEvent& i_event )
+ {
+ SolarMutexGuard aGuard;
+ Reference< XAnimatedImages > xAnimatedImages( i_event.Source, UNO_QUERY_THROW );
+
+ sal_Int32 nPosition(0);
+ OSL_VERIFY( i_event.Accessor >>= nPosition );
+ size_t position = size_t( nPosition );
+ if ( position >= maCachedImageSets.size() )
+ {
+ OSL_ENSURE( false, "AnimatedImagesPeer::elementRemoved: illegal accessor/index!" );
+ updateImageList_nothrow( xAnimatedImages );
+ }
+
+ maCachedImageSets.erase( maCachedImageSets.begin() + position );
+ updateImageList_nothrow();
+ }
+
+
+ void SAL_CALL AnimatedImagesPeer::elementReplaced( const ContainerEvent& i_event )
+ {
+ SolarMutexGuard aGuard;
+ Reference< XAnimatedImages > xAnimatedImages( i_event.Source, UNO_QUERY_THROW );
+
+ sal_Int32 nPosition(0);
+ OSL_VERIFY( i_event.Accessor >>= nPosition );
+ size_t position = size_t( nPosition );
+ if ( position >= maCachedImageSets.size() )
+ {
+ OSL_ENSURE( false, "AnimatedImagesPeer::elementReplaced: illegal accessor/index!" );
+ updateImageList_nothrow( xAnimatedImages );
+ }
+
+ Sequence< OUString > aImageURLs;
+ OSL_VERIFY( i_event.Element >>= aImageURLs );
+ ::std::vector< CachedImage > aImages;
+ lcl_init( aImageURLs, aImages );
+ maCachedImageSets[ position ] = aImages;
+ updateImageList_nothrow();
+ }
+
+
+ void SAL_CALL AnimatedImagesPeer::disposing( const EventObject& i_event )
+ {
+ VCLXWindow::disposing( i_event );
+ }
+
+
+ void SAL_CALL AnimatedImagesPeer::modified( const EventObject& i_event )
+ {
+ impl_updateImages_nolck( i_event.Source );
+ }
+
+
+ void SAL_CALL AnimatedImagesPeer::dispose( )
+ {
+ AnimatedImagesPeer_Base::dispose();
+ SolarMutexGuard aGuard;
+ maCachedImageSets.resize(0);
+ }
+
+ void AnimatedImagesPeer::updateImageList_nothrow()
+ {
+ VclPtr<Throbber> pThrobber = GetAsDynamic<Throbber>();
+ if ( !pThrobber )
+ return;
+
+ try
+ {
+ // collect the image sizes of the different image sets
+ const Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
+ const Reference< XGraphicProvider > xGraphicProvider( css::graphic::GraphicProvider::create(xContext) );
+
+ const bool isHighContrast = pThrobber->GetSettings().GetStyleSettings().GetHighContrastMode();
+
+ sal_Int32 nPreferredSet = -1;
+ const size_t nImageSetCount = maCachedImageSets.size();
+ if ( nImageSetCount < 2 )
+ {
+ nPreferredSet = sal_Int32( nImageSetCount ) - 1;
+ }
+ else
+ {
+ ::std::vector< Size > aImageSizes( nImageSetCount );
+ for ( size_t nImageSet = 0; nImageSet < nImageSetCount; ++nImageSet )
+ {
+ ::std::vector< CachedImage > const& rImageSet( maCachedImageSets[ nImageSet ] );
+ if ( ( rImageSet.empty() )
+ || ( !lcl_ensureImage_throw( xGraphicProvider, isHighContrast, rImageSet[0] ) )
+ )
+ {
+ aImageSizes[ nImageSet ] = Size( SAL_MAX_INT32, SAL_MAX_INT32 );
+ }
+ else
+ {
+ aImageSizes[ nImageSet ] = lcl_getGraphicSizePixel( rImageSet[0].xGraphic );
+ }
+ }
+
+ // find the set with the smallest difference between window size and image size
+ const ::Size aWindowSizePixel = pThrobber->GetSizePixel();
+ tools::Long nMinimalDistance = ::std::numeric_limits< tools::Long >::max();
+ for ( ::std::vector< Size >::const_iterator check = aImageSizes.begin();
+ check != aImageSizes.end();
+ ++check
+ )
+ {
+ if ( ( check->Width > aWindowSizePixel.Width() )
+ || ( check->Height > aWindowSizePixel.Height() )
+ )
+ // do not use an image set which doesn't fit into the window
+ continue;
+
+ const sal_Int64 distance =
+ ( aWindowSizePixel.Width() - check->Width ) * ( aWindowSizePixel.Width() - check->Width )
+ + ( aWindowSizePixel.Height() - check->Height ) * ( aWindowSizePixel.Height() - check->Height );
+ if ( distance < nMinimalDistance )
+ {
+ nMinimalDistance = distance;
+ nPreferredSet = check - aImageSizes.begin();
+ }
+ }
+ }
+
+ // found a set?
+ std::vector< Image > aImages;
+ if ( ( nPreferredSet >= 0 ) && ( o3tl::make_unsigned( nPreferredSet ) < nImageSetCount ) )
+ {
+ // => set the images
+ ::std::vector< CachedImage > const& rImageSet( maCachedImageSets[ nPreferredSet ] );
+ aImages.resize( rImageSet.size() );
+ sal_Int32 imageIndex = 0;
+ for ( const auto& rCachedImage : rImageSet )
+ {
+ lcl_ensureImage_throw( xGraphicProvider, isHighContrast, rCachedImage );
+ aImages[ imageIndex++ ] = Image(rCachedImage.xGraphic);
+ }
+ }
+ pThrobber->setImageList( std::move(aImages) );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit");
+ }
+ }
+
+
+ void AnimatedImagesPeer::updateImageList_nothrow( const Reference< XAnimatedImages >& i_images )
+ {
+ try
+ {
+ const sal_Int32 nImageSetCount = i_images->getImageSetCount();
+ maCachedImageSets.resize(0);
+ for ( sal_Int32 set = 0; set < nImageSetCount; ++set )
+ {
+ const Sequence< OUString > aImageURLs( i_images->getImageSet( set ) );
+ ::std::vector< CachedImage > aImages;
+ lcl_init( aImageURLs, aImages );
+ maCachedImageSets.push_back( aImages );
+ }
+
+ updateImageList_nothrow();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit");
+ }
+ }
+
+} // namespace toolkit
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/awt/asynccallback.cxx b/toolkit/source/awt/asynccallback.cxx
new file mode 100644
index 0000000000..f6804d9c23
--- /dev/null
+++ b/toolkit/source/awt/asynccallback.cxx
@@ -0,0 +1,122 @@
+/* -*- 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 <utility>
+#include <vcl/svapp.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/awt/XRequestCallback.hpp>
+
+/// anonymous implementation namespace
+namespace {
+
+class AsyncCallback:
+ public ::cppu::WeakImplHelper<
+ css::lang::XServiceInfo,
+ css::awt::XRequestCallback>
+{
+public:
+ AsyncCallback() {}
+ AsyncCallback(const AsyncCallback&) = delete;
+ AsyncCallback& operator=(const AsyncCallback&) = delete;
+
+ // css::lang::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;
+
+ // css::awt::XRequestCallback:
+ virtual void SAL_CALL addCallback(const css::uno::Reference< css::awt::XCallback > & xCallback, const css::uno::Any & aData) override;
+
+private:
+
+ struct CallbackData
+ {
+ CallbackData( css::uno::Reference< css::awt::XCallback > _xCallback, css::uno::Any aAny ) :
+ xCallback(std::move( _xCallback )), aData(std::move( aAny )) {}
+
+ css::uno::Reference< css::awt::XCallback > xCallback;
+ css::uno::Any aData;
+ };
+
+ DECL_STATIC_LINK( AsyncCallback, Notify_Impl, void*, void );
+
+ virtual ~AsyncCallback() override {}
+};
+
+// com.sun.star.uno.XServiceInfo:
+OUString SAL_CALL AsyncCallback::getImplementationName()
+{
+ return "com.sun.star.awt.comp.AsyncCallback";
+}
+
+sal_Bool SAL_CALL AsyncCallback::supportsService(OUString const & serviceName)
+{
+ return cppu::supportsService(this, serviceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL AsyncCallback::getSupportedServiceNames()
+{
+ return { "com.sun.star.awt.AsyncCallback" };
+}
+
+// css::awt::XRequestCallback:
+void SAL_CALL AsyncCallback::addCallback(const css::uno::Reference< css::awt::XCallback > & xCallback, const css::uno::Any & aData)
+{
+ if ( Application::IsInMain() )
+ {
+ // NOTE: We don't need SolarMutexGuard here as Application::PostUserEvent is thread-safe
+ CallbackData* pCallbackData = new CallbackData( xCallback, aData );
+ Application::PostUserEvent( LINK( this, AsyncCallback, Notify_Impl ), pCallbackData );
+ }
+}
+
+// private asynchronous link to call reference to the callback object
+IMPL_STATIC_LINK( AsyncCallback, Notify_Impl, void*, p, void )
+{
+ CallbackData* pCallbackData = static_cast<CallbackData*>(p);
+ try
+ {
+ // Asynchronous execution
+ // Check pointer and reference before!
+ if ( pCallbackData && pCallbackData->xCallback.is() )
+ pCallbackData->xCallback->notify( pCallbackData->aData );
+ }
+ catch ( css::uno::Exception& )
+ {
+ }
+
+ delete pCallbackData;
+}
+
+} // closing anonymous implementation namespace
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_awt_comp_AsyncCallback_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new AsyncCallback());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/awt/non-interactable-containers.xml b/toolkit/source/awt/non-interactable-containers.xml
new file mode 100644
index 0000000000..00f3f2a93e
--- /dev/null
+++ b/toolkit/source/awt/non-interactable-containers.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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 .
+ -->
+
+<dialog xmlns="http://openoffice.org/2007/layout"
+ xmlns:cnt="http://openoffice.org/2007/layout/container"
+ title="Interactable Containers" optimumsize="true"
+ border="true" sizeable="true" moveable="true">
+ <hbox>
+ <table columns="3" cnt:title="Page 1">
+ <pushbutton cnt:x-expand="false" cnt:row-span="2" label="1,1" />
+ <pushbutton cnt:y-expand="false" label="1,2" />
+ <pushbutton cnt:y-expand="false" label="1,3" />
+ <pushbutton cnt:col-span="2" label="2,1" />
+ </table>
+ </hbox>
+</dialog>
diff --git a/toolkit/source/awt/scrollabledialog.cxx b/toolkit/source/awt/scrollabledialog.cxx
new file mode 100644
index 0000000000..bcc8d18e07
--- /dev/null
+++ b/toolkit/source/awt/scrollabledialog.cxx
@@ -0,0 +1,173 @@
+/* -*- 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 <helper/scrollabledialog.hxx>
+#include <vcl/settings.hxx>
+
+namespace toolkit
+{
+
+// Using WB_AUTOHSCROLL, WB_AUTOVSCROLL here sucks big time, there is a
+// problem in the toolkit class where there are some clashing IDs
+// ( css::awt::VclWindowPeerAttribute::VSCROLL has the same value
+// as css::awt::WindowAttribute::NODECORATION and they are used
+// in the same bitmap :-( WB_VSCROLL & WB_HSCROLL apparently are only for
+// child classes ( whole thing is a mess if you ask me )
+ScrollableDialog::ScrollableDialog( vcl::Window* pParent, WinBits nStyle, Dialog::InitFlag eFlag )
+ : Dialog( pParent, nStyle & ~( WB_AUTOHSCROLL | WB_AUTOVSCROLL ), eFlag ),
+ maHScrollBar( VclPtr<ScrollBar>::Create(this, WB_HSCROLL | WB_DRAG) ),
+ maVScrollBar( VclPtr<ScrollBar>::Create(this, WB_VSCROLL | WB_DRAG) ),
+ mbHasHoriBar( false ),
+ mbHasVertBar( false ),
+ maScrollVis( None )
+{
+ Link<ScrollBar*,void> aLink( LINK( this, ScrollableDialog, ScrollBarHdl ) );
+ maVScrollBar->SetScrollHdl( aLink );
+ maHScrollBar->SetScrollHdl( aLink );
+
+ ScrollBarVisibility aVis = None;
+
+ if ( nStyle & ( WB_AUTOHSCROLL | WB_AUTOVSCROLL ) )
+ {
+ if ( nStyle & WB_AUTOHSCROLL )
+ aVis = Hori;
+ if ( nStyle & WB_AUTOVSCROLL )
+ {
+ if ( aVis == Hori )
+ aVis = Both;
+ else
+ aVis = Vert;
+ }
+ }
+ setScrollVisibility( aVis );
+ mnScrWidth = Dialog::GetSettings().GetStyleSettings().GetScrollBarSize();
+}
+
+void ScrollableDialog::setScrollVisibility( ScrollBarVisibility rVisState )
+{
+ maScrollVis = rVisState;
+ if ( maScrollVis == Hori || maScrollVis == Both )
+ {
+ mbHasHoriBar = true;
+ maHScrollBar->Show();
+ }
+ if ( maScrollVis == Vert || maScrollVis == Both )
+ {
+ mbHasVertBar = true;
+ maVScrollBar->Show();
+ }
+ if ( mbHasHoriBar || mbHasVertBar )
+ SetStyle( Dialog::GetStyle() | WB_CLIPCHILDREN );
+}
+
+ScrollableDialog::~ScrollableDialog()
+{
+ disposeOnce();
+}
+
+void ScrollableDialog::dispose()
+{
+ maHScrollBar.disposeAndClear();
+ maVScrollBar.disposeAndClear();
+ Dialog::dispose();
+}
+
+void ScrollableDialog::lcl_Scroll( tools::Long nX, tools::Long nY )
+{
+ tools::Long nXScroll = mnScrollPos.X() - nX;
+ tools::Long nYScroll = mnScrollPos.Y() - nY;
+ mnScrollPos = Point( nX, nY );
+
+ tools::Rectangle aScrollableArea( 0, 0, maScrollArea.Width(), maScrollArea.Height() );
+ Scroll(nXScroll, nYScroll, aScrollableArea );
+ // Manually scroll all children ( except the scrollbars )
+ for ( int index = 0; index < GetChildCount(); ++index )
+ {
+ vcl::Window* pChild = GetChild( index );
+ if ( pChild && pChild != maVScrollBar.get() && pChild != maHScrollBar.get() )
+ {
+ Point aPos = pChild->GetPosPixel();
+ aPos += Point( nXScroll, nYScroll );
+ pChild->SetPosPixel( aPos );
+ }
+ }
+}
+
+IMPL_LINK( ScrollableDialog, ScrollBarHdl, ScrollBar*, pSB, void )
+{
+ sal_uInt16 nPos = static_cast<sal_uInt16>(pSB->GetThumbPos());
+ if( pSB == maVScrollBar.get() )
+ lcl_Scroll(mnScrollPos.X(), nPos );
+ else if( pSB == maHScrollBar.get() )
+ lcl_Scroll(nPos, mnScrollPos.Y() );
+}
+
+void ScrollableDialog::SetScrollTop( tools::Long nTop )
+{
+ Point aOld = mnScrollPos;
+ lcl_Scroll( mnScrollPos.X() , mnScrollPos.Y() - nTop );
+ maHScrollBar->SetThumbPos( 0 );
+ // new pos is 0,0
+ mnScrollPos = aOld;
+}
+void ScrollableDialog::SetScrollLeft( tools::Long nLeft )
+{
+ Point aOld = mnScrollPos;
+ lcl_Scroll( mnScrollPos.X() - nLeft , mnScrollPos.Y() );
+ maVScrollBar->SetThumbPos( 0 );
+ // new pos is 0,0
+ mnScrollPos = aOld;
+}
+
+void ScrollableDialog::SetScrollWidth( tools::Long nWidth )
+{
+ maScrollArea.setWidth( nWidth );
+ ResetScrollBars();
+}
+
+void ScrollableDialog::SetScrollHeight( tools::Long nHeight )
+{
+ maScrollArea.setHeight( nHeight );
+ ResetScrollBars();
+}
+
+void ScrollableDialog::Resize()
+{
+ ResetScrollBars();
+}
+
+void ScrollableDialog::ResetScrollBars()
+{
+ Size aOutSz = GetOutputSizePixel();
+
+ Point aVPos( aOutSz.Width() - mnScrWidth, 0 );
+ Point aHPos( 0, aOutSz.Height() - mnScrWidth );
+
+ maVScrollBar->SetPosSizePixel( aVPos, Size( mnScrWidth, GetSizePixel().Height() - mnScrWidth ) );
+ maHScrollBar->SetPosSizePixel( aHPos, Size( GetSizePixel().Width() - mnScrWidth, mnScrWidth ) );
+
+ maHScrollBar->SetRangeMax( maScrollArea.Width() + mnScrWidth );
+ maHScrollBar->SetVisibleSize( GetSizePixel().Width() );
+
+ maVScrollBar->SetRangeMax( maScrollArea.Height() + mnScrWidth );
+ maVScrollBar->SetVisibleSize( GetSizePixel().Height() );
+}
+
+} // toolkit
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/awt/stylesettings.cxx b/toolkit/source/awt/stylesettings.cxx
new file mode 100644
index 0000000000..75c2b687d2
--- /dev/null
+++ b/toolkit/source/awt/stylesettings.cxx
@@ -0,0 +1,926 @@
+/* -*- 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 "stylesettings.hxx"
+#include <toolkit/awt/vclxwindow.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+
+#include <com/sun/star/lang/DisposedException.hpp>
+
+#include <osl/diagnose.h>
+#include <osl/mutex.hxx>
+#include <vcl/event.hxx>
+#include <vcl/window.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+
+
+namespace toolkit
+{
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::RuntimeException;
+ using ::com::sun::star::lang::DisposedException;
+ using ::com::sun::star::lang::EventObject;
+ using ::com::sun::star::awt::FontDescriptor;
+ using ::com::sun::star::awt::XStyleChangeListener;
+
+
+ IMPL_LINK( WindowStyleSettings, OnWindowEvent, VclWindowEvent&, rEvent, void )
+ {
+ if ( rEvent.GetId() != VclEventId::WindowDataChanged )
+ return;
+ const DataChangedEvent* pDataChangedEvent = static_cast< const DataChangedEvent* >( rEvent.GetData() );
+ if ( !pDataChangedEvent || ( pDataChangedEvent->GetType() != DataChangedEventType::SETTINGS ) )
+ return;
+ if ( !( pDataChangedEvent->GetFlags() & AllSettingsFlags::STYLE ) )
+ return;
+
+ EventObject aEvent( *pOwningWindow );
+ aStyleChangeListeners.notifyEach( &XStyleChangeListener::styleSettingsChanged, aEvent );
+ }
+
+
+ //= StyleMethodGuard
+
+ namespace {
+
+ class StyleMethodGuard
+ {
+ public:
+ explicit StyleMethodGuard( const VCLXWindow* pOwningWindow )
+ {
+ if ( pOwningWindow == nullptr )
+ throw DisposedException();
+ }
+
+ private:
+ SolarMutexGuard m_aGuard;
+ };
+
+ }
+
+ //= WindowStyleSettings
+
+
+ WindowStyleSettings::WindowStyleSettings(::osl::Mutex& i_rListenerMutex, VCLXWindow& i_rOwningWindow )
+ : pOwningWindow( &i_rOwningWindow )
+ ,aStyleChangeListeners( i_rListenerMutex )
+ {
+ VclPtr<vcl::Window> pWindow = i_rOwningWindow.GetWindow();
+ if ( !pWindow )
+ throw RuntimeException();
+ pWindow->AddEventListener( LINK( this, WindowStyleSettings, OnWindowEvent ) );
+ }
+
+
+ WindowStyleSettings::~WindowStyleSettings()
+ {
+ }
+
+
+ void WindowStyleSettings::dispose()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+
+ VclPtr<vcl::Window> pWindow = pOwningWindow->GetWindow();
+ OSL_ENSURE( pWindow, "WindowStyleSettings::dispose: window has been reset before we could revoke the listener!" );
+ if ( pWindow )
+ pWindow->RemoveEventListener( LINK( this, WindowStyleSettings, OnWindowEvent ) );
+
+ EventObject aEvent( *this );
+ aStyleChangeListeners.disposeAndClear( aEvent );
+
+ pOwningWindow = nullptr;
+ }
+
+
+ sal_Int32 WindowStyleSettings::ImplGetStyleColor( Color const & (StyleSettings::*i_pGetter)() const ) const
+ {
+ const VclPtr<vcl::Window>& pWindow = pOwningWindow->GetWindow();
+ const AllSettings aAllSettings = pWindow->GetSettings();
+ const StyleSettings& aStyleSettings = aAllSettings.GetStyleSettings();
+ return sal_Int32((aStyleSettings.*i_pGetter)());
+ }
+
+ void WindowStyleSettings::ImplSetStyleColor( void (StyleSettings::*i_pSetter)( Color const & ), sal_Int32 i_nColor )
+ {
+ VclPtr<vcl::Window> pWindow = pOwningWindow->GetWindow();
+ AllSettings aAllSettings = pWindow->GetSettings();
+ StyleSettings aStyleSettings = aAllSettings.GetStyleSettings();
+ (aStyleSettings.*i_pSetter)( Color(ColorTransparency, i_nColor) );
+ aAllSettings.SetStyleSettings( aStyleSettings );
+ pWindow->SetSettings( aAllSettings );
+ }
+
+ FontDescriptor WindowStyleSettings::ImplGetStyleFont( vcl::Font const & (StyleSettings::*i_pGetter)() const ) const
+ {
+ const VclPtr<vcl::Window>& pWindow = pOwningWindow->GetWindow();
+ const AllSettings aAllSettings = pWindow->GetSettings();
+ const StyleSettings& aStyleSettings = aAllSettings.GetStyleSettings();
+ return VCLUnoHelper::CreateFontDescriptor( (aStyleSettings.*i_pGetter)() );
+ }
+
+ void WindowStyleSettings::ImplSetStyleFont( void (StyleSettings::*i_pSetter)( vcl::Font const &),
+ vcl::Font const & (StyleSettings::*i_pGetter)() const, const FontDescriptor& i_rFont )
+ {
+ VclPtr<vcl::Window> pWindow = pOwningWindow->GetWindow();
+ AllSettings aAllSettings = pWindow->GetSettings();
+ StyleSettings aStyleSettings = aAllSettings.GetStyleSettings();
+ const vcl::Font aNewFont = VCLUnoHelper::CreateFont( i_rFont, (aStyleSettings.*i_pGetter)() );
+ (aStyleSettings.*i_pSetter)( aNewFont );
+ aAllSettings.SetStyleSettings( aStyleSettings );
+ pWindow->SetSettings( aAllSettings );
+ }
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getActiveBorderColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetActiveBorderColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setActiveBorderColor( ::sal_Int32 _activebordercolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetActiveBorderColor, _activebordercolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getActiveColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetActiveColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setActiveColor( ::sal_Int32 _activecolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetActiveColor, _activecolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getActiveTabColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetActiveTabColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setActiveTabColor( ::sal_Int32 _activetabcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetActiveTabColor, _activetabcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getActiveTextColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetActiveTextColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setActiveTextColor( ::sal_Int32 _activetextcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetActiveTextColor, _activetextcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getButtonRolloverTextColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetButtonRolloverTextColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setButtonRolloverTextColor( ::sal_Int32 _buttonrollovertextcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetButtonRolloverTextColor, _buttonrollovertextcolor );
+ // Also need to set ActionButtonRolloverTextColor as this setting can't be
+ // set through the UNO interface otherwise.
+ // Previously this setting was used to set colors for both scenarios,
+ // but action button setting was added to differentiate the buttons from
+ // "normal" buttons in some themes.
+ ImplSetStyleColor( &StyleSettings::SetActionButtonRolloverTextColor, _buttonrollovertextcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getButtonTextColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetButtonTextColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setButtonTextColor( ::sal_Int32 _buttontextcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetButtonTextColor, _buttontextcolor );
+ // Also need to set ActionButtonTextColor and DefaultActionButtonTextColor
+ // as this two settings can't be set through the UNO interface otherwise.
+ // Previously this setting was used to set colors for all three scenarios,
+ // but action button setting was added to differentiate the buttons from
+ // "normal" buttons in some themes.
+ ImplSetStyleColor( &StyleSettings::SetActionButtonTextColor, _buttontextcolor );
+ ImplSetStyleColor( &StyleSettings::SetDefaultActionButtonTextColor, _buttontextcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getCheckedColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetCheckedColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setCheckedColor( ::sal_Int32 _checkedcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetCheckedColor, _checkedcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getDarkShadowColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetDarkShadowColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setDarkShadowColor( ::sal_Int32 _darkshadowcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetDarkShadowColor, _darkshadowcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getDeactiveBorderColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetDeactiveBorderColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setDeactiveBorderColor( ::sal_Int32 _deactivebordercolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetDeactiveBorderColor, _deactivebordercolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getDeactiveColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetDeactiveColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setDeactiveColor( ::sal_Int32 _deactivecolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetDeactiveColor, _deactivecolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getDeactiveTextColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetDeactiveTextColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setDeactiveTextColor( ::sal_Int32 _deactivetextcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetDeactiveTextColor, _deactivetextcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getDialogColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetDialogColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setDialogColor( ::sal_Int32 _dialogcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetDialogColor, _dialogcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getDialogTextColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetDialogTextColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setDialogTextColor( ::sal_Int32 _dialogtextcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetDialogTextColor, _dialogtextcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getDisableColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetDisableColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setDisableColor( ::sal_Int32 _disablecolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetDisableColor, _disablecolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getFaceColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetFaceColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setFaceColor( ::sal_Int32 _facecolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetFaceColor, _facecolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getFaceGradientColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ const VclPtr<vcl::Window>& pWindow = pOwningWindow->GetWindow();
+ const AllSettings aAllSettings = pWindow->GetSettings();
+ const StyleSettings& aStyleSettings = aAllSettings.GetStyleSettings();
+ return sal_Int32(aStyleSettings.GetFaceGradientColor());
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getFieldColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetFieldColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setFieldColor( ::sal_Int32 _fieldcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetFieldColor, _fieldcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getFieldRolloverTextColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetFieldRolloverTextColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setFieldRolloverTextColor( ::sal_Int32 _fieldrollovertextcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetFieldRolloverTextColor, _fieldrollovertextcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getFieldTextColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetFieldTextColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setFieldTextColor( ::sal_Int32 _fieldtextcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetFieldTextColor, _fieldtextcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getGroupTextColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetGroupTextColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setGroupTextColor( ::sal_Int32 _grouptextcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetGroupTextColor, _grouptextcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getHelpColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetHelpColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setHelpColor( ::sal_Int32 _helpcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetHelpColor, _helpcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getHelpTextColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetHelpTextColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setHelpTextColor( ::sal_Int32 _helptextcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetHelpTextColor, _helptextcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getHighlightColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetHighlightColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setHighlightColor( ::sal_Int32 _highlightcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetHighlightColor, _highlightcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getHighlightTextColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetHighlightTextColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setHighlightTextColor( ::sal_Int32 _highlighttextcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetHighlightTextColor, _highlighttextcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getInactiveTabColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetInactiveTabColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setInactiveTabColor( ::sal_Int32 _inactivetabcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetInactiveTabColor, _inactivetabcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getLabelTextColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetLabelTextColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setLabelTextColor( ::sal_Int32 _labeltextcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetLabelTextColor, _labeltextcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getLightColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetLightColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setLightColor( ::sal_Int32 _lightcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetLightColor, _lightcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getMenuBarColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetMenuBarColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setMenuBarColor( ::sal_Int32 _menubarcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetMenuBarColor, _menubarcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getMenuBarTextColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetMenuBarTextColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setMenuBarTextColor( ::sal_Int32 _menubartextcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetMenuBarTextColor, _menubartextcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getMenuBorderColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetMenuBorderColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setMenuBorderColor( ::sal_Int32 _menubordercolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetMenuBorderColor, _menubordercolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getMenuColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetMenuColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setMenuColor( ::sal_Int32 _menucolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetMenuColor, _menucolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getMenuHighlightColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetMenuHighlightColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setMenuHighlightColor( ::sal_Int32 _menuhighlightcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetMenuHighlightColor, _menuhighlightcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getMenuHighlightTextColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetMenuHighlightTextColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setMenuHighlightTextColor( ::sal_Int32 _menuhighlighttextcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetMenuHighlightTextColor, _menuhighlighttextcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getMenuTextColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetMenuTextColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setMenuTextColor( ::sal_Int32 _menutextcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetMenuTextColor, _menutextcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getMonoColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetMonoColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setMonoColor( ::sal_Int32 _monocolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetMonoColor, _monocolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getRadioCheckTextColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetRadioCheckTextColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setRadioCheckTextColor( ::sal_Int32 _radiochecktextcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetRadioCheckTextColor, _radiochecktextcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getSeparatorColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ const VclPtr<vcl::Window>& pWindow = pOwningWindow->GetWindow();
+ const AllSettings aAllSettings = pWindow->GetSettings();
+ const StyleSettings& aStyleSettings = aAllSettings.GetStyleSettings();
+ return sal_Int32(aStyleSettings.GetSeparatorColor());
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getShadowColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetShadowColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setShadowColor( ::sal_Int32 _shadowcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetShadowColor, _shadowcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getWindowColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetWindowColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setWindowColor( ::sal_Int32 _windowcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetWindowColor, _windowcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getWindowTextColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetWindowTextColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setWindowTextColor( ::sal_Int32 _windowtextcolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetWindowTextColor, _windowtextcolor );
+ }
+
+
+ ::sal_Int32 SAL_CALL WindowStyleSettings::getWorkspaceColor()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleColor( &StyleSettings::GetWorkspaceColor );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setWorkspaceColor( ::sal_Int32 _workspacecolor )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleColor( &StyleSettings::SetWorkspaceColor, _workspacecolor );
+ }
+
+
+ sal_Bool SAL_CALL WindowStyleSettings::getHighContrastMode()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ const VclPtr<vcl::Window>& pWindow = pOwningWindow->GetWindow();
+ const AllSettings aAllSettings = pWindow->GetSettings();
+ const StyleSettings& aStyleSettings = aAllSettings.GetStyleSettings();
+ return aStyleSettings.GetHighContrastMode();
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setHighContrastMode( sal_Bool _highcontrastmode )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ VclPtr<vcl::Window> pWindow = pOwningWindow->GetWindow();
+ AllSettings aAllSettings = pWindow->GetSettings();
+ StyleSettings aStyleSettings = aAllSettings.GetStyleSettings();
+ aStyleSettings.SetHighContrastMode( _highcontrastmode );
+ aAllSettings.SetStyleSettings( aStyleSettings );
+ pWindow->SetSettings( aAllSettings );
+ }
+
+
+ FontDescriptor SAL_CALL WindowStyleSettings::getApplicationFont()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleFont( &StyleSettings::GetAppFont );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setApplicationFont( const FontDescriptor& _applicationfont )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleFont( &StyleSettings::SetAppFont, &StyleSettings::GetAppFont, _applicationfont );
+ }
+
+
+ FontDescriptor SAL_CALL WindowStyleSettings::getHelpFont()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleFont( &StyleSettings::GetHelpFont );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setHelpFont( const FontDescriptor& _helpfont )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleFont( &StyleSettings::SetHelpFont, &StyleSettings::GetHelpFont, _helpfont );
+ }
+
+
+ FontDescriptor SAL_CALL WindowStyleSettings::getTitleFont()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleFont( &StyleSettings::GetTitleFont );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setTitleFont( const FontDescriptor& _titlefont )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleFont( &StyleSettings::SetTitleFont, &StyleSettings::GetTitleFont, _titlefont );
+ }
+
+
+ FontDescriptor SAL_CALL WindowStyleSettings::getFloatTitleFont()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleFont( &StyleSettings::GetFloatTitleFont );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setFloatTitleFont( const FontDescriptor& _floattitlefont )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleFont( &StyleSettings::SetFloatTitleFont, &StyleSettings::GetFloatTitleFont, _floattitlefont );
+ }
+
+
+ FontDescriptor SAL_CALL WindowStyleSettings::getMenuFont()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleFont( &StyleSettings::GetMenuFont );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setMenuFont( const FontDescriptor& _menufont )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleFont( &StyleSettings::SetMenuFont, &StyleSettings::GetMenuFont, _menufont );
+ }
+
+
+ FontDescriptor SAL_CALL WindowStyleSettings::getToolFont()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleFont( &StyleSettings::GetToolFont );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setToolFont( const FontDescriptor& _toolfont )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleFont( &StyleSettings::SetToolFont, &StyleSettings::GetToolFont, _toolfont );
+ }
+
+
+ FontDescriptor SAL_CALL WindowStyleSettings::getGroupFont()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleFont( &StyleSettings::GetGroupFont );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setGroupFont( const FontDescriptor& _groupfont )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleFont( &StyleSettings::SetGroupFont, &StyleSettings::GetGroupFont, _groupfont );
+ }
+
+
+ FontDescriptor SAL_CALL WindowStyleSettings::getLabelFont()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleFont( &StyleSettings::GetLabelFont );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setLabelFont( const FontDescriptor& _labelfont )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleFont( &StyleSettings::SetLabelFont, &StyleSettings::GetLabelFont, _labelfont );
+ }
+
+
+ FontDescriptor SAL_CALL WindowStyleSettings::getRadioCheckFont()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleFont( &StyleSettings::GetRadioCheckFont );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setRadioCheckFont( const FontDescriptor& _radiocheckfont )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleFont( &StyleSettings::SetRadioCheckFont, &StyleSettings::GetRadioCheckFont, _radiocheckfont );
+ }
+
+
+ FontDescriptor SAL_CALL WindowStyleSettings::getPushButtonFont()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleFont( &StyleSettings::GetPushButtonFont );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setPushButtonFont( const FontDescriptor& _pushbuttonfont )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleFont( &StyleSettings::SetPushButtonFont, &StyleSettings::GetPushButtonFont, _pushbuttonfont );
+ }
+
+
+ FontDescriptor SAL_CALL WindowStyleSettings::getFieldFont()
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ return ImplGetStyleFont( &StyleSettings::GetFieldFont );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::setFieldFont( const FontDescriptor& _fieldfont )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ ImplSetStyleFont( &StyleSettings::SetFieldFont, &StyleSettings::GetFieldFont, _fieldfont );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::addStyleChangeListener( const Reference< XStyleChangeListener >& i_rListener )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ if ( i_rListener.is() )
+ aStyleChangeListeners.addInterface( i_rListener );
+ }
+
+
+ void SAL_CALL WindowStyleSettings::removeStyleChangeListener( const Reference< XStyleChangeListener >& i_rListener )
+ {
+ StyleMethodGuard aGuard( pOwningWindow );
+ if ( i_rListener.is() )
+ aStyleChangeListeners.removeInterface( i_rListener );
+ }
+
+
+} // namespace toolkit
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/awt/stylesettings.hxx b/toolkit/source/awt/stylesettings.hxx
new file mode 100644
index 0000000000..4e3f0b2df9
--- /dev/null
+++ b/toolkit/source/awt/stylesettings.hxx
@@ -0,0 +1,181 @@
+/* -*- 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_AWT_STYLESETTINGS_HXX
+#define INCLUDED_TOOLKIT_SOURCE_AWT_STYLESETTINGS_HXX
+
+#include <com/sun/star/awt/XStyleSettings.hpp>
+
+#include <comphelper/interfacecontainer3.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <tools/link.hxx>
+
+namespace osl
+{
+ class Mutex;
+}
+class Color;
+class VCLXWindow;
+class VclWindowEvent;
+class StyleSettings;
+namespace vcl { class Font; }
+
+namespace toolkit
+{
+
+
+ //= WindowStyleSettings
+
+ typedef ::cppu::WeakImplHelper < css::awt::XStyleSettings
+ > WindowStyleSettings_Base;
+ class WindowStyleSettings : public WindowStyleSettings_Base
+ {
+ public:
+ WindowStyleSettings( ::osl::Mutex& i_rListenerMutex, VCLXWindow& i_rOwningWindow );
+ virtual ~WindowStyleSettings() override;
+
+ void dispose();
+
+ // XStyleSettings
+ virtual ::sal_Int32 SAL_CALL getActiveBorderColor() override;
+ virtual void SAL_CALL setActiveBorderColor( ::sal_Int32 _activebordercolor ) override;
+ virtual ::sal_Int32 SAL_CALL getActiveColor() override;
+ virtual void SAL_CALL setActiveColor( ::sal_Int32 _activecolor ) override;
+ virtual ::sal_Int32 SAL_CALL getActiveTabColor() override;
+ virtual void SAL_CALL setActiveTabColor( ::sal_Int32 _activetabcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getActiveTextColor() override;
+ virtual void SAL_CALL setActiveTextColor( ::sal_Int32 _activetextcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getButtonRolloverTextColor() override;
+ virtual void SAL_CALL setButtonRolloverTextColor( ::sal_Int32 _buttonrollovertextcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getButtonTextColor() override;
+ virtual void SAL_CALL setButtonTextColor( ::sal_Int32 _buttontextcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getCheckedColor() override;
+ virtual void SAL_CALL setCheckedColor( ::sal_Int32 _checkedcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getDarkShadowColor() override;
+ virtual void SAL_CALL setDarkShadowColor( ::sal_Int32 _darkshadowcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getDeactiveBorderColor() override;
+ virtual void SAL_CALL setDeactiveBorderColor( ::sal_Int32 _deactivebordercolor ) override;
+ virtual ::sal_Int32 SAL_CALL getDeactiveColor() override;
+ virtual void SAL_CALL setDeactiveColor( ::sal_Int32 _deactivecolor ) override;
+ virtual ::sal_Int32 SAL_CALL getDeactiveTextColor() override;
+ virtual void SAL_CALL setDeactiveTextColor( ::sal_Int32 _deactivetextcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getDialogColor() override;
+ virtual void SAL_CALL setDialogColor( ::sal_Int32 _dialogcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getDialogTextColor() override;
+ virtual void SAL_CALL setDialogTextColor( ::sal_Int32 _dialogtextcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getDisableColor() override;
+ virtual void SAL_CALL setDisableColor( ::sal_Int32 _disablecolor ) override;
+ virtual ::sal_Int32 SAL_CALL getFaceColor() override;
+ virtual void SAL_CALL setFaceColor( ::sal_Int32 _facecolor ) override;
+ virtual ::sal_Int32 SAL_CALL getFaceGradientColor() override;
+ virtual ::sal_Int32 SAL_CALL getFieldColor() override;
+ virtual void SAL_CALL setFieldColor( ::sal_Int32 _fieldcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getFieldRolloverTextColor() override;
+ virtual void SAL_CALL setFieldRolloverTextColor( ::sal_Int32 _fieldrollovertextcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getFieldTextColor() override;
+ virtual void SAL_CALL setFieldTextColor( ::sal_Int32 _fieldtextcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getGroupTextColor() override;
+ virtual void SAL_CALL setGroupTextColor( ::sal_Int32 _grouptextcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getHelpColor() override;
+ virtual void SAL_CALL setHelpColor( ::sal_Int32 _helpcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getHelpTextColor() override;
+ virtual void SAL_CALL setHelpTextColor( ::sal_Int32 _helptextcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getHighlightColor() override;
+ virtual void SAL_CALL setHighlightColor( ::sal_Int32 _highlightcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getHighlightTextColor() override;
+ virtual void SAL_CALL setHighlightTextColor( ::sal_Int32 _highlighttextcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getInactiveTabColor() override;
+ virtual void SAL_CALL setInactiveTabColor( ::sal_Int32 _inactivetabcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getLabelTextColor() override;
+ virtual void SAL_CALL setLabelTextColor( ::sal_Int32 _labeltextcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getLightColor() override;
+ virtual void SAL_CALL setLightColor( ::sal_Int32 _lightcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getMenuBarColor() override;
+ virtual void SAL_CALL setMenuBarColor( ::sal_Int32 _menubarcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getMenuBarTextColor() override;
+ virtual void SAL_CALL setMenuBarTextColor( ::sal_Int32 _menubartextcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getMenuBorderColor() override;
+ virtual void SAL_CALL setMenuBorderColor( ::sal_Int32 _menubordercolor ) override;
+ virtual ::sal_Int32 SAL_CALL getMenuColor() override;
+ virtual void SAL_CALL setMenuColor( ::sal_Int32 _menucolor ) override;
+ virtual ::sal_Int32 SAL_CALL getMenuHighlightColor() override;
+ virtual void SAL_CALL setMenuHighlightColor( ::sal_Int32 _menuhighlightcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getMenuHighlightTextColor() override;
+ virtual void SAL_CALL setMenuHighlightTextColor( ::sal_Int32 _menuhighlighttextcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getMenuTextColor() override;
+ virtual void SAL_CALL setMenuTextColor( ::sal_Int32 _menutextcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getMonoColor() override;
+ virtual void SAL_CALL setMonoColor( ::sal_Int32 _monocolor ) override;
+ virtual ::sal_Int32 SAL_CALL getRadioCheckTextColor() override;
+ virtual void SAL_CALL setRadioCheckTextColor( ::sal_Int32 _radiochecktextcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getSeparatorColor() override;
+ virtual ::sal_Int32 SAL_CALL getShadowColor() override;
+ virtual void SAL_CALL setShadowColor( ::sal_Int32 _shadowcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getWindowColor() override;
+ virtual void SAL_CALL setWindowColor( ::sal_Int32 _windowcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getWindowTextColor() override;
+ virtual void SAL_CALL setWindowTextColor( ::sal_Int32 _windowtextcolor ) override;
+ virtual ::sal_Int32 SAL_CALL getWorkspaceColor() override;
+ virtual void SAL_CALL setWorkspaceColor( ::sal_Int32 _workspacecolor ) override;
+ virtual sal_Bool SAL_CALL getHighContrastMode() override;
+ virtual void SAL_CALL setHighContrastMode( sal_Bool _highcontrastmode ) override;
+ virtual css::awt::FontDescriptor SAL_CALL getApplicationFont() override;
+ virtual void SAL_CALL setApplicationFont( const css::awt::FontDescriptor& _applicationfont ) override;
+ virtual css::awt::FontDescriptor SAL_CALL getHelpFont() override;
+ virtual void SAL_CALL setHelpFont( const css::awt::FontDescriptor& _helpfont ) override;
+ virtual css::awt::FontDescriptor SAL_CALL getTitleFont() override;
+ virtual void SAL_CALL setTitleFont( const css::awt::FontDescriptor& _titlefont ) override;
+ virtual css::awt::FontDescriptor SAL_CALL getFloatTitleFont() override;
+ virtual void SAL_CALL setFloatTitleFont( const css::awt::FontDescriptor& _floattitlefont ) override;
+ virtual css::awt::FontDescriptor SAL_CALL getMenuFont() override;
+ virtual void SAL_CALL setMenuFont( const css::awt::FontDescriptor& _menufont ) override;
+ virtual css::awt::FontDescriptor SAL_CALL getToolFont() override;
+ virtual void SAL_CALL setToolFont( const css::awt::FontDescriptor& _toolfont ) override;
+ virtual css::awt::FontDescriptor SAL_CALL getGroupFont() override;
+ virtual void SAL_CALL setGroupFont( const css::awt::FontDescriptor& _groupfont ) override;
+ virtual css::awt::FontDescriptor SAL_CALL getLabelFont() override;
+ virtual void SAL_CALL setLabelFont( const css::awt::FontDescriptor& _labelfont ) override;
+ virtual css::awt::FontDescriptor SAL_CALL getRadioCheckFont() override;
+ virtual void SAL_CALL setRadioCheckFont( const css::awt::FontDescriptor& _radiocheckfont ) override;
+ virtual css::awt::FontDescriptor SAL_CALL getPushButtonFont() override;
+ virtual void SAL_CALL setPushButtonFont( const css::awt::FontDescriptor& _pushbuttonfont ) override;
+ virtual css::awt::FontDescriptor SAL_CALL getFieldFont() override;
+ virtual void SAL_CALL setFieldFont( const css::awt::FontDescriptor& _fieldfont ) override;
+ virtual void SAL_CALL addStyleChangeListener( const css::uno::Reference< css::awt::XStyleChangeListener >& Listener ) override;
+ virtual void SAL_CALL removeStyleChangeListener( const css::uno::Reference< css::awt::XStyleChangeListener >& Listener ) override;
+
+ private:
+ void ImplSetStyleFont( void (StyleSettings::*i_pSetter)( vcl::Font const &),
+ vcl::Font const & (StyleSettings::*i_pGetter)() const, const css::awt::FontDescriptor& i_rFont );
+ void ImplSetStyleColor( void (StyleSettings::*i_pSetter)( Color const & ), sal_Int32 i_nColor );
+ sal_Int32 ImplGetStyleColor( Color const & (StyleSettings::*i_pGetter)() const ) const;
+ css::awt::FontDescriptor ImplGetStyleFont( vcl::Font const & (StyleSettings::*i_pGetter)() const ) const;
+ DECL_LINK( OnWindowEvent, VclWindowEvent&, void );
+
+ VCLXWindow* pOwningWindow;
+ ::comphelper::OInterfaceContainerHelper3<css::awt::XStyleChangeListener> aStyleChangeListeners;
+ };
+
+
+} // namespace toolkit
+
+
+#endif // INCLUDED_TOOLKIT_SOURCE_AWT_STYLESETTINGS_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/awt/vclxaccessiblecomponent.cxx b/toolkit/source/awt/vclxaccessiblecomponent.cxx
new file mode 100644
index 0000000000..9c2321ede3
--- /dev/null
+++ b/toolkit/source/awt/vclxaccessiblecomponent.cxx
@@ -0,0 +1,854 @@
+/* -*- 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/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <comphelper/accessiblecontexthelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <toolkit/awt/vclxaccessiblecomponent.hxx>
+#include <toolkit/awt/vclxwindow.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <toolkit/awt/vclxfont.hxx>
+#include <vcl/toolkit/dialog.hxx>
+#include <vcl/vclevent.hxx>
+#include <vcl/window.hxx>
+#include <vcl/toolkit/edit.hxx>
+#include <vcl/settings.hxx>
+#include <tools/debug.hxx>
+#include <unotools/accessiblerelationsethelper.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/menu.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::comphelper;
+
+VCLXAccessibleComponent::VCLXAccessibleComponent( VCLXWindow* pVCLXWindow )
+{
+ m_xVCLXWindow = pVCLXWindow;
+
+ DBG_ASSERT( pVCLXWindow->GetWindow(), "VCLXAccessibleComponent - no window!" );
+ m_xEventSource = pVCLXWindow->GetWindow();
+ if ( m_xEventSource )
+ {
+ m_xEventSource->AddEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
+ m_xEventSource->AddChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
+ }
+
+ // announce the XAccessible of our creator to the base class
+ lateInit( pVCLXWindow );
+}
+
+VCLXWindow* VCLXAccessibleComponent::GetVCLXWindow() const
+{
+ return m_xVCLXWindow.get();
+}
+
+void VCLXAccessibleComponent::DisconnectEvents()
+{
+ if ( m_xEventSource )
+ {
+ m_xEventSource->RemoveEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
+ m_xEventSource->RemoveChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
+ m_xEventSource.clear();
+ }
+}
+
+VCLXAccessibleComponent::~VCLXAccessibleComponent()
+{
+ ensureDisposed();
+ DisconnectEvents();
+}
+
+OUString VCLXAccessibleComponent::getImplementationName()
+{
+ return "com.sun.star.comp.toolkit.AccessibleWindow";
+}
+
+sal_Bool VCLXAccessibleComponent::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence< OUString > VCLXAccessibleComponent::getSupportedServiceNames()
+{
+ uno::Sequence< OUString > aNames { "com.sun.star.awt.AccessibleWindow" };
+ return aNames;
+}
+
+IMPL_LINK( VCLXAccessibleComponent, WindowEventListener, VclWindowEvent&, rEvent, void )
+{
+ /* Ignore VclEventId::WindowEndPopupMode, because the UNO accessibility wrapper
+ * might have been destroyed by the previous VCLEventListener (if no AT tool
+ * is running), e.g. sub-toolbars in impress.
+ */
+ if ( m_xVCLXWindow.is() /* #122218# */ && (rEvent.GetId() != VclEventId::WindowEndPopupMode) )
+ {
+ DBG_ASSERT( rEvent.GetWindow(), "Window???" );
+ if( !rEvent.GetWindow()->IsAccessibilityEventsSuppressed() || ( rEvent.GetId() == VclEventId::ObjectDying ) )
+ {
+ ProcessWindowEvent( rEvent );
+ }
+ }
+}
+
+IMPL_LINK( VCLXAccessibleComponent, WindowChildEventListener, VclWindowEvent&, rEvent, void )
+{
+ if ( m_xVCLXWindow.is() /* #i68079# */ )
+ {
+ DBG_ASSERT( rEvent.GetWindow(), "Window???" );
+ if( !rEvent.GetWindow()->IsAccessibilityEventsSuppressed() )
+ {
+ // #103087# to prevent an early release of the component
+ uno::Reference< accessibility::XAccessibleContext > xHoldAlive = this;
+
+ ProcessWindowChildEvent( rEvent );
+ }
+ }
+}
+
+uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::GetChildAccessible( const VclWindowEvent& rVclWindowEvent )
+{
+ // checks if the data in the window event is our direct child
+ // and returns its accessible
+
+ // MT: Change this later, normally a show/hide event shouldn't have the vcl::Window* in pData.
+ vcl::Window* pChildWindow = static_cast<vcl::Window *>(rVclWindowEvent.GetData());
+ // tdf#141101/tdf#156561 Handle the event if this is either the a11y parent or the
+ // vcl::Window parent, since child events are sent for the vcl::Window hierarchy
+ // (s. Window::CallEventListeners) and e.g. DockingManager does manual partial reparenting
+ // that would cause child events to not be forwarded to the a11y level when
+ // not taking GetParent() into account here
+ if (pChildWindow && (GetWindow() == pChildWindow->GetAccessibleParentWindow()
+ || GetWindow() == pChildWindow->GetParent()))
+ return pChildWindow->GetAccessible( rVclWindowEvent.GetId() == VclEventId::WindowShow );
+ else
+ return uno::Reference< accessibility::XAccessible > ();
+}
+
+void VCLXAccessibleComponent::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ uno::Any aOldValue, aNewValue;
+ uno::Reference< accessibility::XAccessible > xAcc;
+
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::WindowShow: // send create on show for direct accessible children
+ {
+ xAcc = GetChildAccessible( rVclWindowEvent );
+ if( xAcc.is() )
+ {
+ aNewValue <<= xAcc;
+ NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
+
+ // CHILD event above results in a11y event listeners getting registered,
+ // so send state change event for SHOWING event after that
+ uno::Reference<XAccessibleContext> xChildContext = xAcc->getAccessibleContext();
+ if (xChildContext.is())
+ {
+ VCLXAccessibleComponent* pChildComponent = dynamic_cast<VCLXAccessibleComponent*>(xChildContext.get());
+ if (pChildComponent)
+ {
+ css::uno::Any aNewStateValue;
+ aNewStateValue <<= accessibility::AccessibleStateType::SHOWING;
+ pChildComponent->NotifyAccessibleEvent(accessibility::AccessibleEventId::STATE_CHANGED, css::uno::Any(), aNewStateValue);
+ }
+ }
+ }
+ }
+ break;
+ case VclEventId::WindowHide: // send destroy on hide for direct accessible children
+ {
+ xAcc = GetChildAccessible( rVclWindowEvent );
+ if( xAcc.is() )
+ {
+ // send state change event for SHOWING before sending the CHILD event below,
+ // since that one results in a11y event listeners getting removed
+ uno::Reference<XAccessibleContext> xChildContext = xAcc->getAccessibleContext();
+ if (xChildContext.is())
+ {
+ VCLXAccessibleComponent* pChildComponent = dynamic_cast<VCLXAccessibleComponent*>(xChildContext.get());
+ if (pChildComponent)
+ {
+ css::uno::Any aOldStateValue;
+ aOldStateValue <<= accessibility::AccessibleStateType::SHOWING;
+ pChildComponent->NotifyAccessibleEvent(accessibility::AccessibleEventId::STATE_CHANGED, aOldStateValue, css::uno::Any());
+ }
+ }
+
+ aOldValue <<= xAcc;
+ NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
+ }
+ }
+ break;
+ default: break;
+ }
+}
+
+void VCLXAccessibleComponent::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ uno::Any aOldValue, aNewValue;
+
+ vcl::Window* pAccWindow = rVclWindowEvent.GetWindow();
+ assert(pAccWindow && "VCLXAccessibleComponent::ProcessWindowEvent - Window?");
+
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::ObjectDying:
+ {
+ DisconnectEvents();
+ m_xVCLXWindow.clear();
+ }
+ break;
+ case VclEventId::WindowChildDestroyed:
+ {
+ vcl::Window* pWindow = static_cast<vcl::Window*>(rVclWindowEvent.GetData());
+ DBG_ASSERT( pWindow, "VclEventId::WindowChildDestroyed - Window=?" );
+ if ( pWindow->GetAccessible( false ).is() )
+ {
+ aOldValue <<= pWindow->GetAccessible( false );
+ NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
+ }
+ }
+ break;
+ case VclEventId::WindowActivate:
+ {
+ sal_Int16 aAccessibleRole = getAccessibleRole();
+ // avoid notification if a child frame is already active
+ // only one frame may be active at a given time
+ if ( !pAccWindow->HasActiveChildFrame() &&
+ ( aAccessibleRole == accessibility::AccessibleRole::FRAME ||
+ aAccessibleRole == accessibility::AccessibleRole::ALERT ||
+ aAccessibleRole == accessibility::AccessibleRole::DIALOG ) ) // #i18891#
+ {
+ aNewValue <<= accessibility::AccessibleStateType::ACTIVE;
+ NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+ }
+ break;
+ case VclEventId::WindowDeactivate:
+ {
+ sal_Int16 aAccessibleRole = getAccessibleRole();
+ if ( aAccessibleRole == accessibility::AccessibleRole::FRAME ||
+ aAccessibleRole == accessibility::AccessibleRole::ALERT ||
+ aAccessibleRole == accessibility::AccessibleRole::DIALOG ) // #i18891#
+ {
+ aOldValue <<= accessibility::AccessibleStateType::ACTIVE;
+ NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+ }
+ break;
+ case VclEventId::WindowGetFocus:
+ case VclEventId::ControlGetFocus:
+ {
+ if( (pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VclEventId::ControlGetFocus) ||
+ (!pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VclEventId::WindowGetFocus) )
+ {
+ // if multiple listeners were registered it is possible that the
+ // focus was changed during event processing (eg SfxTopWindow )
+ // #106082# allow ChildPathFocus only for CompoundControls, for windows the focus must be in the window itself
+ if( (pAccWindow->IsCompoundControl() && pAccWindow->HasChildPathFocus()) ||
+ (!pAccWindow->IsCompoundControl() && pAccWindow->HasFocus()) )
+ {
+ aNewValue <<= accessibility::AccessibleStateType::FOCUSED;
+ NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+ }
+ }
+ break;
+ case VclEventId::WindowLoseFocus:
+ case VclEventId::ControlLoseFocus:
+ {
+ if( (pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VclEventId::ControlLoseFocus) ||
+ (!pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VclEventId::WindowLoseFocus) )
+ {
+ aOldValue <<= accessibility::AccessibleStateType::FOCUSED;
+ NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+ }
+ break;
+ case VclEventId::WindowFrameTitleChanged:
+ {
+ OUString aOldName( *static_cast<OUString*>(rVclWindowEvent.GetData()) );
+ OUString aNewName( getAccessibleName() );
+ aOldValue <<= aOldName;
+ aNewValue <<= aNewName;
+ NotifyAccessibleEvent( accessibility::AccessibleEventId::NAME_CHANGED, aOldValue, aNewValue );
+ }
+ break;
+ case VclEventId::WindowEnabled:
+ {
+ aNewValue <<= accessibility::AccessibleStateType::ENABLED;
+ NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ aNewValue <<= accessibility::AccessibleStateType::SENSITIVE;
+ NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+ break;
+ case VclEventId::WindowDisabled:
+ {
+ aOldValue <<= accessibility::AccessibleStateType::SENSITIVE;
+ NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+
+ aOldValue <<= accessibility::AccessibleStateType::ENABLED;
+ NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+ break;
+ case VclEventId::WindowMove:
+ case VclEventId::WindowResize:
+ {
+ NotifyAccessibleEvent( accessibility::AccessibleEventId::BOUNDRECT_CHANGED, aOldValue, aNewValue );
+ }
+ break;
+ case VclEventId::WindowMenubarAdded:
+ {
+ MenuBar* pMenuBar = static_cast<MenuBar*>(rVclWindowEvent.GetData());
+ if ( pMenuBar )
+ {
+ uno::Reference< accessibility::XAccessible > xChild( pMenuBar->GetAccessible() );
+ if ( xChild.is() )
+ {
+ aNewValue <<= xChild;
+ NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
+ }
+ }
+ }
+ break;
+ case VclEventId::WindowMenubarRemoved:
+ {
+ MenuBar* pMenuBar = static_cast<MenuBar*>(rVclWindowEvent.GetData());
+ if ( pMenuBar )
+ {
+ uno::Reference< accessibility::XAccessible > xChild( pMenuBar->GetAccessible() );
+ if ( xChild.is() )
+ {
+ aOldValue <<= xChild;
+ NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
+ }
+ }
+ }
+ break;
+ case VclEventId::WindowMinimize:
+ {
+ aNewValue <<= accessibility::AccessibleStateType::ICONIFIED;
+ NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+ break;
+ case VclEventId::WindowNormalize:
+ {
+ aOldValue <<= accessibility::AccessibleStateType::ICONIFIED;
+ NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
+ }
+ break;
+ case VclEventId::WindowHide:
+ case VclEventId::WindowShow:
+ // WindowHide and WindowShow are handled in ProcessWindowChildEvent so the right order
+ // regarding the CHILD event can be taken into account
+ default:
+ {
+ }
+ break;
+ }
+}
+
+void VCLXAccessibleComponent::disposing()
+{
+ DisconnectEvents();
+
+ OAccessibleExtendedComponentHelper::disposing();
+
+ m_xVCLXWindow.clear();
+}
+
+vcl::Window* VCLXAccessibleComponent::GetWindow() const
+{
+ return GetVCLXWindow() ? GetVCLXWindow()->GetWindow()
+ : nullptr;
+}
+
+void VCLXAccessibleComponent::FillAccessibleRelationSet( utl::AccessibleRelationSetHelper& rRelationSet )
+{
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( !pWindow )
+ return;
+
+ vcl::Window *pLabeledBy = pWindow->GetAccessibleRelationLabeledBy();
+ if ( pLabeledBy && pLabeledBy != pWindow )
+ {
+ uno::Sequence< uno::Reference< uno::XInterface > > aSequence { pLabeledBy->GetAccessible() };
+ rRelationSet.AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::LABELED_BY, aSequence ) );
+ }
+
+ vcl::Window* pLabelFor = pWindow->GetAccessibleRelationLabelFor();
+ if ( pLabelFor && pLabelFor != pWindow )
+ {
+ uno::Sequence< uno::Reference< uno::XInterface > > aSequence { pLabelFor->GetAccessible() };
+ rRelationSet.AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::LABEL_FOR, aSequence ) );
+ }
+
+ vcl::Window* pMemberOf = pWindow->GetAccessibleRelationMemberOf();
+ if ( pMemberOf && pMemberOf != pWindow )
+ {
+ uno::Sequence< uno::Reference< uno::XInterface > > aSequence { pMemberOf->GetAccessible() };
+ rRelationSet.AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::MEMBER_OF, aSequence ) );
+ }
+}
+
+void VCLXAccessibleComponent::FillAccessibleStateSet( sal_Int64& rStateSet )
+{
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ if ( pWindow->IsVisible() )
+ {
+ rStateSet |= accessibility::AccessibleStateType::VISIBLE;
+ rStateSet |= accessibility::AccessibleStateType::SHOWING;
+ }
+ else
+ {
+ rStateSet |= accessibility::AccessibleStateType::INVALID;
+ }
+
+ if ( pWindow->IsEnabled() )
+ {
+ rStateSet |= accessibility::AccessibleStateType::ENABLED;
+ rStateSet |= accessibility::AccessibleStateType::SENSITIVE;
+ }
+
+ if ( pWindow->HasChildPathFocus() &&
+ ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||
+ getAccessibleRole() == accessibility::AccessibleRole::ALERT ||
+ getAccessibleRole() == accessibility::AccessibleRole::DIALOG ) ) // #i18891#
+ rStateSet |= accessibility::AccessibleStateType::ACTIVE;
+
+ if ( pWindow->HasFocus() || ( pWindow->IsCompoundControl() && pWindow->HasChildPathFocus() ) )
+ rStateSet |= accessibility::AccessibleStateType::FOCUSED;
+
+ if ( pWindow->IsWait() )
+ rStateSet |= accessibility::AccessibleStateType::BUSY;
+
+ if ( pWindow->GetStyle() & WB_SIZEABLE )
+ rStateSet |= accessibility::AccessibleStateType::RESIZABLE;
+ // 6. frame doesn't have MOVABLE state
+ // 10. for password text, where is the sensitive state?
+ if( ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||getAccessibleRole() == accessibility::AccessibleRole::DIALOG )&& pWindow->GetStyle() & WB_MOVEABLE )
+ rStateSet |= accessibility::AccessibleStateType::MOVEABLE;
+ if( pWindow->IsDialog() )
+ {
+ Dialog *pDlg = static_cast< Dialog* >( pWindow.get() );
+ if( pDlg->IsInExecute() )
+ rStateSet |= accessibility::AccessibleStateType::MODAL;
+ }
+ //If a combobox or list's edit child isn't read-only,EDITABLE state
+ //should be set.
+ if( pWindow && pWindow->GetType() == WindowType::COMBOBOX )
+ {
+ if( !( pWindow->GetStyle() & WB_READONLY) ||
+ !static_cast<Edit*>(pWindow.get())->IsReadOnly() )
+ rStateSet |= accessibility::AccessibleStateType::EDITABLE;
+ }
+
+ VclPtr<vcl::Window> pChild = pWindow->GetWindow( GetWindowType::FirstChild );
+
+ while( pWindow && pChild )
+ {
+ VclPtr<vcl::Window> pWinTemp = pChild->GetWindow( GetWindowType::FirstChild );
+ if( pWinTemp && pWinTemp->GetType() == WindowType::EDIT )
+ {
+ if( !( pWinTemp->GetStyle() & WB_READONLY) ||
+ !static_cast<Edit*>(pWinTemp.get())->IsReadOnly() )
+ rStateSet |= accessibility::AccessibleStateType::EDITABLE;
+ break;
+ }
+ if( pChild->GetType() == WindowType::EDIT )
+ {
+ if( !( pChild->GetStyle() & WB_READONLY) ||
+ !static_cast<Edit*>(pChild.get())->IsReadOnly())
+ rStateSet |= accessibility::AccessibleStateType::EDITABLE;
+ break;
+ }
+ pChild = pChild->GetWindow( GetWindowType::Next );
+ }
+ }
+ else
+ {
+ rStateSet |= accessibility::AccessibleStateType::DEFUNC;
+ }
+
+/*
+
+MUST BE SET FROM DERIVED CLASSES:
+
+CHECKABLE
+CHECKED
+COLLAPSED
+EXPANDED
+EXPANDABLE
+EDITABLE
+FOCUSABLE
+HORIZONTAL
+VERTICAL
+ICONIFIED
+MULTILINE
+MULTI_SELECTABLE
+PRESSED
+SELECTABLE
+SELECTED
+SINGLE_LINE
+TRANSIENT
+
+ */
+}
+
+
+// accessibility::XAccessibleContext
+sal_Int64 VCLXAccessibleComponent::getAccessibleChildCount()
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int64 nChildren = 0;
+ if ( GetWindow() )
+ nChildren = GetWindow()->GetAccessibleChildWindowCount();
+
+ return nChildren;
+}
+
+uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleChild( sal_Int64 i )
+{
+ OExternalLockGuard aGuard( this );
+
+ if ( i >= getAccessibleChildCount() )
+ throw lang::IndexOutOfBoundsException();
+
+ uno::Reference< accessibility::XAccessible > xAcc;
+ if ( GetWindow() )
+ {
+ vcl::Window* pChild = GetWindow()->GetAccessibleChildWindow( static_cast<sal_uInt16>(i) );
+ if ( pChild )
+ xAcc = pChild->GetAccessible();
+ }
+
+ return xAcc;
+}
+
+uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleParent( )
+{
+ OExternalLockGuard aGuard( this );
+
+ uno::Reference< accessibility::XAccessible > xAcc;
+ if ( GetWindow() )
+ {
+ vcl::Window* pParent = GetWindow()->GetAccessibleParentWindow();
+ if ( pParent )
+ xAcc = pParent->GetAccessible();
+ }
+ return xAcc;
+}
+
+sal_Int64 VCLXAccessibleComponent::getAccessibleIndexInParent( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int64 nIndex = -1;
+
+ if ( GetWindow() )
+ {
+ vcl::Window* pParent = GetWindow()->GetAccessibleParentWindow();
+ if ( pParent )
+ {
+ // Iterate over all the parent's children and search for this object.
+ // this should be compatible with the code in SVX
+ uno::Reference< accessibility::XAccessible > xParentAcc( pParent->GetAccessible() );
+ if ( xParentAcc.is() )
+ {
+ uno::Reference< accessibility::XAccessibleContext > xParentContext ( xParentAcc->getAccessibleContext() );
+ if ( xParentContext.is() )
+ {
+ sal_Int64 nChildCount = xParentContext->getAccessibleChildCount();
+ for ( sal_Int64 i = 0; i < nChildCount; i++ )
+ {
+ uno::Reference< accessibility::XAccessible > xChild( xParentContext->getAccessibleChild(i) );
+ if ( xChild.is() )
+ {
+ uno::Reference< accessibility::XAccessibleContext > xChildContext = xChild->getAccessibleContext();
+ if ( xChildContext == static_cast<accessibility::XAccessibleContext*>(this) )
+ {
+ nIndex = i;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return nIndex;
+}
+
+sal_Int16 VCLXAccessibleComponent::getAccessibleRole( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int16 nRole = 0;
+
+ if ( GetWindow() )
+ nRole = GetWindow()->GetAccessibleRole();
+
+ return nRole;
+}
+
+OUString VCLXAccessibleComponent::getAccessibleDescription( )
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString aDescription;
+
+ if ( GetWindow() )
+ aDescription = GetWindow()->GetAccessibleDescription();
+
+ return aDescription;
+}
+
+OUString VCLXAccessibleComponent::getAccessibleName( )
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString aName;
+ if ( GetWindow() )
+ {
+ aName = GetWindow()->GetAccessibleName();
+#if OSL_DEBUG_LEVEL > 0
+ // append window type to accessible name for debugging purposes
+ // if LIBO_APPEND_WINDOW_TYPE_TO_ACCESSIBLE_NAME environment variable is set
+ static const char* pEnvAppendType = getenv("LIBO_APPEND_WINDOW_TYPE_TO_ACCESSIBLE_NAME");
+ if (pEnvAppendType && OUString::createFromAscii(pEnvAppendType) != u"0")
+ aName += " (Type = " + OUString::number(static_cast<sal_Int32>(GetWindow()->GetType())) + ")";
+#endif
+ }
+ return aName;
+}
+
+OUString VCLXAccessibleComponent::getAccessibleId( )
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString aId;
+ if ( GetWindow() )
+ {
+ const OUString &aWindowId = GetWindow()->get_id();
+ aId = aWindowId;
+ }
+ return aId;
+}
+
+uno::Reference< accessibility::XAccessibleRelationSet > VCLXAccessibleComponent::getAccessibleRelationSet( )
+{
+ OExternalLockGuard aGuard( this );
+
+ rtl::Reference<utl::AccessibleRelationSetHelper> pRelationSetHelper = new utl::AccessibleRelationSetHelper;
+ FillAccessibleRelationSet( *pRelationSetHelper );
+ return pRelationSetHelper;
+}
+
+sal_Int64 VCLXAccessibleComponent::getAccessibleStateSet( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int64 nStateSet = 0;
+ FillAccessibleStateSet( nStateSet );
+ return nStateSet;
+}
+
+lang::Locale VCLXAccessibleComponent::getLocale()
+{
+ OExternalLockGuard aGuard( this );
+
+ return Application::GetSettings().GetLanguageTag().getLocale();
+}
+
+uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleAtPoint( const awt::Point& rPoint )
+{
+ OExternalLockGuard aGuard( this );
+
+ uno::Reference< accessibility::XAccessible > xChild;
+ for ( sal_Int64 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
+ {
+ uno::Reference< accessibility::XAccessible > xAcc = getAccessibleChild( i );
+ if ( xAcc.is() )
+ {
+ uno::Reference< accessibility::XAccessibleComponent > xComp( xAcc->getAccessibleContext(), uno::UNO_QUERY );
+ if ( xComp.is() )
+ {
+ tools::Rectangle aRect = VCLRectangle( xComp->getBounds() );
+ Point aPos = VCLPoint( rPoint );
+ if ( aRect.Contains( aPos ) )
+ {
+ xChild = xAcc;
+ break;
+ }
+ }
+ }
+ }
+
+ return xChild;
+}
+
+// accessibility::XAccessibleComponent
+awt::Rectangle VCLXAccessibleComponent::implGetBounds()
+{
+ awt::Rectangle aBounds ( 0, 0, 0, 0 );
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ AbsoluteScreenPixelRectangle aRect = pWindow->GetWindowExtentsAbsolute();
+ aBounds = AWTRectangle( aRect );
+ vcl::Window* pParent = pWindow->GetAccessibleParentWindow();
+ if ( pParent )
+ {
+ AbsoluteScreenPixelRectangle aParentRect = pParent->GetWindowExtentsAbsolute();
+ awt::Point aParentScreenLoc = AWTPoint( aParentRect.TopLeft() );
+ aBounds.X -= aParentScreenLoc.X;
+ aBounds.Y -= aParentScreenLoc.Y;
+ }
+ }
+
+ return aBounds;
+}
+
+awt::Point VCLXAccessibleComponent::getLocationOnScreen( )
+{
+ OExternalLockGuard aGuard( this );
+
+ awt::Point aPos;
+ if ( GetWindow() )
+ {
+ AbsoluteScreenPixelRectangle aRect = GetWindow()->GetWindowExtentsAbsolute();
+ aPos.X = aRect.Left();
+ aPos.Y = aRect.Top();
+ }
+
+ return aPos;
+}
+
+void VCLXAccessibleComponent::grabFocus( )
+{
+ OExternalLockGuard aGuard( this );
+
+ sal_Int64 nStates = getAccessibleStateSet();
+ if ( m_xVCLXWindow.is() && ( nStates & accessibility::AccessibleStateType::FOCUSABLE ) )
+ m_xVCLXWindow->setFocus();
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleComponent::getForeground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Color nColor;
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ 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();
+ // COL_AUTO is not very meaningful for AT
+ if ( nColor == COL_AUTO)
+ nColor = pWindow->GetTextColor();
+ }
+ }
+
+ return sal_Int32(nColor);
+}
+
+sal_Int32 SAL_CALL VCLXAccessibleComponent::getBackground( )
+{
+ OExternalLockGuard aGuard( this );
+
+ Color nColor;
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ if ( pWindow->IsControlBackground() )
+ nColor = pWindow->GetControlBackground();
+ else
+ nColor = pWindow->GetBackground().GetColor();
+ }
+
+ return sal_Int32(nColor);
+}
+
+// XAccessibleExtendedComponent
+
+uno::Reference< awt::XFont > SAL_CALL VCLXAccessibleComponent::getFont( )
+{
+ OExternalLockGuard aGuard( this );
+
+ uno::Reference< awt::XFont > xFont;
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ uno::Reference< awt::XDevice > xDev( pWindow->GetComponentInterface(), uno::UNO_QUERY );
+ if ( xDev.is() )
+ {
+ vcl::Font aFont;
+ if ( pWindow->IsControlFont() )
+ aFont = pWindow->GetControlFont();
+ else
+ aFont = pWindow->GetFont();
+ rtl::Reference<VCLXFont> pVCLXFont = new VCLXFont;
+ pVCLXFont->Init( *xDev, aFont );
+ xFont = pVCLXFont;
+ }
+ }
+
+ return xFont;
+}
+
+OUString SAL_CALL VCLXAccessibleComponent::getTitledBorderText( )
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sRet;
+ if ( GetWindow() )
+ sRet = GetWindow()->GetText();
+
+ return sRet;
+}
+
+OUString SAL_CALL VCLXAccessibleComponent::getToolTipText( )
+{
+ OExternalLockGuard aGuard( this );
+
+ OUString sRet;
+ if ( GetWindow() )
+ sRet = GetWindow()->GetQuickHelpText();
+
+ return sRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/awt/vclxbitmap.cxx b/toolkit/source/awt/vclxbitmap.cxx
new file mode 100644
index 0000000000..1faedb6235
--- /dev/null
+++ b/toolkit/source/awt/vclxbitmap.cxx
@@ -0,0 +1,60 @@
+/* -*- 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/vclxbitmap.hxx>
+#include <tools/stream.hxx>
+#include <vcl/dibtools.hxx>
+#include <vcl/BitmapTools.hxx>
+
+
+
+
+// css::awt::XBitmap
+css::awt::Size VCLXBitmap::getSize()
+{
+ std::scoped_lock aGuard( GetMutex() );
+
+ css::awt::Size aSize( maBitmap.GetSizePixel().Width(), maBitmap.GetSizePixel().Height() );
+ return aSize;
+}
+
+css::uno::Sequence< sal_Int8 > VCLXBitmap::getDIB()
+{
+ std::scoped_lock aGuard( GetMutex() );
+
+ SvMemoryStream aMem;
+ WriteDIB(maBitmap.GetBitmap(), aMem, false, true);
+ return css::uno::Sequence<sal_Int8>( static_cast<sal_Int8 const *>(aMem.GetData()), aMem.Tell() );
+}
+
+css::uno::Sequence< sal_Int8 > VCLXBitmap::getMaskDIB()
+{
+ std::scoped_lock aGuard( GetMutex() );
+
+ return vcl::bitmap::GetMaskDIB(maBitmap);
+}
+
+sal_Int64 SAL_CALL VCLXBitmap::estimateUsage()
+{
+ std::scoped_lock aGuard( GetMutex() );
+
+ return maBitmap.GetSizeBytes();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/awt/vclxcontainer.cxx b/toolkit/source/awt/vclxcontainer.cxx
new file mode 100644
index 0000000000..de7518d418
--- /dev/null
+++ b/toolkit/source/awt/vclxcontainer.cxx
@@ -0,0 +1,264 @@
+/* -*- 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/vclxcontainer.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <toolkit/helper/listenermultiplexer.hxx>
+
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <vcl/tabpage.hxx>
+#include <tools/debug.hxx>
+#include <helper/scrollabledialog.hxx>
+#include <helper/property.hxx>
+
+void VCLXContainer::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ VCLXWindow::ImplGetPropertyIds( rIds );
+}
+
+VCLXContainer::VCLXContainer()
+{
+}
+
+VCLXContainer::~VCLXContainer()
+{
+}
+
+
+// css::awt::XVclContainer
+void VCLXContainer::addVclContainerListener( const css::uno::Reference< css::awt::XVclContainerListener >& rxListener )
+{
+ SolarMutexGuard aGuard;
+
+ if (!IsDisposed())
+ GetContainerListeners().addInterface( rxListener );
+}
+
+void VCLXContainer::removeVclContainerListener( const css::uno::Reference< css::awt::XVclContainerListener >& rxListener )
+{
+ SolarMutexGuard aGuard;
+
+ if (!IsDisposed())
+ GetContainerListeners().removeInterface( rxListener );
+}
+
+css::uno::Sequence< css::uno::Reference< css::awt::XWindow > > VCLXContainer::getWindows( )
+{
+ SolarMutexGuard aGuard;
+
+ // Request container interface from all children
+ css::uno::Sequence< css::uno::Reference< css::awt::XWindow > > aSeq;
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ sal_uInt16 nChildren = pWindow->GetChildCount();
+ if ( nChildren )
+ {
+ aSeq = css::uno::Sequence< css::uno::Reference< css::awt::XWindow > >( nChildren );
+ css::uno::Reference< css::awt::XWindow > * pChildRefs = aSeq.getArray();
+ for ( sal_uInt16 n = 0; n < nChildren; n++ )
+ {
+ vcl::Window* pChild = pWindow->GetChild( n );
+ css::uno::Reference< css::awt::XWindowPeer > xWP = pChild->GetComponentInterface();
+ css::uno::Reference< css::awt::XWindow > xW( xWP, css::uno::UNO_QUERY );
+ pChildRefs[n] = xW;
+ }
+ }
+ }
+ return aSeq;
+}
+
+
+// css::awt::XVclContainerPeer
+void VCLXContainer::enableDialogControl( sal_Bool bEnable )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ WinBits nStyle = pWindow->GetStyle();
+ if ( bEnable )
+ nStyle |= WB_DIALOGCONTROL;
+ else
+ nStyle &= (~WB_DIALOGCONTROL);
+ pWindow->SetStyle( nStyle );
+ }
+}
+
+void VCLXContainer::setTabOrder( const css::uno::Sequence< css::uno::Reference< css::awt::XWindow > >& Components, const css::uno::Sequence< css::uno::Any >& Tabs, sal_Bool bGroupControl )
+{
+ SolarMutexGuard aGuard;
+
+ sal_uInt32 nCount = Components.getLength();
+ DBG_ASSERT( nCount == static_cast<sal_uInt32>(Tabs.getLength()), "setTabOrder: TabCount != ComponentCount" );
+ const css::uno::Reference< css::awt::XWindow > * pComps = Components.getConstArray();
+ const css::uno::Any* pTabs = Tabs.getConstArray();
+
+ vcl::Window* pPrevWin = nullptr;
+ for ( sal_uInt32 n = 0; n < nCount; n++ )
+ {
+ // css::style::TabStop
+ VclPtr<vcl::Window> pWin = VCLUnoHelper::GetWindow( pComps[n] );
+ // May be NULL if a css::uno::Sequence is originated from TabController and is missing a peer!
+ if ( pWin )
+ {
+ // Order windows before manipulating their style, because elements such as the
+ // RadioButton considers the PREV-window in StateChanged.
+ if ( pPrevWin )
+ pWin->SetZOrder( pPrevWin, ZOrderFlags::Behind );
+
+ WinBits nStyle = pWin->GetStyle();
+ nStyle &= ~(WB_TABSTOP|WB_NOTABSTOP|WB_GROUP);
+ if ( pTabs[n].getValueType().getTypeClass() == css::uno::TypeClass_BOOLEAN )
+ {
+ bool bTab = false;
+ pTabs[n] >>= bTab;
+ nStyle |= ( bTab ? WB_TABSTOP : WB_NOTABSTOP );
+ }
+ pWin->SetStyle( nStyle );
+
+ if ( bGroupControl )
+ {
+ if ( n == 0 )
+ pWin->SetDialogControlStart( true );
+ else
+ pWin->SetDialogControlStart( false );
+ }
+
+ pPrevWin = pWin;
+ }
+ }
+}
+
+void VCLXContainer::setGroup( const css::uno::Sequence< css::uno::Reference< css::awt::XWindow > >& Components )
+{
+ SolarMutexGuard aGuard;
+
+ sal_uInt32 nCount = Components.getLength();
+ const css::uno::Reference< css::awt::XWindow > * pComps = Components.getConstArray();
+
+ vcl::Window* pPrevWin = nullptr;
+ vcl::Window* pPrevRadio = nullptr;
+ for ( sal_uInt32 n = 0; n < nCount; n++ )
+ {
+ VclPtr<vcl::Window> pWin = VCLUnoHelper::GetWindow( pComps[n] );
+ if ( pWin )
+ {
+ vcl::Window* pSortBehind = pPrevWin;
+ // #57096# Sort all radios consecutively
+ bool bNewPrevWin = true;
+ if ( pWin->GetType() == WindowType::RADIOBUTTON )
+ {
+ if ( pPrevRadio )
+ {
+ // This RadioButton was sorted before PrevWin
+ bNewPrevWin = ( pPrevWin == pPrevRadio );
+ pSortBehind = pPrevRadio;
+ }
+ pPrevRadio = pWin;
+ }
+
+ // Z-Order
+ if ( pSortBehind )
+ pWin->SetZOrder( pSortBehind, ZOrderFlags::Behind );
+
+ WinBits nStyle = pWin->GetStyle();
+ if ( n == 0 )
+ nStyle |= WB_GROUP;
+ else
+ nStyle &= (~WB_GROUP);
+ pWin->SetStyle( nStyle );
+
+ // Add WB_GROUP after the last group
+ if ( n == ( nCount - 1 ) )
+ {
+ vcl::Window* pBehindLast = pWin->GetWindow( GetWindowType::Next );
+ if ( pBehindLast )
+ {
+ WinBits nLastStyle = pBehindLast->GetStyle();
+ nLastStyle |= WB_GROUP;
+ pBehindLast->SetStyle( nLastStyle );
+ }
+ }
+
+ if ( bNewPrevWin )
+ pPrevWin = pWin;
+ }
+ }
+}
+
+void SAL_CALL VCLXContainer::setProperty(
+ const OUString& PropertyName,
+ const css::uno::Any& Value )
+{
+ SolarMutexGuard aGuard;
+
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_SCROLLHEIGHT:
+ case BASEPROPERTY_SCROLLWIDTH:
+ case BASEPROPERTY_SCROLLTOP:
+ case BASEPROPERTY_SCROLLLEFT:
+ {
+ sal_Int32 nVal =0;
+ Value >>= nVal;
+ Size aSize( nVal, nVal );
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ MapMode aMode( MapUnit::MapAppFont );
+ toolkit::ScrollableDialog* pScrollable = dynamic_cast< toolkit::ScrollableDialog* >( pWindow.get() );
+ TabPage* pScrollTabPage = dynamic_cast< TabPage* >( pWindow.get() );
+ if ( pWindow && (pScrollable || pScrollTabPage) )
+ {
+ aSize = pWindow->LogicToPixel( aSize, aMode );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_SCROLLHEIGHT:
+ pScrollable ? pScrollable->SetScrollHeight( aSize.Height() ) : (void)0;
+ pScrollTabPage ? pScrollTabPage->SetScrollHeight( aSize.Height() ) : (void)0;
+ break;
+ case BASEPROPERTY_SCROLLWIDTH:
+ pScrollable ? pScrollable->SetScrollWidth( aSize.Width() ) : (void)0;
+ pScrollTabPage ? pScrollTabPage->SetScrollWidth( aSize.Width() ) : (void)0;
+ break;
+ case BASEPROPERTY_SCROLLTOP:
+ pScrollable ? pScrollable->SetScrollTop( aSize.Height() ) : (void)0;
+ pScrollTabPage ? pScrollTabPage->SetScrollTop( aSize.Height() ) : (void)0;
+ break;
+ case BASEPROPERTY_SCROLLLEFT:
+ pScrollable ? pScrollable->SetScrollLeft( aSize.Width() ) : (void)0;
+ pScrollTabPage ? pScrollTabPage->SetScrollLeft( aSize.Width() ) : (void)0;
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ break;
+ }
+
+ default:
+ {
+ VCLXWindow::setProperty( PropertyName, Value );
+ }
+ }
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/awt/vclxdevice.cxx b/toolkit/source/awt/vclxdevice.cxx
new file mode 100644
index 0000000000..c4ed981467
--- /dev/null
+++ b/toolkit/source/awt/vclxdevice.cxx
@@ -0,0 +1,251 @@
+/* -*- 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/util/MeasureUnit.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+
+#include <toolkit/awt/vclxdevice.hxx>
+#include <toolkit/awt/vclxfont.hxx>
+#include <awt/vclxbitmap.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+
+#include <vcl/svapp.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/metric.hxx>
+
+
+VCLXDevice::VCLXDevice()
+{
+}
+
+VCLXDevice::~VCLXDevice()
+{
+ //TODO: why was this empty, and everything done in ~VCLXVirtualDevice?
+ SolarMutexGuard g;
+ mpOutputDevice.reset();
+}
+
+// css::awt::XDevice,
+css::uno::Reference< css::awt::XGraphics > VCLXDevice::createGraphics( )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Reference< css::awt::XGraphics > xRef;
+
+ if ( mpOutputDevice )
+ xRef = mpOutputDevice->CreateUnoGraphics();
+
+ return xRef;
+}
+
+css::uno::Reference< css::awt::XDevice > VCLXDevice::createDevice( sal_Int32 nWidth, sal_Int32 nHeight )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Reference< css::awt::XDevice > xRef;
+ if ( GetOutputDevice() )
+ {
+ rtl::Reference<VCLXVirtualDevice> pVDev = new VCLXVirtualDevice;
+ VclPtrInstance<VirtualDevice> pVclVDev( *GetOutputDevice() );
+ pVclVDev->SetOutputSizePixel( Size( nWidth, nHeight ) );
+ pVDev->SetVirtualDevice( pVclVDev );
+ xRef = pVDev;
+ }
+ return xRef;
+}
+
+css::awt::DeviceInfo VCLXDevice::getInfo()
+{
+ SolarMutexGuard aGuard;
+
+ css::awt::DeviceInfo aInfo;
+
+ if (mpOutputDevice)
+ aInfo = mpOutputDevice->GetDeviceInfo();
+
+ return aInfo;
+}
+
+css::uno::Sequence< css::awt::FontDescriptor > VCLXDevice::getFontDescriptors( )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Sequence< css::awt::FontDescriptor> aFonts;
+ if( mpOutputDevice )
+ {
+ int nFonts = mpOutputDevice->GetFontFaceCollectionCount();
+ if ( nFonts )
+ {
+ aFonts = css::uno::Sequence< css::awt::FontDescriptor>( nFonts );
+ css::awt::FontDescriptor* pFonts = aFonts.getArray();
+ for ( int n = 0; n < nFonts; n++ )
+ pFonts[n] = VCLUnoHelper::CreateFontDescriptor( mpOutputDevice->GetFontMetricFromCollection( n ) );
+ }
+ }
+ return aFonts;
+}
+
+css::uno::Reference< css::awt::XFont > VCLXDevice::getFont( const css::awt::FontDescriptor& rDescriptor )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Reference< css::awt::XFont > xRef;
+ if( mpOutputDevice )
+ {
+ rtl::Reference<VCLXFont> pMetric = new VCLXFont;
+ pMetric->Init( *this, VCLUnoHelper::CreateFont( rDescriptor, mpOutputDevice->GetFont() ) );
+ xRef = pMetric;
+ }
+ return xRef;
+}
+
+css::uno::Reference< css::awt::XBitmap > VCLXDevice::createBitmap( sal_Int32 nX, sal_Int32 nY, sal_Int32 nWidth, sal_Int32 nHeight )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Reference< css::awt::XBitmap > xBmp;
+ if( mpOutputDevice )
+ {
+ BitmapEx aBmp = mpOutputDevice->GetBitmapEx( Point( nX, nY ), Size( nWidth, nHeight ) );
+
+ rtl::Reference<VCLXBitmap> pBmp = new VCLXBitmap;
+ pBmp->SetBitmap( aBmp );
+ xBmp = pBmp;
+ }
+ return xBmp;
+}
+
+css::uno::Reference< css::awt::XDisplayBitmap > VCLXDevice::createDisplayBitmap( const css::uno::Reference< css::awt::XBitmap >& rxBitmap )
+{
+ SolarMutexGuard aGuard;
+
+ BitmapEx aBmp = VCLUnoHelper::GetBitmap( rxBitmap );
+ rtl::Reference<VCLXBitmap> pBmp = new VCLXBitmap;
+ pBmp->SetBitmap( aBmp );
+ return pBmp;
+}
+
+VCLXVirtualDevice::~VCLXVirtualDevice()
+{
+ SolarMutexGuard aGuard;
+
+ mpOutputDevice.disposeAndClear();
+}
+
+// Interface implementation of css::awt::XUnitConversion
+
+css::awt::Point SAL_CALL VCLXDevice::convertPointToLogic( const css::awt::Point& aPoint, ::sal_Int16 TargetUnit )
+{
+ SolarMutexGuard aGuard;
+ if (TargetUnit == css::util::MeasureUnit::PERCENT )
+ {
+ // percentage not allowed here
+ throw css::lang::IllegalArgumentException();
+ }
+
+ css::awt::Point aAWTPoint(0,0);
+ // X,Y
+
+ if( mpOutputDevice )
+ {
+ MapMode aMode(VCLUnoHelper::ConvertToMapModeUnit(TargetUnit));
+ ::Point aVCLPoint = VCLUnoHelper::ConvertToVCLPoint(aPoint);
+ ::Point aDevPoint = mpOutputDevice->PixelToLogic(aVCLPoint, aMode );
+ aAWTPoint = VCLUnoHelper::ConvertToAWTPoint(aDevPoint);
+ }
+
+ return aAWTPoint;
+}
+
+
+css::awt::Point SAL_CALL VCLXDevice::convertPointToPixel( const css::awt::Point& aPoint, ::sal_Int16 SourceUnit )
+{
+ SolarMutexGuard aGuard;
+ if (SourceUnit == css::util::MeasureUnit::PERCENT ||
+ SourceUnit == css::util::MeasureUnit::PIXEL )
+ {
+ // pixel or percentage not allowed here
+ throw css::lang::IllegalArgumentException();
+ }
+
+ css::awt::Point aAWTPoint(0,0);
+
+ if( mpOutputDevice )
+ {
+ MapMode aMode(VCLUnoHelper::ConvertToMapModeUnit(SourceUnit));
+ ::Point aVCLPoint = VCLUnoHelper::ConvertToVCLPoint(aPoint);
+ ::Point aDevPoint = mpOutputDevice->LogicToPixel(aVCLPoint, aMode );
+ aAWTPoint = VCLUnoHelper::ConvertToAWTPoint(aDevPoint);
+ }
+
+ return aAWTPoint;
+}
+
+css::awt::Size SAL_CALL VCLXDevice::convertSizeToLogic( const css::awt::Size& aSize, ::sal_Int16 TargetUnit )
+{
+ SolarMutexGuard aGuard;
+ if (TargetUnit == css::util::MeasureUnit::PERCENT)
+ {
+ // percentage not allowed here
+ throw css::lang::IllegalArgumentException();
+ }
+
+ css::awt::Size aAWTSize(0,0);
+ // Width, Height
+
+
+ if( mpOutputDevice )
+ {
+ MapMode aMode(VCLUnoHelper::ConvertToMapModeUnit(TargetUnit));
+ ::Size aVCLSize = VCLUnoHelper::ConvertToVCLSize(aSize);
+ ::Size aDevSz = mpOutputDevice->PixelToLogic(aVCLSize, aMode );
+ aAWTSize = VCLUnoHelper::ConvertToAWTSize(aDevSz);
+ }
+
+ return aAWTSize;
+}
+
+css::awt::Size SAL_CALL VCLXDevice::convertSizeToPixel( const css::awt::Size& aSize, ::sal_Int16 SourceUnit )
+{
+ SolarMutexGuard aGuard;
+ if (SourceUnit == css::util::MeasureUnit::PERCENT ||
+ SourceUnit == css::util::MeasureUnit::PIXEL)
+ {
+ // pixel or percentage not allowed here
+ throw css::lang::IllegalArgumentException();
+ }
+
+ css::awt::Size aAWTSize(0,0);
+ // Width, Height
+ if( mpOutputDevice )
+ {
+ MapMode aMode(VCLUnoHelper::ConvertToMapModeUnit(SourceUnit));
+ ::Size aVCLSize = VCLUnoHelper::ConvertToVCLSize(aSize);
+ ::Size aDevSz = mpOutputDevice->LogicToPixel(aVCLSize, aMode );
+ aAWTSize = VCLUnoHelper::ConvertToAWTSize(aDevSz);
+ }
+
+ return aAWTSize;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/awt/vclxfont.cxx b/toolkit/source/awt/vclxfont.cxx
new file mode 100644
index 0000000000..01e7aaae79
--- /dev/null
+++ b/toolkit/source/awt/vclxfont.cxx
@@ -0,0 +1,189 @@
+/* -*- 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/awt/XDevice.hpp>
+
+#include <comphelper/sequence.hxx>
+#include <toolkit/awt/vclxfont.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+
+#include <vcl/kernarray.hxx>
+#include <vcl/metric.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/svapp.hxx>
+
+VCLXFont::VCLXFont()
+{
+ mpFontMetric = nullptr;
+}
+
+VCLXFont::~VCLXFont()
+{
+}
+
+void VCLXFont::Init( css::awt::XDevice& rxDev, const vcl::Font& rFont )
+{
+ mxDevice = &rxDev;
+
+ mpFontMetric.reset();
+
+ maFont = rFont;
+}
+
+bool VCLXFont::ImplAssertValidFontMetric()
+{
+ if ( !mpFontMetric && mxDevice.is() )
+ {
+ OutputDevice* pOutDev = VCLUnoHelper::GetOutputDevice( mxDevice );
+ if ( pOutDev )
+ {
+ vcl::Font aOldFont = pOutDev->GetFont();
+ pOutDev->SetFont( maFont );
+ mpFontMetric.reset( new FontMetric( pOutDev->GetFontMetric() ) );
+ pOutDev->SetFont( aOldFont );
+ }
+ }
+ return mpFontMetric != nullptr;
+}
+
+css::awt::FontDescriptor VCLXFont::getFontDescriptor( )
+{
+ std::unique_lock aGuard( maMutex );
+
+ return VCLUnoHelper::CreateFontDescriptor( maFont );
+
+}
+
+css::awt::SimpleFontMetric VCLXFont::getFontMetric( )
+{
+ std::unique_lock aGuard( maMutex );
+
+ css::awt::SimpleFontMetric aFM;
+ if ( ImplAssertValidFontMetric() )
+ aFM = VCLUnoHelper::CreateFontMetric( *mpFontMetric );
+ return aFM;
+}
+
+sal_Int16 VCLXFont::getCharWidth( sal_Unicode c )
+{
+ std::unique_lock aGuard( maMutex );
+
+ sal_Int16 nRet = -1;
+ OutputDevice* pOutDev = VCLUnoHelper::GetOutputDevice( mxDevice );
+ if ( pOutDev )
+ {
+ vcl::Font aOldFont = pOutDev->GetFont();
+ pOutDev->SetFont( maFont );
+
+ nRet = sal::static_int_cast< sal_Int16 >(
+ pOutDev->GetTextWidth( OUString(c) ));
+
+ pOutDev->SetFont( aOldFont );
+ }
+ return nRet;
+}
+
+css::uno::Sequence< sal_Int16 > VCLXFont::getCharWidths( sal_Unicode nFirst, sal_Unicode nLast )
+{
+ std::unique_lock aGuard( maMutex );
+
+ css::uno::Sequence<sal_Int16> aSeq;
+ OutputDevice* pOutDev = VCLUnoHelper::GetOutputDevice( mxDevice );
+ if ( pOutDev )
+ {
+ vcl::Font aOldFont = pOutDev->GetFont();
+ pOutDev->SetFont( maFont );
+
+ sal_Int16 nCount = nLast-nFirst + 1;
+ aSeq = css::uno::Sequence<sal_Int16>( nCount );
+ for ( sal_uInt16 n = 0; n < nCount; n++ )
+ {
+ aSeq.getArray()[n] = sal::static_int_cast< sal_Int16 >(
+ pOutDev->GetTextWidth(
+ OUString(static_cast< sal_Unicode >(nFirst+n)) ));
+ }
+
+ pOutDev->SetFont( aOldFont );
+ }
+ return aSeq;
+}
+
+sal_Int32 VCLXFont::getStringWidth( const OUString& str )
+{
+ std::unique_lock aGuard( maMutex );
+
+ sal_Int32 nRet = -1;
+ OutputDevice* pOutDev = VCLUnoHelper::GetOutputDevice( mxDevice );
+ if ( pOutDev )
+ {
+ vcl::Font aOldFont = pOutDev->GetFont();
+ pOutDev->SetFont( maFont );
+ nRet = pOutDev->GetTextWidth( str );
+ pOutDev->SetFont( aOldFont );
+ }
+ return nRet;
+}
+
+sal_Int32 VCLXFont::getStringWidthArray( const OUString& str, css::uno::Sequence< sal_Int32 >& rDXArray )
+{
+ std::unique_lock aGuard( maMutex );
+
+ sal_Int32 nRet = -1;
+ OutputDevice* pOutDev = VCLUnoHelper::GetOutputDevice( mxDevice );
+ if ( pOutDev )
+ {
+ vcl::Font aOldFont = pOutDev->GetFont();
+ pOutDev->SetFont( maFont );
+ KernArray aDXA;
+ nRet = pOutDev->GetTextArray( str, &aDXA );
+ rDXArray.realloc(aDXA.size());
+ sal_Int32* pArray = rDXArray.getArray();
+ for (size_t i = 0, nLen = aDXA.size(); i < nLen; ++i)
+ pArray[i] = aDXA[i];
+ pOutDev->SetFont( aOldFont );
+ }
+ return nRet;
+}
+
+void VCLXFont::getKernPairs( css::uno::Sequence< sal_Unicode >& /*rnChars1*/, css::uno::Sequence< sal_Unicode >& /*rnChars2*/, css::uno::Sequence< sal_Int16 >& /*rnKerns*/ )
+{
+ // NOTE: this empty method is just used for keeping the related UNO-API stable
+}
+
+// css::awt::XFont2
+sal_Bool VCLXFont::hasGlyphs( const OUString& aText )
+{
+ std::unique_lock aGuard( maMutex );
+ SolarMutexGuard aSolarGuard;
+
+ OutputDevice* pOutDev = VCLUnoHelper::GetOutputDevice( mxDevice );
+ if ( pOutDev )
+ {
+ if ( pOutDev->HasGlyphs( maFont, aText ) == -1 )
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/awt/vclxgraphics.cxx b/toolkit/source/awt/vclxgraphics.cxx
new file mode 100644
index 0000000000..06df80a421
--- /dev/null
+++ b/toolkit/source/awt/vclxgraphics.cxx
@@ -0,0 +1,487 @@
+/* -*- 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 <awt/vclxgraphics.hxx>
+#include <toolkit/awt/vclxdevice.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+
+#include <vcl/svapp.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/image.hxx>
+#include <vcl/kernarray.hxx>
+#include <vcl/gradient.hxx>
+#include <vcl/metric.hxx>
+#include <tools/debug.hxx>
+
+using namespace com::sun::star;
+
+
+
+VCLXGraphics::VCLXGraphics()
+ : mpOutputDevice(nullptr)
+ , meRasterOp(RasterOp::OverPaint)
+{
+}
+
+VCLXGraphics::~VCLXGraphics()
+{
+ std::vector< VCLXGraphics* > *pLst = mpOutputDevice ? mpOutputDevice->GetUnoGraphicsList() : nullptr;
+ if ( pLst )
+ {
+ auto it = std::find(pLst->begin(), pLst->end(), this);
+ if (it != pLst->end())
+ pLst->erase( it );
+ }
+
+ mpClipRegion.reset();
+
+ SolarMutexGuard g;
+ mpOutputDevice.reset();
+}
+
+void VCLXGraphics::SetOutputDevice( OutputDevice* pOutDev )
+{
+ mpOutputDevice = pOutDev;
+ mxDevice = nullptr;
+ initAttrs();
+}
+
+void VCLXGraphics::Init( OutputDevice* pOutDev )
+{
+ DBG_ASSERT( !mpOutputDevice, "VCLXGraphics::Init already has pOutDev !" );
+ mpOutputDevice = pOutDev;
+
+ initAttrs();
+ mpClipRegion = nullptr;
+
+ // Register at OutputDevice
+ std::vector< VCLXGraphics* > *pLst = mpOutputDevice->GetUnoGraphicsList();
+ if ( !pLst )
+ pLst = mpOutputDevice->CreateUnoGraphicsList();
+ pLst->push_back( this );
+}
+
+void VCLXGraphics::initAttrs()
+{
+ if ( !mpOutputDevice )
+ return;
+
+ maFont = mpOutputDevice->GetFont();
+ maTextColor = mpOutputDevice->GetTextColor(); /* COL_BLACK */
+ maTextFillColor = mpOutputDevice->GetTextFillColor(); /* COL_TRANSPARENT */
+ maLineColor = mpOutputDevice->GetLineColor(); /* COL_BLACK */
+ maFillColor = mpOutputDevice->GetFillColor(); /* COL_WHITE */
+ meRasterOp = mpOutputDevice->GetRasterOp(); /* RasterOp::OverPaint */
+}
+
+void VCLXGraphics::InitOutputDevice( InitOutDevFlags nFlags )
+{
+ if(!mpOutputDevice)
+ return;
+
+ SolarMutexGuard aVclGuard;
+
+ if ( nFlags & InitOutDevFlags::FONT )
+ {
+ mpOutputDevice->SetFont( maFont );
+ mpOutputDevice->SetTextColor( maTextColor );
+ mpOutputDevice->SetTextFillColor( maTextFillColor );
+ }
+
+ if ( nFlags & InitOutDevFlags::COLORS )
+ {
+ mpOutputDevice->SetLineColor( maLineColor );
+ mpOutputDevice->SetFillColor( maFillColor );
+ }
+
+ mpOutputDevice->SetRasterOp( meRasterOp );
+
+ if( mpClipRegion )
+ mpOutputDevice->SetClipRegion( *mpClipRegion );
+ else
+ mpOutputDevice->SetClipRegion();
+}
+
+uno::Reference< awt::XDevice > VCLXGraphics::getDevice()
+{
+ SolarMutexGuard aGuard;
+
+ if( !mxDevice.is() && mpOutputDevice )
+ {
+ rtl::Reference<VCLXDevice> pDev = new VCLXDevice;
+ pDev->SetOutputDevice( mpOutputDevice );
+ mxDevice = pDev;
+ }
+ return mxDevice;
+}
+
+awt::SimpleFontMetric VCLXGraphics::getFontMetric()
+{
+ SolarMutexGuard aGuard;
+
+ awt::SimpleFontMetric aM;
+ if( mpOutputDevice )
+ {
+ mpOutputDevice->SetFont( maFont );
+ aM = VCLUnoHelper::CreateFontMetric( mpOutputDevice->GetFontMetric() );
+ }
+ return aM;
+}
+
+void VCLXGraphics::setFont( const uno::Reference< awt::XFont >& rxFont )
+{
+ SolarMutexGuard aGuard;
+
+ maFont = VCLUnoHelper::CreateFont( rxFont );
+}
+
+void VCLXGraphics::selectFont( const awt::FontDescriptor& rDescription )
+{
+ SolarMutexGuard aGuard;
+
+ maFont = VCLUnoHelper::CreateFont( rDescription, vcl::Font() );
+}
+
+void VCLXGraphics::setTextColor( sal_Int32 nColor )
+{
+ SolarMutexGuard aGuard;
+
+ maTextColor = Color( ColorTransparency, nColor );
+}
+
+void VCLXGraphics::setTextFillColor( sal_Int32 nColor )
+{
+ SolarMutexGuard aGuard;
+
+ maTextFillColor = Color( ColorTransparency, nColor );
+}
+
+void VCLXGraphics::setLineColor( sal_Int32 nColor )
+{
+ SolarMutexGuard aGuard;
+
+ maLineColor = Color( ColorTransparency, nColor );
+}
+
+void VCLXGraphics::setFillColor( sal_Int32 nColor )
+{
+ SolarMutexGuard aGuard;
+
+ maFillColor = Color( ColorTransparency, nColor );
+}
+
+void VCLXGraphics::setRasterOp( awt::RasterOperation eROP )
+{
+ SolarMutexGuard aGuard;
+
+ meRasterOp = static_cast<RasterOp>(eROP);
+}
+
+void VCLXGraphics::setClipRegion( const uno::Reference< awt::XRegion >& rxRegion )
+{
+ SolarMutexGuard aGuard;
+
+ if ( rxRegion.is() )
+ mpClipRegion.reset( new vcl::Region( VCLUnoHelper::GetRegion( rxRegion ) ) );
+ else
+ mpClipRegion.reset();
+}
+
+void VCLXGraphics::intersectClipRegion( const uno::Reference< awt::XRegion >& rxRegion )
+{
+ SolarMutexGuard aGuard;
+
+ if ( rxRegion.is() )
+ {
+ vcl::Region aRegion( VCLUnoHelper::GetRegion( rxRegion ) );
+ if ( !mpClipRegion )
+ mpClipRegion.reset( new vcl::Region( aRegion ) );
+ else
+ mpClipRegion->Intersect( aRegion );
+ }
+}
+
+void VCLXGraphics::push( )
+{
+ SolarMutexGuard aGuard;
+
+
+ if( mpOutputDevice )
+ mpOutputDevice->Push();
+}
+
+void VCLXGraphics::pop( )
+{
+ SolarMutexGuard aGuard;
+
+
+ if( mpOutputDevice )
+ mpOutputDevice->Pop();
+}
+
+void VCLXGraphics::clear(
+ const awt::Rectangle& aRect )
+{
+ SolarMutexGuard aGuard;
+
+ if( mpOutputDevice )
+ {
+ const ::tools::Rectangle aVCLRect = VCLUnoHelper::ConvertToVCLRect( aRect );
+ mpOutputDevice->Erase( aVCLRect );
+ }
+}
+
+void VCLXGraphics::copy( const uno::Reference< awt::XDevice >& rxSource, sal_Int32 nSourceX, sal_Int32 nSourceY, sal_Int32 nSourceWidth, sal_Int32 nSourceHeight, sal_Int32 nDestX, sal_Int32 nDestY, sal_Int32 nDestWidth, sal_Int32 nDestHeight )
+{
+ SolarMutexGuard aGuard;
+
+ if ( mpOutputDevice )
+ {
+ VCLXDevice* pFromDev = dynamic_cast<VCLXDevice*>( rxSource.get() );
+ DBG_ASSERT( pFromDev, "VCLXGraphics::copy - invalid device" );
+ if ( pFromDev )
+ {
+ InitOutputDevice( InitOutDevFlags::NONE );
+ mpOutputDevice->DrawOutDev( Point( nDestX, nDestY ), Size( nDestWidth, nDestHeight ),
+ Point( nSourceX, nSourceY ), Size( nSourceWidth, nSourceHeight ), *pFromDev->GetOutputDevice() );
+ }
+ }
+}
+
+void VCLXGraphics::draw( const uno::Reference< awt::XDisplayBitmap >& rxBitmapHandle, sal_Int32 nSourceX, sal_Int32 nSourceY, sal_Int32 nSourceWidth, sal_Int32 nSourceHeight, sal_Int32 nDestX, sal_Int32 nDestY, sal_Int32 nDestWidth, sal_Int32 nDestHeight )
+{
+ SolarMutexGuard aGuard;
+
+ if( !mpOutputDevice )
+ return;
+
+ InitOutputDevice( InitOutDevFlags::NONE);
+ uno::Reference< awt::XBitmap > xBitmap( rxBitmapHandle, uno::UNO_QUERY );
+ BitmapEx aBmpEx = VCLUnoHelper::GetBitmap( xBitmap );
+
+ Point aPos(nDestX - nSourceX, nDestY - nSourceY);
+ Size aSz = aBmpEx.GetSizePixel();
+
+ if(nDestWidth != nSourceWidth)
+ {
+ float zoomX = static_cast<float>(nDestWidth) / static_cast<float>(nSourceWidth);
+ aSz.setWidth( static_cast<tools::Long>(static_cast<float>(aSz.Width()) * zoomX) );
+ }
+
+ if(nDestHeight != nSourceHeight)
+ {
+ float zoomY = static_cast<float>(nDestHeight) / static_cast<float>(nSourceHeight);
+ aSz.setHeight( static_cast<tools::Long>(static_cast<float>(aSz.Height()) * zoomY) );
+ }
+
+ if(nSourceX || nSourceY || aSz.Width() != nSourceWidth || aSz.Height() != nSourceHeight)
+ mpOutputDevice->IntersectClipRegion(vcl::Region(tools::Rectangle(nDestX, nDestY, nDestX + nDestWidth - 1, nDestY + nDestHeight - 1)));
+
+ mpOutputDevice->DrawBitmapEx( aPos, aSz, aBmpEx );
+}
+
+void VCLXGraphics::drawPixel( sal_Int32 x, sal_Int32 y )
+{
+ SolarMutexGuard aGuard;
+
+ if( mpOutputDevice )
+ {
+ InitOutputDevice( InitOutDevFlags::COLORS );
+ mpOutputDevice->DrawPixel( Point( x, y ) );
+ }
+}
+
+void VCLXGraphics::drawLine( sal_Int32 x1, sal_Int32 y1, sal_Int32 x2, sal_Int32 y2 )
+{
+ SolarMutexGuard aGuard;
+
+ if( mpOutputDevice )
+ {
+ InitOutputDevice( InitOutDevFlags::COLORS );
+ mpOutputDevice->DrawLine( Point( x1, y1 ), Point( x2, y2 ) );
+ }
+}
+
+void VCLXGraphics::drawRect( sal_Int32 x, sal_Int32 y, sal_Int32 width, sal_Int32 height )
+{
+ SolarMutexGuard aGuard;
+
+ if( mpOutputDevice )
+ {
+ InitOutputDevice( InitOutDevFlags::COLORS );
+ mpOutputDevice->DrawRect( tools::Rectangle( Point( x, y ), Size( width, height ) ) );
+ }
+}
+
+void VCLXGraphics::drawRoundedRect( sal_Int32 x, sal_Int32 y, sal_Int32 width, sal_Int32 height, sal_Int32 nHorzRound, sal_Int32 nVertRound )
+{
+ SolarMutexGuard aGuard;
+
+ if( mpOutputDevice )
+ {
+ InitOutputDevice( InitOutDevFlags::COLORS );
+ mpOutputDevice->DrawRect( tools::Rectangle( Point( x, y ), Size( width, height ) ), nHorzRound, nVertRound );
+ }
+}
+
+void VCLXGraphics::drawPolyLine( const uno::Sequence< sal_Int32 >& DataX, const uno::Sequence< sal_Int32 >& DataY )
+{
+ SolarMutexGuard aGuard;
+
+ if( mpOutputDevice )
+ {
+ InitOutputDevice( InitOutDevFlags::COLORS );
+ mpOutputDevice->DrawPolyLine( VCLUnoHelper::CreatePolygon( DataX, DataY ) );
+ }
+}
+
+void VCLXGraphics::drawPolygon( const uno::Sequence< sal_Int32 >& DataX, const uno::Sequence< sal_Int32 >& DataY )
+{
+ SolarMutexGuard aGuard;
+
+ if( mpOutputDevice )
+ {
+ InitOutputDevice( InitOutDevFlags::COLORS );
+ mpOutputDevice->DrawPolygon( VCLUnoHelper::CreatePolygon( DataX, DataY ) );
+ }
+}
+
+void VCLXGraphics::drawPolyPolygon( const uno::Sequence< uno::Sequence< sal_Int32 > >& DataX, const uno::Sequence< uno::Sequence< sal_Int32 > >& DataY )
+{
+ SolarMutexGuard aGuard;
+
+ if( mpOutputDevice )
+ {
+ InitOutputDevice( InitOutDevFlags::COLORS );
+ sal_uInt16 nPolys = static_cast<sal_uInt16>(DataX.getLength());
+ tools::PolyPolygon aPolyPoly( nPolys );
+ for ( sal_uInt16 n = 0; n < nPolys; n++ )
+ aPolyPoly[n] = VCLUnoHelper::CreatePolygon( DataX.getConstArray()[n], DataY.getConstArray()[n] );
+
+ mpOutputDevice->DrawPolyPolygon( aPolyPoly );
+ }
+}
+
+void VCLXGraphics::drawEllipse( sal_Int32 x, sal_Int32 y, sal_Int32 width, sal_Int32 height )
+{
+ SolarMutexGuard aGuard;
+
+ if( mpOutputDevice )
+ {
+ InitOutputDevice( InitOutDevFlags::COLORS );
+ mpOutputDevice->DrawEllipse( tools::Rectangle( Point( x, y ), Size( width, height ) ) );
+ }
+}
+
+void VCLXGraphics::drawArc( sal_Int32 x, sal_Int32 y, sal_Int32 width, sal_Int32 height, sal_Int32 x1, sal_Int32 y1, sal_Int32 x2, sal_Int32 y2 )
+{
+ SolarMutexGuard aGuard;
+
+ if( mpOutputDevice )
+ {
+ InitOutputDevice( InitOutDevFlags::COLORS );
+ mpOutputDevice->DrawArc( tools::Rectangle( Point( x, y ), Size( width, height ) ), Point( x1, y1 ), Point( x2, y2 ) );
+ }
+}
+
+void VCLXGraphics::drawPie( sal_Int32 x, sal_Int32 y, sal_Int32 width, sal_Int32 height, sal_Int32 x1, sal_Int32 y1, sal_Int32 x2, sal_Int32 y2 )
+{
+ SolarMutexGuard aGuard;
+
+ if( mpOutputDevice )
+ {
+ InitOutputDevice( InitOutDevFlags::COLORS );
+ mpOutputDevice->DrawPie( tools::Rectangle( Point( x, y ), Size( width, height ) ), Point( x1, y1 ), Point( x2, y2 ) );
+ }
+}
+
+void VCLXGraphics::drawChord( sal_Int32 x, sal_Int32 y, sal_Int32 width, sal_Int32 height, sal_Int32 x1, sal_Int32 y1, sal_Int32 x2, sal_Int32 y2 )
+{
+ SolarMutexGuard aGuard;
+
+ if( mpOutputDevice )
+ {
+ InitOutputDevice( InitOutDevFlags::COLORS );
+ mpOutputDevice->DrawChord( tools::Rectangle( Point( x, y ), Size( width, height ) ), Point( x1, y1 ), Point( x2, y2 ) );
+ }
+}
+
+void VCLXGraphics::drawGradient( sal_Int32 x, sal_Int32 y, sal_Int32 width, sal_Int32 height, const awt::Gradient& rGradient )
+{
+ SolarMutexGuard aGuard;
+
+ if( !mpOutputDevice )
+ return;
+
+ InitOutputDevice( InitOutDevFlags::COLORS );
+ Gradient aGradient(rGradient.Style, Color(ColorTransparency, rGradient.StartColor), Color(ColorTransparency, rGradient.EndColor));
+ aGradient.SetAngle(Degree10(rGradient.Angle));
+ aGradient.SetBorder(rGradient.Border);
+ aGradient.SetOfsX(rGradient.XOffset);
+ aGradient.SetOfsY(rGradient.YOffset);
+ aGradient.SetStartIntensity(rGradient.StartIntensity);
+ aGradient.SetEndIntensity(rGradient.EndIntensity);
+ aGradient.SetSteps(rGradient.StepCount);
+ mpOutputDevice->DrawGradient( tools::Rectangle( Point( x, y ), Size( width, height ) ), aGradient );
+}
+
+void VCLXGraphics::drawText( sal_Int32 x, sal_Int32 y, const OUString& rText )
+{
+ SolarMutexGuard aGuard;
+
+ if( mpOutputDevice )
+ {
+ InitOutputDevice( InitOutDevFlags::COLORS |InitOutDevFlags::FONT);
+ mpOutputDevice->DrawText( Point( x, y ), rText );
+ }
+}
+
+void VCLXGraphics::drawTextArray( sal_Int32 x, sal_Int32 y, const OUString& rText, const uno::Sequence< sal_Int32 >& rLongs )
+{
+ SolarMutexGuard aGuard;
+
+ if( mpOutputDevice )
+ {
+ InitOutputDevice( InitOutDevFlags::COLORS|InitOutDevFlags::FONT );
+ KernArray aDXA;
+ aDXA.reserve(rText.getLength());
+ for(int i = 0; i < rText.getLength(); ++i)
+ aDXA.push_back(rLongs[i]);
+ mpOutputDevice->DrawTextArray( Point( x, y ), rText, aDXA, {}, 0, rText.getLength());
+ }
+}
+
+
+void VCLXGraphics::drawImage( sal_Int32 x, sal_Int32 y, sal_Int32 width, sal_Int32 height, sal_Int16 nStyle, const uno::Reference< graphic::XGraphic >& xGraphic )
+{
+ SolarMutexGuard aGuard;
+
+ if( mpOutputDevice && xGraphic.is() )
+ {
+ Image aImage( xGraphic );
+ if ( !!aImage )
+ {
+ InitOutputDevice( InitOutDevFlags::COLORS );
+ mpOutputDevice->DrawImage( Point( x, y ), Size( width, height ), aImage, static_cast<DrawImageFlags>(nStyle) );
+ }
+ }
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/awt/vclxmenu.cxx b/toolkit/source/awt/vclxmenu.cxx
new file mode 100644
index 0000000000..37785849c5
--- /dev/null
+++ b/toolkit/source/awt/vclxmenu.cxx
@@ -0,0 +1,869 @@
+/* -*- 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 <toolkit/awt/vclxmenu.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <tools/debug.hxx>
+#include <vcl/dialoghelper.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/menu.hxx>
+#include <vcl/keycod.hxx>
+#include <vcl/image.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+
+#include <com/sun/star/awt/KeyModifier.hpp>
+
+VCLXMenu::VCLXMenu()
+ : maMenuListeners( *this )
+ , mnDefaultItem(0)
+{
+ mpMenu = nullptr;
+}
+
+VCLXMenu::VCLXMenu( Menu* pMenu )
+ : maMenuListeners( *this )
+ , mnDefaultItem(0)
+{
+ mpMenu = pMenu;
+}
+
+VCLXMenu::~VCLXMenu()
+{
+ maPopupMenuRefs.clear();
+ if ( mpMenu )
+ {
+ SolarMutexGuard g;
+ mpMenu->RemoveEventListener( LINK( this, VCLXMenu, MenuEventListener ) );
+ mpMenu.disposeAndClear();
+ }
+}
+
+bool VCLXMenu::IsPopupMenu() const
+{
+ return (mpMenu && ! mpMenu->IsMenuBar());
+}
+
+void VCLXMenu::ImplCreateMenu( bool bPopup )
+{
+ DBG_ASSERT( !mpMenu, "CreateMenu: Menu exists!" );
+
+ if ( bPopup )
+ mpMenu = VclPtr<PopupMenu>::Create();
+ else
+ mpMenu = VclPtr<MenuBar>::Create();
+
+ mpMenu->AddEventListener( LINK( this, VCLXMenu, MenuEventListener ) );
+}
+
+void VCLXMenu::ImplAddListener()
+{
+ assert(mpMenu);
+ mpMenu->AddEventListener( LINK( this, VCLXMenu, MenuEventListener ) );
+}
+
+IMPL_LINK( VCLXMenu, MenuEventListener, VclMenuEvent&, rMenuEvent, void )
+{
+ DBG_ASSERT( rMenuEvent.GetMenu() && mpMenu, "Menu???" );
+
+ if ( rMenuEvent.GetMenu() != mpMenu ) // Also called for the root menu
+ return;
+
+ switch ( rMenuEvent.GetId() )
+ {
+ case VclEventId::MenuSelect:
+ {
+ if ( maMenuListeners.getLength() )
+ {
+ css::awt::MenuEvent aEvent;
+ aEvent.Source = getXWeak();
+ aEvent.MenuId = mpMenu->GetCurItemId();
+ maMenuListeners.itemSelected( aEvent );
+ }
+ }
+ break;
+ case VclEventId::ObjectDying:
+ {
+ mpMenu = nullptr;
+ }
+ break;
+ case VclEventId::MenuHighlight:
+ {
+ if ( maMenuListeners.getLength() )
+ {
+ css::awt::MenuEvent aEvent;
+ aEvent.Source = getXWeak();
+ aEvent.MenuId = mpMenu->GetCurItemId();
+ maMenuListeners.itemHighlighted( aEvent );
+ }
+ }
+ break;
+ case VclEventId::MenuActivate:
+ {
+ if ( maMenuListeners.getLength() )
+ {
+ css::awt::MenuEvent aEvent;
+ aEvent.Source = getXWeak();
+ aEvent.MenuId = mpMenu->GetCurItemId();
+ maMenuListeners.itemActivated( aEvent );
+ }
+ }
+ break;
+ case VclEventId::MenuDeactivate:
+ {
+ if ( maMenuListeners.getLength() )
+ {
+ css::awt::MenuEvent aEvent;
+ aEvent.Source = getXWeak();
+ aEvent.MenuId = mpMenu->GetCurItemId();
+ maMenuListeners.itemDeactivated( aEvent );
+ }
+ }
+ break;
+
+ // ignore accessibility events
+ case VclEventId::MenuEnable:
+ case VclEventId::MenuInsertItem:
+ case VclEventId::MenuRemoveItem:
+ case VclEventId::MenuSubmenuActivate:
+ case VclEventId::MenuSubmenuDeactivate:
+ case VclEventId::MenuSubmenuChanged:
+ case VclEventId::MenuDehighlight:
+ case VclEventId::MenuDisable:
+ case VclEventId::MenuItemRoleChanged:
+ case VclEventId::MenuItemTextChanged:
+ case VclEventId::MenuItemChecked:
+ case VclEventId::MenuItemUnchecked:
+ case VclEventId::MenuShow:
+ case VclEventId::MenuHide:
+ break;
+
+ default: OSL_FAIL( "MenuEventListener - Unknown event!" );
+ }
+}
+
+
+OUString SAL_CALL VCLXMenu::getImplementationName( )
+{
+ std::unique_lock aGuard( maMutex );
+ const bool bIsPopupMenu = IsPopupMenu();
+ aGuard.unlock();
+
+ OUString implName( "stardiv.Toolkit." );
+ if ( bIsPopupMenu )
+ implName += "VCLXPopupMenu";
+ else
+ implName += "VCLXMenuBar";
+
+ return implName;
+}
+
+css::uno::Sequence< OUString > SAL_CALL VCLXMenu::getSupportedServiceNames( )
+{
+ std::unique_lock aGuard( maMutex );
+ const bool bIsPopupMenu = IsPopupMenu();
+ aGuard.unlock();
+
+ if ( bIsPopupMenu )
+ return css::uno::Sequence<OUString>{
+ "com.sun.star.awt.PopupMenu",
+ "stardiv.vcl.PopupMenu"};
+ else
+ return css::uno::Sequence<OUString>{
+ "com.sun.star.awt.MenuBar",
+ "stardiv.vcl.MenuBar"};
+}
+
+sal_Bool SAL_CALL VCLXMenu::supportsService(const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Any VCLXMenu::queryInterface(
+ const css::uno::Type & rType )
+{
+ std::unique_lock aGuard( maMutex );
+ const bool bIsPopupMenu = IsPopupMenu();
+ aGuard.unlock();
+
+ css::uno::Any aRet;
+
+ if ( bIsPopupMenu )
+ aRet = ::cppu::queryInterface( rType,
+ static_cast< css::awt::XMenu* >(static_cast<css::awt::XMenuBar*>(this)),
+ static_cast< css::awt::XPopupMenu* >(this),
+ static_cast< css::lang::XTypeProvider* >(this),
+ static_cast< css::lang::XServiceInfo* >(this) );
+ else
+ aRet = ::cppu::queryInterface( rType,
+ static_cast< css::awt::XMenu* >(static_cast<css::awt::XMenuBar*>(this)),
+ static_cast< css::awt::XMenuBar* >(this),
+ static_cast< css::lang::XTypeProvider* >(this),
+ static_cast< css::lang::XServiceInfo* >(this) );
+
+ return (aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ));
+}
+
+
+css::uno::Sequence< css::uno::Type > VCLXMenu::getTypes()
+{
+ std::unique_lock aGuard( maMutex );
+ const bool bIsPopupMenu = IsPopupMenu();
+ aGuard.unlock();
+
+ if ( bIsPopupMenu )
+ {
+ static cppu::OTypeCollection collectionPopupMenu(
+ cppu::UnoType<css::lang::XTypeProvider>::get(), cppu::UnoType<css::awt::XMenu>::get(),
+ cppu::UnoType<css::awt::XPopupMenu>::get(),
+ cppu::UnoType<css::lang::XServiceInfo>::get());
+ return collectionPopupMenu.getTypes();
+ }
+ else
+ {
+ static cppu::OTypeCollection collectionMenuBar(
+ cppu::UnoType<css::lang::XTypeProvider>::get(), cppu::UnoType<css::awt::XMenu>::get(),
+ cppu::UnoType<css::awt::XMenuBar>::get(),
+ cppu::UnoType<css::lang::XServiceInfo>::get());
+ return collectionMenuBar.getTypes();
+ }
+}
+
+
+css::uno::Sequence< sal_Int8 > VCLXMenu::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+void VCLXMenu::addMenuListener(
+ const css::uno::Reference< css::awt::XMenuListener >& rxListener )
+{
+ std::unique_lock aGuard( maMutex );
+
+ maMenuListeners.addInterface( rxListener );
+}
+
+void VCLXMenu::removeMenuListener(
+ const css::uno::Reference< css::awt::XMenuListener >& rxListener )
+{
+ std::unique_lock aGuard( maMutex );
+
+ maMenuListeners.removeInterface( rxListener );
+}
+
+void VCLXMenu::insertItem(
+ sal_Int16 nItemId,
+ const OUString& aText,
+ sal_Int16 nItemStyle,
+ sal_Int16 nPos )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ if ( mpMenu )
+ mpMenu->InsertItem(nItemId, aText, static_cast<MenuItemBits>(nItemStyle), {}, nPos);
+}
+
+void VCLXMenu::removeItem(
+ sal_Int16 nPos,
+ sal_Int16 nCount )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ if (!mpMenu)
+ return;
+
+ sal_Int32 nItemCount = static_cast<sal_Int32>(mpMenu->GetItemCount());
+ if ((nCount > 0) && (nPos >= 0) && (nPos < nItemCount))
+ {
+ sal_Int16 nP = sal::static_int_cast< sal_Int16 >(
+ std::min( static_cast<int>(nPos+nCount), static_cast<int>(nItemCount) ));
+ while( nP-nPos > 0 )
+ mpMenu->RemoveItem( --nP );
+ }
+}
+
+sal_Int16 VCLXMenu::getItemCount( )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ return mpMenu ? mpMenu->GetItemCount() : 0;
+}
+
+sal_Int16 VCLXMenu::getItemId(
+ sal_Int16 nPos )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ return mpMenu ? mpMenu->GetItemId( nPos ) : 0;
+}
+
+sal_Int16 VCLXMenu::getItemPos(
+ sal_Int16 nId )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ return mpMenu ? mpMenu->GetItemPos( nId ) : 0;
+}
+
+void VCLXMenu::enableItem(
+ sal_Int16 nItemId,
+ sal_Bool bEnable )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ if ( mpMenu )
+ mpMenu->EnableItem( nItemId, bEnable );
+}
+
+sal_Bool VCLXMenu::isItemEnabled(
+ sal_Int16 nItemId )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ return mpMenu && mpMenu->IsItemEnabled( nItemId );
+}
+
+void VCLXMenu::setItemText(
+ sal_Int16 nItemId,
+ const OUString& aText )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ if ( mpMenu )
+ mpMenu->SetItemText( nItemId, aText );
+}
+
+OUString VCLXMenu::getItemText(
+ sal_Int16 nItemId )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ OUString aItemText;
+ if ( mpMenu )
+ aItemText = mpMenu->GetItemText( nItemId );
+ return aItemText;
+}
+
+void VCLXMenu::setPopupMenu(
+ sal_Int16 nItemId,
+ const css::uno::Reference< css::awt::XPopupMenu >& rxPopupMenu )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ VCLXMenu* pVCLMenu = dynamic_cast<VCLXMenu*>( rxPopupMenu.get() );
+ DBG_ASSERT( pVCLMenu && pVCLMenu->GetMenu() && pVCLMenu->IsPopupMenu(), "setPopupMenu: Invalid Menu!" );
+
+ if ( mpMenu && pVCLMenu && pVCLMenu->GetMenu() && pVCLMenu->IsPopupMenu() )
+ {
+ maPopupMenuRefs.push_back( rxPopupMenu );
+
+ mpMenu->SetPopupMenu( nItemId, static_cast<PopupMenu*>( pVCLMenu->GetMenu() ) );
+ }
+}
+
+css::uno::Reference< css::awt::XPopupMenu > VCLXMenu::getPopupMenu(
+ sal_Int16 nItemId )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ css::uno::Reference< css::awt::XPopupMenu > aRef;
+ Menu* pMenu = mpMenu ? mpMenu->GetPopupMenu( nItemId ) : nullptr;
+ if ( pMenu )
+ {
+ for ( size_t n = maPopupMenuRefs.size(); n; )
+ {
+ css::uno::Reference< css::awt::XPopupMenu >& rRef = maPopupMenuRefs[ --n ];
+ Menu* pM = static_cast<VCLXMenu*>(rRef.get())->GetMenu();
+ if ( pM == pMenu )
+ {
+ aRef = rRef;
+ break;
+ }
+ }
+ // it seems the popup menu is not insert into maPopupMenuRefs
+ // if the popup men is not created by stardiv.Toolkit.VCLXPopupMenu
+ if( !aRef.is() )
+ {
+ aRef = new VCLXPopupMenu( static_cast<PopupMenu*>(pMenu) );
+ }
+ }
+ return aRef;
+}
+
+// css::awt::XPopupMenu
+void VCLXMenu::insertSeparator(
+ sal_Int16 nPos )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ if ( mpMenu )
+ mpMenu->InsertSeparator({}, nPos);
+}
+
+void VCLXMenu::setDefaultItem(
+ sal_Int16 nItemId )
+{
+ std::unique_lock aGuard( maMutex );
+
+ mnDefaultItem = nItemId;
+}
+
+sal_Int16 VCLXMenu::getDefaultItem( )
+{
+ std::unique_lock aGuard( maMutex );
+
+ return mnDefaultItem;
+}
+
+void VCLXMenu::checkItem(
+ sal_Int16 nItemId,
+ sal_Bool bCheck )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ if ( mpMenu )
+ mpMenu->CheckItem( nItemId, bCheck );
+}
+
+sal_Bool VCLXMenu::isItemChecked(
+ sal_Int16 nItemId )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ return mpMenu && mpMenu->IsItemChecked( nItemId );
+}
+
+sal_Int16 VCLXMenu::execute(
+ const css::uno::Reference< css::awt::XWindowPeer >& rxWindowPeer,
+ const css::awt::Rectangle& rPos,
+ sal_Int16 nFlags )
+{
+ SolarMutexGuard aSolarGuard;
+ auto pMenu = mpMenu;
+ {
+ std::unique_lock aGuard( maMutex );
+ if ( !mpMenu || !IsPopupMenu() )
+ return 0;
+ }
+ // cannot call this with mutex locked because it will call back into us
+ return static_cast<PopupMenu*>(pMenu.get())->Execute(
+ VCLUnoHelper::GetWindow( rxWindowPeer ),
+ VCLRectangle( rPos ),
+ static_cast<PopupMenuFlags>(nFlags) | PopupMenuFlags::NoMouseUpClose );
+}
+
+
+void SAL_CALL VCLXMenu::setCommand(
+ sal_Int16 nItemId,
+ const OUString& aCommand )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ if ( mpMenu )
+ mpMenu->SetItemCommand( nItemId, aCommand );
+}
+
+OUString SAL_CALL VCLXMenu::getCommand(
+ sal_Int16 nItemId )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ OUString aItemCommand;
+ if ( mpMenu )
+ aItemCommand = mpMenu->GetItemCommand( nItemId );
+ return aItemCommand;
+}
+
+void SAL_CALL VCLXMenu::setHelpCommand(
+ sal_Int16 nItemId,
+ const OUString& aHelp )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ if ( mpMenu )
+ mpMenu->SetHelpCommand( nItemId, aHelp );
+}
+
+OUString SAL_CALL VCLXMenu::getHelpCommand(
+ sal_Int16 nItemId )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ OUString aHelpCommand;
+ if ( mpMenu )
+ aHelpCommand = mpMenu->GetHelpCommand( nItemId );
+ return aHelpCommand;
+}
+
+
+namespace
+{
+ Image lcl_XGraphic2VCLImage(
+ const css::uno::Reference< css::graphic::XGraphic >& xGraphic,
+ bool bResize )
+ {
+ Image aImage;
+ if ( !xGraphic.is() )
+ return aImage;
+
+ aImage = Image( xGraphic );
+ const ::Size aCurSize = aImage.GetSizePixel();
+ const sal_Int32 nCurWidth = aCurSize.Width();
+ const sal_Int32 nCurHeight = aCurSize.Height();
+ constexpr sal_Int32 nIdeal( 16 );
+
+ if ( nCurWidth > 0 && nCurHeight > 0 )
+ {
+ if ( bResize && ( nCurWidth > nIdeal || nCurHeight > nIdeal ) )
+ {
+ sal_Int32 nIdealWidth = std::min(nCurWidth, nIdeal);
+ sal_Int32 nIdealHeight = std::min(nCurHeight, nIdeal);
+
+ ::Size aNewSize( nIdealWidth, nIdealHeight );
+
+ bool bModified( false );
+ BitmapEx aBitmapEx = aImage.GetBitmapEx();
+ bModified = aBitmapEx.Scale( aNewSize, BmpScaleFlag::BestQuality );
+
+ if ( bModified )
+ aImage = Image( aBitmapEx );
+ }
+ }
+ return aImage;
+ }
+
+ /** Copied from include/svtools/acceleratorexecute.hxx */
+ css::awt::KeyEvent lcl_VCLKey2AWTKey(
+ const vcl::KeyCode& aVCLKey)
+ {
+ css::awt::KeyEvent aAWTKey;
+ aAWTKey.Modifiers = 0;
+ aAWTKey.KeyCode = static_cast<sal_Int16>(aVCLKey.GetCode());
+
+ if (aVCLKey.IsShift())
+ aAWTKey.Modifiers |= css::awt::KeyModifier::SHIFT;
+ if (aVCLKey.IsMod1())
+ aAWTKey.Modifiers |= css::awt::KeyModifier::MOD1;
+ if (aVCLKey.IsMod2())
+ aAWTKey.Modifiers |= css::awt::KeyModifier::MOD2;
+ if (aVCLKey.IsMod3())
+ aAWTKey.Modifiers |= css::awt::KeyModifier::MOD3;
+
+ return aAWTKey;
+ }
+
+ vcl::KeyCode lcl_AWTKey2VCLKey(const css::awt::KeyEvent& aAWTKey)
+ {
+ bool bShift = ((aAWTKey.Modifiers & css::awt::KeyModifier::SHIFT) == css::awt::KeyModifier::SHIFT );
+ bool bMod1 = ((aAWTKey.Modifiers & css::awt::KeyModifier::MOD1 ) == css::awt::KeyModifier::MOD1 );
+ bool bMod2 = ((aAWTKey.Modifiers & css::awt::KeyModifier::MOD2 ) == css::awt::KeyModifier::MOD2 );
+ bool bMod3 = ((aAWTKey.Modifiers & css::awt::KeyModifier::MOD3 ) == css::awt::KeyModifier::MOD3 );
+ sal_uInt16 nKey = static_cast<sal_uInt16>(aAWTKey.KeyCode);
+
+ return vcl::KeyCode(nKey, bShift, bMod1, bMod2, bMod3);
+ }
+
+}
+
+
+sal_Bool SAL_CALL VCLXMenu::isPopupMenu( )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+ return IsPopupMenu();
+}
+
+void SAL_CALL VCLXMenu::clear( )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+ if ( mpMenu )
+ mpMenu->Clear();
+}
+
+
+css::awt::MenuItemType SAL_CALL VCLXMenu::getItemType(
+ ::sal_Int16 nItemPos )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ css::awt::MenuItemType aMenuItemType =
+ css::awt::MenuItemType_DONTKNOW;
+ if ( mpMenu )
+ {
+ aMenuItemType = static_cast<css::awt::MenuItemType>(mpMenu->GetItemType( nItemPos ));
+ }
+
+ return aMenuItemType;
+}
+
+void SAL_CALL VCLXMenu::hideDisabledEntries(
+ sal_Bool bHide )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+ if ( mpMenu )
+ {
+ if ( bHide )
+ mpMenu->SetMenuFlags( mpMenu->GetMenuFlags() | MenuFlags::HideDisabledEntries );
+ else
+ mpMenu->SetMenuFlags( mpMenu->GetMenuFlags() & ~MenuFlags::HideDisabledEntries );
+ }
+}
+
+
+sal_Bool SAL_CALL VCLXMenu::isInExecute( )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ if ( mpMenu && IsPopupMenu() )
+ return vcl::IsInPopupMenuExecute();
+ else
+ return false;
+}
+
+
+void SAL_CALL VCLXMenu::endExecute()
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ if ( mpMenu && IsPopupMenu() )
+ static_cast<PopupMenu*>( mpMenu.get() )->EndExecute();
+}
+
+
+void SAL_CALL VCLXMenu::enableAutoMnemonics(
+ sal_Bool bEnable )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+ if ( mpMenu )
+ {
+ if ( !bEnable )
+ mpMenu->SetMenuFlags( mpMenu->GetMenuFlags() | MenuFlags::NoAutoMnemonics );
+ else
+ mpMenu->SetMenuFlags( mpMenu->GetMenuFlags() & ~MenuFlags::NoAutoMnemonics );
+ }
+}
+
+
+void SAL_CALL VCLXMenu::setAcceleratorKeyEvent(
+ ::sal_Int16 nItemId,
+ const css::awt::KeyEvent& aKeyEvent )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ if ( mpMenu && IsPopupMenu() && MENU_ITEM_NOTFOUND != mpMenu->GetItemPos( nItemId ) )
+ {
+ vcl::KeyCode aVCLKeyCode = lcl_AWTKey2VCLKey( aKeyEvent );
+ mpMenu->SetAccelKey( nItemId, aVCLKeyCode );
+ }
+}
+
+
+css::awt::KeyEvent SAL_CALL VCLXMenu::getAcceleratorKeyEvent(
+ ::sal_Int16 nItemId )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ css::awt::KeyEvent aKeyEvent;
+ if ( mpMenu && IsPopupMenu() && MENU_ITEM_NOTFOUND != mpMenu->GetItemPos( nItemId ) )
+ {
+ vcl::KeyCode nKeyCode = mpMenu->GetAccelKey( nItemId );
+ aKeyEvent = lcl_VCLKey2AWTKey( nKeyCode );
+ }
+
+ return aKeyEvent;
+}
+
+
+void SAL_CALL VCLXMenu::setHelpText(
+ ::sal_Int16 nItemId,
+ const OUString& sHelpText )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ if ( mpMenu && MENU_ITEM_NOTFOUND != mpMenu->GetItemPos( nItemId ) )
+ {
+ mpMenu->SetHelpText( nItemId, sHelpText );
+ }
+}
+
+
+OUString SAL_CALL VCLXMenu::getHelpText(
+ ::sal_Int16 nItemId )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ OUString sHelpText;
+ if ( mpMenu && MENU_ITEM_NOTFOUND != mpMenu->GetItemPos( nItemId ) )
+ {
+ sHelpText = mpMenu->GetHelpText( nItemId );
+ }
+
+ return sHelpText;
+}
+
+
+void SAL_CALL VCLXMenu::setTipHelpText(
+ ::sal_Int16 nItemId,
+ const OUString& sTipHelpText )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ if ( mpMenu && MENU_ITEM_NOTFOUND != mpMenu->GetItemPos( nItemId ) )
+ {
+ mpMenu->SetTipHelpText( nItemId, sTipHelpText );
+ }
+}
+
+
+OUString SAL_CALL VCLXMenu::getTipHelpText(
+ ::sal_Int16 nItemId )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ OUString sTipHelpText;
+ if ( mpMenu && MENU_ITEM_NOTFOUND != mpMenu->GetItemPos( nItemId ) )
+ {
+ sTipHelpText = mpMenu->GetTipHelpText( nItemId );
+ }
+ return sTipHelpText;
+}
+
+
+void SAL_CALL VCLXMenu::setItemImage(
+ ::sal_Int16 nItemId,
+ const css::uno::Reference< css::graphic::XGraphic >& xGraphic,
+ sal_Bool bScale )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ if ( mpMenu && IsPopupMenu() && MENU_ITEM_NOTFOUND != mpMenu->GetItemPos( nItemId ) )
+ {
+ Image aImage = lcl_XGraphic2VCLImage( xGraphic, bScale );
+ mpMenu->SetItemImage( nItemId, aImage );
+ }
+}
+
+
+css::uno::Reference< css::graphic::XGraphic > SAL_CALL
+VCLXMenu::getItemImage(
+ ::sal_Int16 nItemId )
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard( maMutex );
+
+ css::uno::Reference< css::graphic::XGraphic > rxGraphic;
+
+ if ( mpMenu && IsPopupMenu() && MENU_ITEM_NOTFOUND != mpMenu->GetItemPos( nItemId ) )
+ {
+ Image aImage = mpMenu->GetItemImage( nItemId );
+ if ( !!aImage )
+ rxGraphic = Graphic(aImage.GetBitmapEx()).GetXGraphic();
+ }
+ return rxGraphic;
+}
+
+void VCLXMenu::setUserValue(sal_uInt16 nItemId, void* nUserValue, MenuUserDataReleaseFunction aFunc)
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard(maMutex);
+
+ mpMenu->SetUserValue(nItemId, nUserValue, aFunc);
+}
+
+void* VCLXMenu::getUserValue(sal_uInt16 nItemId)
+{
+ SolarMutexGuard aSolarGuard;
+ std::unique_lock aGuard(maMutex);
+
+ return mpMenu->GetUserValue(nItemId);
+}
+
+VCLXMenuBar::VCLXMenuBar()
+{
+ ImplCreateMenu( false );
+}
+
+VCLXMenuBar::VCLXMenuBar( MenuBar* pMenuBar ) : VCLXMenu( static_cast<Menu *>(pMenuBar) )
+{
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_VCLXMenuBar_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new VCLXMenuBar());
+}
+
+VCLXPopupMenu::VCLXPopupMenu()
+{
+ ImplCreateMenu( true );
+}
+
+VCLXPopupMenu::VCLXPopupMenu( PopupMenu* pPopMenu ) : VCLXMenu( static_cast<Menu *>(pPopMenu) )
+{
+ ImplAddListener();
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_VCLXPopupMenu_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new VCLXPopupMenu());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/awt/vclxpointer.cxx b/toolkit/source/awt/vclxpointer.cxx
new file mode 100644
index 0000000000..b541610413
--- /dev/null
+++ b/toolkit/source/awt/vclxpointer.cxx
@@ -0,0 +1,70 @@
+/* -*- 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 <awt/vclxpointer.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+VCLXPointer::VCLXPointer() : maPointer(PointerStyle::Arrow)
+{
+}
+
+VCLXPointer::~VCLXPointer()
+{
+}
+
+void VCLXPointer::setType( sal_Int32 nType )
+{
+ std::scoped_lock aGuard( maMutex );
+
+ maPointer = static_cast<PointerStyle>(nType);
+}
+
+sal_Int32 VCLXPointer::getType()
+{
+ std::scoped_lock aGuard( maMutex );
+
+ return static_cast<sal_Int32>(maPointer);
+}
+
+OUString VCLXPointer::getImplementationName()
+{
+ return "stardiv.Toolkit.VCLXPointer";
+}
+
+sal_Bool VCLXPointer::supportsService(OUString const & ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+css::uno::Sequence<OUString> VCLXPointer::getSupportedServiceNames()
+{
+ return css::uno::Sequence<OUString>{
+ "com.sun.star.awt.Pointer", "stardiv.vcl.Pointer"};
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_VCLXPointer_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new VCLXPointer());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/awt/vclxprinter.cxx b/toolkit/source/awt/vclxprinter.cxx
new file mode 100644
index 0000000000..6ace061795
--- /dev/null
+++ b/toolkit/source/awt/vclxprinter.cxx
@@ -0,0 +1,379 @@
+/* -*- 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 <awt/vclxprinter.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <comphelper/string.hxx>
+
+#include <vcl/print.hxx>
+#include <vcl/jobset.hxx>
+#include <vcl/oldprintadaptor.hxx>
+#include <vcl/svapp.hxx>
+
+#include <tools/debug.hxx>
+#include <tools/stream.hxx>
+#include <o3tl/string_view.hxx>
+
+#include <toolkit/awt/vclxdevice.hxx>
+
+
+#define BINARYSETUPMARKER 0x23864691
+
+#define PROPERTY_Orientation 0
+#define PROPERTY_Horizontal 1
+
+// ----------------------------------------------------
+// class VCLXPrinterPropertySet
+// ----------------------------------------------------
+
+IMPLEMENT_FORWARD_XINTERFACE2( VCLXPrinterPropertySet, VCLXPrinterPropertySet_Base, OPropertySetHelper )
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXPrinterPropertySet, VCLXPrinterPropertySet_Base, ::cppu::OPropertySetHelper )
+
+VCLXPrinterPropertySet::VCLXPrinterPropertySet( const OUString& rPrinterName )
+ : OPropertySetHelper( m_aBHelper )
+ , mxPrinter(VclPtrInstance< Printer >(rPrinterName))
+{
+ SolarMutexGuard aSolarGuard;
+
+ mnOrientation = 0;
+ mbHorizontal = false;
+}
+
+VCLXPrinterPropertySet::~VCLXPrinterPropertySet()
+{
+ SolarMutexGuard aSolarGuard;
+ mxPrinter.reset();
+}
+
+css::uno::Reference< css::awt::XDevice > const & VCLXPrinterPropertySet::GetDevice()
+{
+ if ( !mxPrnDevice.is() )
+ {
+ rtl::Reference<VCLXDevice> pDev = new VCLXDevice;
+ pDev->SetOutputDevice( GetPrinter() );
+ mxPrnDevice = pDev;
+ }
+ return mxPrnDevice;
+}
+
+css::uno::Reference< css::beans::XPropertySetInfo > VCLXPrinterPropertySet::getPropertySetInfo( )
+{
+ static css::uno::Reference< css::beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+::cppu::IPropertyArrayHelper& VCLXPrinterPropertySet::getInfoHelper()
+{
+ static ::cppu::OPropertyArrayHelper s_PropertyArrayHelper(
+ css::uno::Sequence<css::beans::Property>{
+ css::beans::Property( "Orientation", PROPERTY_Orientation, cppu::UnoType<sal_Int16>::get(), 0 ),
+ css::beans::Property( "Horizontal", PROPERTY_Horizontal, cppu::UnoType<bool>::get(), 0 )},
+ false);
+
+ return s_PropertyArrayHelper;
+}
+
+sal_Bool VCLXPrinterPropertySet::convertFastPropertyValue( css::uno::Any & rConvertedValue, css::uno::Any & rOldValue, sal_Int32 nHandle, const css::uno::Any& rValue )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ bool bDifferent = false;
+ switch ( nHandle )
+ {
+ case PROPERTY_Orientation:
+ {
+ sal_Int16 n;
+ if( ( rValue >>= n ) && ( n != mnOrientation ) )
+ {
+ rConvertedValue <<= n;
+ rOldValue <<= mnOrientation;
+ bDifferent = true;
+ }
+ }
+ break;
+ case PROPERTY_Horizontal:
+ {
+ bool b;
+ if( ( rValue >>= b ) && ( b != mbHorizontal ) )
+ {
+ rConvertedValue <<= b;
+ rOldValue <<= mbHorizontal;
+ bDifferent = true;
+ }
+ }
+ break;
+ default:
+ {
+ OSL_FAIL( "VCLXPrinterPropertySet_Impl::convertFastPropertyValue - invalid Handle" );
+ }
+ }
+ return bDifferent;
+}
+
+void VCLXPrinterPropertySet::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const css::uno::Any& rValue )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ switch( nHandle )
+ {
+ case PROPERTY_Orientation:
+ {
+ rValue >>= mnOrientation;
+ }
+ break;
+ case PROPERTY_Horizontal:
+ {
+ rValue >>= mbHorizontal;
+ }
+ break;
+ default:
+ {
+ OSL_FAIL( "VCLXPrinterPropertySet_Impl::convertFastPropertyValue - invalid Handle" );
+ }
+ }
+}
+
+void VCLXPrinterPropertySet::getFastPropertyValue( css::uno::Any& rValue, sal_Int32 nHandle ) const
+{
+ ::osl::MutexGuard aGuard( const_cast<VCLXPrinterPropertySet*>(this)->m_aMutex );
+
+ switch( nHandle )
+ {
+ case PROPERTY_Orientation:
+ rValue <<= mnOrientation;
+ break;
+ case PROPERTY_Horizontal:
+ rValue <<= mbHorizontal;
+ break;
+ default:
+ {
+ OSL_FAIL( "VCLXPrinterPropertySet_Impl::convertFastPropertyValue - invalid Handle" );
+ }
+ }
+}
+
+// css::awt::XPrinterPropertySet
+void VCLXPrinterPropertySet::setHorizontal( sal_Bool bHorizontal )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ css::uno::Any aValue;
+ aValue <<= bHorizontal;
+ setFastPropertyValue( PROPERTY_Horizontal, aValue );
+}
+
+css::uno::Sequence< OUString > VCLXPrinterPropertySet::getFormDescriptions( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ const sal_uInt16 nPaperBinCount = GetPrinter()->GetPaperBinCount();
+ css::uno::Sequence< OUString > aDescriptions( nPaperBinCount );
+ for ( sal_uInt16 n = 0; n < nPaperBinCount; n++ )
+ {
+ // Format: <DisplayFormName;FormNameId;DisplayPaperBinName;PaperBinNameId;DisplayPaperName;PaperNameId>
+ OUString aDescr = "*;*;" + GetPrinter()->GetPaperBinName( n ) + ";" +
+ OUString::number(n) + ";*;*";
+
+ aDescriptions.getArray()[n] = aDescr;
+ }
+ return aDescriptions;
+}
+
+void VCLXPrinterPropertySet::selectForm( const OUString& rFormDescription )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ sal_uInt16 nPaperBin = sal::static_int_cast< sal_uInt16 >(
+ o3tl::toInt32(o3tl::getToken(rFormDescription, 3, ';' )));
+ GetPrinter()->SetPaperBin( nPaperBin );
+}
+
+css::uno::Sequence< sal_Int8 > VCLXPrinterPropertySet::getBinarySetup( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ SvMemoryStream aMem;
+ aMem.WriteUInt32( BINARYSETUPMARKER );
+ WriteJobSetup( aMem, GetPrinter()->GetJobSetup() );
+ return css::uno::Sequence<sal_Int8>( static_cast<sal_Int8 const *>(aMem.GetData()), aMem.Tell() );
+}
+
+void VCLXPrinterPropertySet::setBinarySetup( const css::uno::Sequence< sal_Int8 >& data )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ SvMemoryStream aMem( const_cast<signed char*>(data.getConstArray()), data.getLength(), StreamMode::READ );
+ sal_uInt32 nMarker;
+ aMem.ReadUInt32( nMarker );
+ DBG_ASSERT( nMarker == BINARYSETUPMARKER, "setBinarySetup - invalid!" );
+ if ( nMarker == BINARYSETUPMARKER )
+ {
+ JobSetup aSetup;
+ ReadJobSetup( aMem, aSetup );
+ GetPrinter()->SetJobSetup( aSetup );
+ }
+}
+
+
+// ----------------------------------------------------
+// class VCLXPrinter
+// ----------------------------------------------------
+VCLXPrinter::VCLXPrinter( const OUString& rPrinterName )
+ : VCLXPrinter_Base( rPrinterName )
+{
+}
+
+VCLXPrinter::~VCLXPrinter()
+{
+}
+
+sal_Bool VCLXPrinter::start( const OUString& /*rJobName*/, sal_Int16 /*nCopies*/, sal_Bool /*bCollate*/ )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if (mxPrinter)
+ {
+ maInitJobSetup = mxPrinter->GetJobSetup();
+ mxListener = std::make_shared<vcl::OldStylePrintAdaptor>(mxPrinter, nullptr);
+ }
+
+ return true;
+}
+
+void VCLXPrinter::end( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if (mxListener)
+ {
+ Printer::PrintJob(mxListener, maInitJobSetup);
+ mxListener.reset();
+ }
+}
+
+void VCLXPrinter::terminate( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ mxListener.reset();
+}
+
+css::uno::Reference< css::awt::XDevice > VCLXPrinter::startPage( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if (mxListener)
+ {
+ mxListener->StartPage();
+ }
+ return GetDevice();
+}
+
+void VCLXPrinter::endPage( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if (mxListener)
+ {
+ mxListener->EndPage();
+ }
+}
+
+
+// ----------------------------------------------------
+// class VCLXInfoPrinter
+// ----------------------------------------------------
+
+VCLXInfoPrinter::VCLXInfoPrinter( const OUString& rPrinterName )
+ : VCLXInfoPrinter_Base( rPrinterName )
+{
+}
+
+VCLXInfoPrinter::~VCLXInfoPrinter()
+{
+}
+
+// css::awt::XInfoPrinter
+css::uno::Reference< css::awt::XDevice > VCLXInfoPrinter::createDevice( )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return GetDevice();
+}
+
+// ----------------------------------------------------
+// class VCLXPrinterServer
+// ----------------------------------------------------
+
+// css::awt::XPrinterServer2
+css::uno::Sequence< OUString > VCLXPrinterServer::getPrinterNames( )
+{
+ const std::vector<OUString>& rQueues = Printer::GetPrinterQueues();
+ sal_uInt32 nPrinters = rQueues.size();
+
+ css::uno::Sequence< OUString > aNames( nPrinters );
+ for ( sal_uInt32 n = 0; n < nPrinters; n++ )
+ aNames.getArray()[n] = rQueues[n];
+
+ return aNames;
+}
+
+OUString VCLXPrinterServer::getDefaultPrinterName()
+{
+ return Printer::GetDefaultPrinterName();
+}
+
+css::uno::Reference< css::awt::XPrinter > VCLXPrinterServer::createPrinter( const OUString& rPrinterName )
+{
+ css::uno::Reference< css::awt::XPrinter > xP = new VCLXPrinter( rPrinterName );
+ return xP;
+}
+
+css::uno::Reference< css::awt::XInfoPrinter > VCLXPrinterServer::createInfoPrinter( const OUString& rPrinterName )
+{
+ css::uno::Reference< css::awt::XInfoPrinter > xP = new VCLXInfoPrinter( rPrinterName );
+ return xP;
+}
+
+OUString VCLXPrinterServer::getImplementationName()
+{
+ return "stardiv.Toolkit.VCLXPrinterServer";
+}
+
+sal_Bool VCLXPrinterServer::supportsService(OUString const & ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+css::uno::Sequence<OUString> VCLXPrinterServer::getSupportedServiceNames()
+{
+ return css::uno::Sequence<OUString>{
+ "com.sun.star.awt.PrinterServer", "stardiv.vcl.PrinterServer"};
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_VCLXPrinterServer_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new VCLXPrinterServer);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/awt/vclxregion.cxx b/toolkit/source/awt/vclxregion.cxx
new file mode 100644
index 0000000000..fff7e7969d
--- /dev/null
+++ b/toolkit/source/awt/vclxregion.cxx
@@ -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 .
+ */
+
+#include <awt/vclxregion.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <toolkit/helper/convert.hxx>
+
+
+
+VCLXRegion::VCLXRegion()
+{
+}
+
+VCLXRegion::~VCLXRegion()
+{
+}
+
+css::awt::Rectangle VCLXRegion::getBounds()
+{
+ std::scoped_lock aGuard( maMutex );
+
+ return AWTRectangle( maRegion.GetBoundRect() );
+}
+
+void VCLXRegion::clear()
+{
+ std::scoped_lock aGuard( maMutex );
+
+ maRegion.SetEmpty();
+}
+
+void VCLXRegion::move( sal_Int32 nHorzMove, sal_Int32 nVertMove )
+{
+ std::scoped_lock aGuard( maMutex );
+
+ maRegion.Move( nHorzMove, nVertMove );
+}
+
+void VCLXRegion::unionRectangle( const css::awt::Rectangle& rRect )
+{
+ std::scoped_lock aGuard( maMutex );
+
+ maRegion.Union( VCLRectangle( rRect ) );
+}
+
+void VCLXRegion::intersectRectangle( const css::awt::Rectangle& rRect )
+{
+ std::scoped_lock aGuard( maMutex );
+
+ maRegion.Intersect( VCLRectangle( rRect ) );
+}
+
+void VCLXRegion::excludeRectangle( const css::awt::Rectangle& rRect )
+{
+ std::scoped_lock aGuard( maMutex );
+
+ maRegion.Exclude( VCLRectangle( rRect ) );
+}
+
+void VCLXRegion::xOrRectangle( const css::awt::Rectangle& rRect )
+{
+ std::scoped_lock aGuard( maMutex );
+
+ maRegion.XOr( VCLRectangle( rRect ) );
+}
+
+void VCLXRegion::unionRegion( const css::uno::Reference< css::awt::XRegion >& rxRegion )
+{
+ std::scoped_lock aGuard( maMutex );
+
+ if ( rxRegion.is() )
+ maRegion.Union( VCLUnoHelper::GetRegion( rxRegion ) );
+}
+
+void VCLXRegion::intersectRegion( const css::uno::Reference< css::awt::XRegion >& rxRegion )
+{
+ std::scoped_lock aGuard( maMutex );
+
+ if ( rxRegion.is() )
+ maRegion.Intersect( VCLUnoHelper::GetRegion( rxRegion ) );
+}
+
+void VCLXRegion::excludeRegion( const css::uno::Reference< css::awt::XRegion >& rxRegion )
+{
+ std::scoped_lock aGuard( maMutex );
+
+ if ( rxRegion.is() )
+ maRegion.Exclude( VCLUnoHelper::GetRegion( rxRegion ) );
+}
+
+void VCLXRegion::xOrRegion( const css::uno::Reference< css::awt::XRegion >& rxRegion )
+{
+ std::scoped_lock aGuard( maMutex );
+
+ if ( rxRegion.is() )
+ maRegion.XOr( VCLUnoHelper::GetRegion( rxRegion ) );
+}
+
+css::uno::Sequence< css::awt::Rectangle > VCLXRegion::getRectangles()
+{
+ std::scoped_lock aGuard( maMutex );
+
+ RectangleVector aRectangles;
+ maRegion.GetRegionRectangles(aRectangles);
+
+// sal_uLong nRects = maRegion.GetRectCount();
+ css::uno::Sequence< css::awt::Rectangle > aRects(aRectangles.size());
+ sal_uInt32 a(0);
+
+ for(const auto& rRect : aRectangles)
+ {
+ aRects.getArray()[a++] = AWTRectangle(rRect);
+ }
+
+ //Rectangle aRect;
+ //sal_uInt32 nR = 0;
+ //RegionHandle h = maRegion.BeginEnumRects();
+ //while ( maRegion.GetEnumRects( h, aRect ) )
+ // aRects.getArray()[nR++] = AWTRectangle( aRect );
+ //maRegion.EndEnumRects( h );
+
+ return aRects;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/awt/vclxspinbutton.cxx b/toolkit/source/awt/vclxspinbutton.cxx
new file mode 100644
index 0000000000..cc4747dc20
--- /dev/null
+++ b/toolkit/source/awt/vclxspinbutton.cxx
@@ -0,0 +1,331 @@
+/* -*- 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/vclxspinbutton.hxx>
+#include <helper/property.hxx>
+#include <com/sun/star/awt/ScrollBarOrientation.hpp>
+
+#include <vcl/toolkit/spin.hxx>
+#include <vcl/svapp.hxx>
+#include "vclxwindows_internal.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;
+
+
+ namespace
+ {
+ void lcl_modifyStyle( vcl::Window* _pWindow, WinBits _nStyleBits, bool _bShouldBePresent )
+ {
+ WinBits nStyle = _pWindow->GetStyle();
+ if ( _bShouldBePresent )
+ nStyle |= _nStyleBits;
+ else
+ nStyle &= ~_nStyleBits;
+ _pWindow->SetStyle( nStyle );
+ }
+ }
+
+ VCLXSpinButton::VCLXSpinButton()
+ :maAdjustmentListeners( *this )
+ {
+ }
+
+
+ VCLXSpinButton::~VCLXSpinButton()
+ {
+ }
+
+
+ IMPLEMENT_FORWARD_XINTERFACE2( VCLXSpinButton, VCLXWindow, VCLXSpinButton_Base )
+
+
+ IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXSpinButton, VCLXWindow, VCLXSpinButton_Base )
+
+
+ void SAL_CALL VCLXSpinButton::dispose( )
+ {
+ {
+ SolarMutexGuard aGuard;
+
+ EventObject aDisposeEvent;
+ aDisposeEvent.Source = *this;
+ maAdjustmentListeners.disposeAndClear( aDisposeEvent );
+ }
+
+ VCLXWindow::dispose();
+ }
+
+
+ void SAL_CALL VCLXSpinButton::addAdjustmentListener( const Reference< XAdjustmentListener >& listener )
+ {
+ if ( listener.is() )
+ maAdjustmentListeners.addInterface( listener );
+ }
+
+
+ void SAL_CALL VCLXSpinButton::removeAdjustmentListener( const Reference< XAdjustmentListener >& listener )
+ {
+ if ( listener.is() )
+ maAdjustmentListeners.removeInterface( listener );
+ }
+
+ namespace
+ {
+ typedef void (SpinButton::*SetSpinButtonValue) (tools::Long);
+ typedef tools::Long (SpinButton::*GetSpinButtonValue) () const;
+
+
+ void lcl_setSpinButtonValue(vcl::Window* _pWindow, SetSpinButtonValue _pSetter, sal_Int32 _nValue )
+ {
+ SolarMutexGuard aGuard;
+ SpinButton* pSpinButton = static_cast< SpinButton* >( _pWindow );
+ if ( pSpinButton )
+ (pSpinButton->*_pSetter)( _nValue );
+ }
+
+
+ sal_Int32 lcl_getSpinButtonValue(const vcl::Window* _pWindow, GetSpinButtonValue _pGetter )
+ {
+ SolarMutexGuard aGuard;
+
+ sal_Int32 nValue = 0;
+
+ const SpinButton* pSpinButton = static_cast< const SpinButton* >( _pWindow );
+ if ( pSpinButton )
+ nValue = (pSpinButton->*_pGetter)( );
+ return nValue;
+ }
+ }
+
+
+ void SAL_CALL VCLXSpinButton::setValue( sal_Int32 n )
+ {
+ lcl_setSpinButtonValue( GetWindow(), &SpinButton::SetValue, n );
+ }
+
+
+ void SAL_CALL VCLXSpinButton::setValues( sal_Int32 minValue, sal_Int32 maxValue, sal_Int32 currentValue )
+ {
+ SolarMutexGuard aGuard;
+
+ setMinimum( minValue );
+ setMaximum( maxValue );
+ setValue( currentValue );
+ }
+
+
+ sal_Int32 SAL_CALL VCLXSpinButton::getValue( )
+ {
+ return lcl_getSpinButtonValue( GetWindow(), &SpinButton::GetValue );
+ }
+
+
+ void SAL_CALL VCLXSpinButton::setMinimum( sal_Int32 minValue )
+ {
+ lcl_setSpinButtonValue( GetWindow(), &SpinButton::SetRangeMin, minValue );
+ }
+
+
+ void SAL_CALL VCLXSpinButton::setMaximum( sal_Int32 maxValue )
+ {
+ lcl_setSpinButtonValue( GetWindow(), &SpinButton::SetRangeMax, maxValue );
+ }
+
+
+ sal_Int32 SAL_CALL VCLXSpinButton::getMinimum( )
+ {
+ return lcl_getSpinButtonValue( GetWindow(), &SpinButton::GetRangeMin );
+ }
+
+
+ sal_Int32 SAL_CALL VCLXSpinButton::getMaximum( )
+ {
+ return lcl_getSpinButtonValue( GetWindow(), &SpinButton::GetRangeMax );
+ }
+
+
+ void SAL_CALL VCLXSpinButton::setSpinIncrement( sal_Int32 spinIncrement )
+ {
+ lcl_setSpinButtonValue( GetWindow(), &SpinButton::SetValueStep, spinIncrement );
+ }
+
+
+ sal_Int32 SAL_CALL VCLXSpinButton::getSpinIncrement( )
+ {
+ return lcl_getSpinButtonValue( GetWindow(), &SpinButton::GetValueStep );
+ }
+
+
+ void SAL_CALL VCLXSpinButton::setOrientation( sal_Int32 orientation )
+ {
+ SolarMutexGuard aGuard;
+
+ lcl_modifyStyle( GetWindow(), WB_HSCROLL, orientation == ScrollBarOrientation::HORIZONTAL );
+ }
+
+
+ sal_Int32 SAL_CALL VCLXSpinButton::getOrientation( )
+ {
+ return ( 0 != ( GetWindow()->GetStyle() & WB_HSCROLL ) )
+ ? ScrollBarOrientation::HORIZONTAL
+ : ScrollBarOrientation::VERTICAL;
+ }
+
+
+ void VCLXSpinButton::ProcessWindowEvent( const VclWindowEvent& _rVclWindowEvent )
+ {
+ SolarMutexClearableGuard aGuard;
+ Reference< XSpinValue > xKeepAlive( this );
+ VclPtr<SpinButton> pSpinButton = GetAs<SpinButton>();
+ if ( !pSpinButton )
+ return;
+
+ switch ( _rVclWindowEvent.GetId() )
+ {
+ case VclEventId::SpinbuttonUp:
+ case VclEventId::SpinbuttonDown:
+ if ( maAdjustmentListeners.getLength() )
+ {
+ AdjustmentEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.Value = pSpinButton->GetValue();
+
+ aGuard.clear();
+ maAdjustmentListeners.adjustmentValueChanged( aEvent );
+ }
+ break;
+
+ default:
+ xKeepAlive.clear();
+ aGuard.clear();
+ VCLXWindow::ProcessWindowEvent( _rVclWindowEvent );
+ break;
+ }
+ }
+
+
+ void SAL_CALL VCLXSpinButton::setProperty( const OUString& PropertyName, const Any& Value )
+ {
+ SolarMutexGuard aGuard;
+
+ sal_Int32 nValue = 0;
+ bool bIsLongValue = ( Value >>= nValue );
+
+ if ( !GetWindow() )
+ return;
+
+ sal_uInt16 nPropertyId = GetPropertyId( PropertyName );
+ switch ( nPropertyId )
+ {
+ case BASEPROPERTY_BACKGROUNDCOLOR:
+ // the default implementation of the base class doesn't work here, since our
+ // interpretation for this property is slightly different
+ setButtonLikeFaceColor( GetWindow(), Value);
+ break;
+
+ case BASEPROPERTY_SPINVALUE:
+ if ( bIsLongValue )
+ setValue( nValue );
+ break;
+
+ case BASEPROPERTY_SPINVALUE_MIN:
+ if ( bIsLongValue )
+ setMinimum( nValue );
+ break;
+
+ case BASEPROPERTY_SPINVALUE_MAX:
+ if ( bIsLongValue )
+ setMaximum( nValue );
+ break;
+
+ case BASEPROPERTY_SPININCREMENT:
+ if ( bIsLongValue )
+ setSpinIncrement( nValue );
+ break;
+
+ case BASEPROPERTY_ORIENTATION:
+ if ( bIsLongValue )
+ lcl_modifyStyle( GetWindow(), WB_HSCROLL, nValue == ScrollBarOrientation::HORIZONTAL );
+ break;
+
+ default:
+ VCLXWindow::setProperty( PropertyName, Value );
+ }
+ }
+
+
+ Any SAL_CALL VCLXSpinButton::getProperty( const OUString& PropertyName )
+ {
+ SolarMutexGuard aGuard;
+
+ Any aReturn;
+
+ if ( GetWindow() )
+ {
+ sal_uInt16 nPropertyId = GetPropertyId( PropertyName );
+ switch ( nPropertyId )
+ {
+ case BASEPROPERTY_BACKGROUNDCOLOR:
+ // the default implementation of the base class doesn't work here, since our
+ // interpretation for this property is slightly different
+ aReturn = getButtonLikeFaceColor( GetWindow() );
+ break;
+
+ case BASEPROPERTY_SPINVALUE:
+ aReturn <<= getValue( );
+ break;
+
+ case BASEPROPERTY_SPINVALUE_MIN:
+ aReturn <<= getMinimum( );
+ break;
+
+ case BASEPROPERTY_SPINVALUE_MAX:
+ aReturn <<= getMaximum( );
+ break;
+
+ case BASEPROPERTY_SPININCREMENT:
+ aReturn <<= getSpinIncrement( );
+ break;
+
+ case BASEPROPERTY_ORIENTATION:
+ aReturn <<= static_cast<sal_Int32>( ( 0 != ( GetWindow()->GetStyle() & WB_HSCROLL ) )
+ ? ScrollBarOrientation::HORIZONTAL
+ : ScrollBarOrientation::VERTICAL
+ );
+ break;
+
+ default:
+ aReturn = VCLXWindow::getProperty( PropertyName );
+ }
+ }
+ return aReturn;
+ }
+
+
+} // namespace toolkit
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/awt/vclxsystemdependentwindow.cxx b/toolkit/source/awt/vclxsystemdependentwindow.cxx
new file mode 100644
index 0000000000..2ba59470a8
--- /dev/null
+++ b/toolkit/source/awt/vclxsystemdependentwindow.cxx
@@ -0,0 +1,90 @@
+/* -*- 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/lang/SystemDependent.hpp>
+
+#if defined UNX && ! defined MACOSX
+#include <com/sun/star/awt/SystemDependentXWindow.hpp>
+#endif
+
+#include <awt/vclxsystemdependentwindow.hxx>
+
+#ifdef MACOSX
+#include <premac.h>
+#include <Cocoa/Cocoa.h>
+#include <postmac.h>
+#endif
+
+#include <vcl/svapp.hxx>
+#include <vcl/syschild.hxx>
+#include <vcl/sysdata.hxx>
+
+
+
+VCLXSystemDependentWindow::VCLXSystemDependentWindow()
+{
+}
+
+VCLXSystemDependentWindow::~VCLXSystemDependentWindow()
+{
+}
+
+css::uno::Any VCLXSystemDependentWindow::getWindowHandle( const css::uno::Sequence< sal_Int8 >& /*ProcessId*/, sal_Int16 SystemType )
+{
+ SolarMutexGuard aGuard;
+
+ // TODO, check the process id
+ css::uno::Any aRet;
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ const SystemEnvData* pSysData = static_cast<SystemChildWindow *>(pWindow.get())->GetSystemData();
+ if( pSysData )
+ {
+#if defined(_WIN32)
+ if( SystemType == css::lang::SystemDependent::SYSTEM_WIN32 )
+ {
+ aRet <<= reinterpret_cast<sal_IntPtr>(pSysData->hWnd);
+ }
+#elif defined(MACOSX)
+ if( SystemType == css::lang::SystemDependent::SYSTEM_MAC )
+ {
+ aRet <<= reinterpret_cast<sal_IntPtr>(pSysData->mpNSView);
+ }
+#elif defined(ANDROID)
+ // Nothing
+ (void) SystemType;
+#elif defined(IOS)
+ // Nothing
+ (void) SystemType;
+#elif defined(UNX)
+ if( SystemType == css::lang::SystemDependent::SYSTEM_XWINDOW )
+ {
+ css::awt::SystemDependentXWindow aSD;
+ aSD.DisplayPointer = sal::static_int_cast< sal_Int64 >(reinterpret_cast< sal_IntPtr >(pSysData->pDisplay));
+ aSD.WindowHandle = pSysData->GetWindowHandle(pWindow->ImplGetFrame());
+ aRet <<= aSD;
+ }
+#endif
+ }
+ }
+ return aRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/awt/vclxtabpagecontainer.cxx b/toolkit/source/awt/vclxtabpagecontainer.cxx
new file mode 100644
index 0000000000..afd3d843b7
--- /dev/null
+++ b/toolkit/source/awt/vclxtabpagecontainer.cxx
@@ -0,0 +1,233 @@
+/* -*- 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/vclxtabpagecontainer.hxx>
+#include <com/sun/star/awt/tab/XTabPageModel.hpp>
+#include <com/sun/star/awt/XControl.hpp>
+#include <o3tl/safeint.hxx>
+#include <sal/log.hxx>
+#include <helper/property.hxx>
+#include <vcl/image.hxx>
+#include <vcl/tabpage.hxx>
+#include <vcl/tabctrl.hxx>
+#include <vcl/svapp.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+
+#include <helper/tkresmgr.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;
+
+
+void VCLXTabPageContainer::GetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ VCLXWindow::ImplGetPropertyIds( rIds );
+}
+
+VCLXTabPageContainer::VCLXTabPageContainer() :
+ m_aTabPageListeners( *this )
+{
+}
+
+VCLXTabPageContainer::~VCLXTabPageContainer()
+{
+ SAL_INFO("toolkit", __FUNCTION__);
+}
+
+void SAL_CALL VCLXTabPageContainer::draw( sal_Int32 nX, sal_Int32 nY )
+{
+ SolarMutexGuard aGuard;
+ VclPtr<TabControl> pTabControl = GetAs<TabControl>();
+ if ( pTabControl )
+ {
+ TabPage *pTabPage = pTabControl->GetTabPage( sal::static_int_cast< sal_uInt16 >( pTabControl->GetCurPageId( ) ) );
+ OutputDevice* pDev = VCLUnoHelper::GetOutputDevice( getGraphics() );
+ if (pTabPage && pDev)
+ {
+ ::Point aPos( nX, nY );
+ aPos = pDev->PixelToLogic( aPos );
+ pTabPage->Draw( pDev, aPos, SystemTextColorFlags::NONE );
+ }
+ }
+
+ VCLXWindow::draw( nX, nY );
+}
+
+void SAL_CALL VCLXTabPageContainer::setProperty(const OUString& PropertyName, const Any& Value )
+{
+ SolarMutexGuard aGuard;
+ VclPtr<TabControl> pTabPage = GetAs<TabControl>();
+ if ( pTabPage )
+ VCLXWindow::setProperty( PropertyName, Value );
+}
+
+::sal_Int16 SAL_CALL VCLXTabPageContainer::getActiveTabPageID()
+{
+ VclPtr<TabControl> pTabCtrl = GetAs<TabControl>();
+ return pTabCtrl ? pTabCtrl->GetCurPageId( ) : 0;
+}
+
+void SAL_CALL VCLXTabPageContainer::setActiveTabPageID( ::sal_Int16 _activetabpageid )
+{
+ VclPtr<TabControl> pTabCtrl = GetAs<TabControl>();
+ if ( pTabCtrl )
+ pTabCtrl->SelectTabPage(_activetabpageid);
+}
+
+::sal_Int16 SAL_CALL VCLXTabPageContainer::getTabPageCount( )
+{
+ VclPtr<TabControl> pTabCtrl = GetAs<TabControl>();
+ return pTabCtrl ? pTabCtrl->GetPageCount() : 0;
+}
+
+sal_Bool SAL_CALL VCLXTabPageContainer::isTabPageActive( ::sal_Int16 tabPageIndex )
+{
+ return (getActiveTabPageID() == tabPageIndex);
+}
+
+Reference< css::awt::tab::XTabPage > SAL_CALL VCLXTabPageContainer::getTabPage( ::sal_Int16 tabPageIndex )
+{
+ return (tabPageIndex >= 0 && o3tl::make_unsigned(tabPageIndex) < m_aTabPages.size()) ? m_aTabPages[tabPageIndex] : nullptr;
+}
+
+Reference< css::awt::tab::XTabPage > SAL_CALL VCLXTabPageContainer::getTabPageByID( ::sal_Int16 tabPageID )
+{
+ SolarMutexGuard aGuard;
+ Reference< css::awt::tab::XTabPage > xTabPage;
+ for(const auto& rTabPage : m_aTabPages)
+ {
+ Reference< awt::XControl > xControl(rTabPage,UNO_QUERY );
+ Reference< awt::tab::XTabPageModel > xP( xControl->getModel(), UNO_QUERY );
+ if ( tabPageID == xP->getTabPageID() )
+ {
+ xTabPage = rTabPage;
+ break;
+ }
+ }
+ return xTabPage;
+}
+
+void SAL_CALL VCLXTabPageContainer::addTabPageContainerListener( const Reference< css::awt::tab::XTabPageContainerListener >& listener )
+{
+ m_aTabPageListeners.addInterface( listener );
+}
+
+void SAL_CALL VCLXTabPageContainer::removeTabPageContainerListener( const Reference< css::awt::tab::XTabPageContainerListener >& listener )
+{
+ m_aTabPageListeners.removeInterface( listener );
+}
+
+void VCLXTabPageContainer::ProcessWindowEvent( const VclWindowEvent& _rVclWindowEvent )
+{
+ SolarMutexClearableGuard aGuard;
+ VclPtr<TabControl> pTabControl = GetAs<TabControl>();
+ if ( !pTabControl )
+ return;
+
+ switch ( _rVclWindowEvent.GetId() )
+ {
+ case VclEventId::TabpageActivate:
+ {
+ sal_uLong page = reinterpret_cast<sal_uLong>(_rVclWindowEvent.GetData());
+ awt::tab::TabPageActivatedEvent aEvent(nullptr,page);
+ m_aTabPageListeners.tabPageActivated(aEvent);
+ break;
+ }
+ default:
+ aGuard.clear();
+ VCLXWindow::ProcessWindowEvent( _rVclWindowEvent );
+ break;
+ }
+}
+void SAL_CALL VCLXTabPageContainer::disposing( const css::lang::EventObject& /*Source*/ )
+{
+}
+void SAL_CALL VCLXTabPageContainer::elementInserted( const css::container::ContainerEvent& Event )
+{
+ SolarMutexGuard aGuard;
+ VclPtr<TabControl> pTabCtrl = GetAs<TabControl>();
+ Reference< css::awt::tab::XTabPage > xTabPage(Event.Element,uno::UNO_QUERY);
+ if ( !pTabCtrl || !xTabPage.is() )
+ return;
+
+ Reference< awt::XControl > xControl(xTabPage,UNO_QUERY );
+ Reference< awt::tab::XTabPageModel > xP( xControl->getModel(), UNO_QUERY );
+ sal_Int16 nPageID = xP->getTabPageID();
+
+ if (!xControl->getPeer().is())
+ throw RuntimeException("No peer for tabpage container!");
+ VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xControl->getPeer());
+ TabPage* pPage = static_cast<TabPage*>(pWindow.get());
+ pTabCtrl->InsertPage(nPageID,pPage->GetText());
+
+ pPage->Hide();
+ pTabCtrl->SetTabPage(nPageID,pPage);
+ pTabCtrl->SetHelpText(nPageID,xP->getToolTip());
+ pTabCtrl->SetPageImage(nPageID,TkResMgr::getImageFromURL(xP->getImageURL()));
+ pTabCtrl->SelectTabPage(nPageID);
+ pTabCtrl->SetPageEnabled(nPageID,xP->getEnabled());
+ m_aTabPages.push_back(xTabPage);
+
+}
+void SAL_CALL VCLXTabPageContainer::elementRemoved( const css::container::ContainerEvent& Event )
+{
+ SolarMutexGuard aGuard;
+ VclPtr<TabControl> pTabCtrl = GetAs<TabControl>();
+ Reference< css::awt::tab::XTabPage > xTabPage(Event.Element,uno::UNO_QUERY);
+ if ( pTabCtrl && xTabPage.is() )
+ {
+ Reference< awt::XControl > xControl(xTabPage,UNO_QUERY );
+ Reference< awt::tab::XTabPageModel > xP( xControl->getModel(), UNO_QUERY );
+ pTabCtrl->RemovePage(xP->getTabPageID());
+ std::erase(m_aTabPages,xTabPage);
+ }
+}
+void SAL_CALL VCLXTabPageContainer::elementReplaced( const css::container::ContainerEvent& /*Event*/ )
+{
+}
+
+void VCLXTabPageContainer::propertiesChange(const::css::uno::Sequence<PropertyChangeEvent>& rEvents)
+{
+ SolarMutexGuard aGuard;
+ VclPtr<TabControl> pTabCtrl = GetAs<TabControl>();
+ if (!pTabCtrl)
+ return;
+
+ for (const beans::PropertyChangeEvent& rEvent : rEvents) {
+ // handle property changes for tab pages
+ Reference< css::awt::tab::XTabPageModel > xTabPageModel(rEvent.Source, uno::UNO_QUERY);
+ if (!xTabPageModel.is())
+ continue;
+
+ const sal_Int16 nId = xTabPageModel->getTabPageID();
+ if (rEvent.PropertyName == GetPropertyName(BASEPROPERTY_ENABLED)) {
+ pTabCtrl->SetPageEnabled(nId, xTabPageModel->getEnabled());
+ } else if (rEvent.PropertyName == GetPropertyName(BASEPROPERTY_TITLE)) {
+ pTabCtrl->SetPageText(nId, xTabPageModel->getTitle());
+ } else if (rEvent.PropertyName == GetPropertyName(BASEPROPERTY_IMAGEURL)) {
+ pTabCtrl->SetPageImage(nId, TkResMgr::getImageFromURL(xTabPageModel->getImageURL()));
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/awt/vclxtoolkit.cxx b/toolkit/source/awt/vclxtoolkit.cxx
new file mode 100644
index 0000000000..fc6b7b9df8
--- /dev/null
+++ b/toolkit/source/awt/vclxtoolkit.cxx
@@ -0,0 +1,2624 @@
+/* -*- 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 <string_view>
+#include <thread>
+
+#ifdef _WIN32
+#include <prewin.h>
+#include <postwin.h>
+#endif
+#include <config_features.h>
+#include <com/sun/star/awt/WindowAttribute.hpp>
+#include <com/sun/star/awt/VclWindowPeerAttribute.hpp>
+#include <com/sun/star/awt/WindowClass.hpp>
+#include <com/sun/star/awt/MessageBoxButtons.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/SystemDependent.hpp>
+#include <com/sun/star/awt/FocusEvent.hpp>
+#include <com/sun/star/awt/KeyEvent.hpp>
+#include <com/sun/star/awt/KeyModifier.hpp>
+#include <com/sun/star/lang/EventObject.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/uno/XInterface.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/beans/XPropertyChangeListener.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/datatransfer/clipboard/SystemClipboard.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/awt/XToolkitExperimental.hpp>
+#include <com/sun/star/awt/XToolkitRobot.hpp>
+
+#include <cppuhelper/basemutex.hxx>
+#include <cppuhelper/bootstrap.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <o3tl/safeint.hxx>
+#include <osl/conditn.hxx>
+#include <osl/module.h>
+#include <osl/thread.hxx>
+#include <osl/mutex.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/process.h>
+#include <sal/log.hxx>
+#include <tools/link.hxx>
+#include <vcl/idletask.hxx>
+#include <vcl/wintypes.hxx>
+
+#ifdef MACOSX
+#include <premac.h>
+#include <Cocoa/Cocoa.h>
+#include <postmac.h>
+#endif
+
+#include <utility>
+#include <vcl/sysdata.hxx>
+#include <vcl/textrectinfo.hxx>
+#include <vcl/toolkit/vclmedit.hxx>
+
+#include <toolkit/awt/vclxwindows.hxx>
+#include <awt/vclxwindows.hxx>
+#include <awt/vclxsystemdependentwindow.hxx>
+#include <awt/vclxregion.hxx>
+#include <awt/vclxtabpagecontainer.hxx>
+#include <awt/vclxtopwindow.hxx>
+
+#include <awt/animatedimagespeer.hxx>
+#include <toolkit/awt/vclxwindow.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <helper/property.hxx>
+
+#include <toolkit/helper/convert.hxx>
+#include <controls/filectrl.hxx>
+#include <controls/svmedit.hxx>
+#include <controls/table/tablecontrol.hxx>
+#include <controls/treecontrolpeer.hxx>
+#include <vcl/toolkit/button.hxx>
+#include <vcl/toolkit/calendar.hxx>
+#include <vcl/toolkit/combobox.hxx>
+#include <vcl/ctrl.hxx>
+#include <vcl/toolkit/dialog.hxx>
+#include <vcl/dockingarea.hxx>
+#include <vcl/dockwin.hxx>
+#include <vcl/toolkit/edit.hxx>
+#include <vcl/event.hxx>
+#include <vcl/toolkit/field.hxx>
+#include <vcl/toolkit/fixed.hxx>
+#include <vcl/toolkit/fixedhyper.hxx>
+#include <vcl/toolkit/floatwin.hxx>
+#include <vcl/toolkit/fmtfield.hxx>
+#include <vcl/toolkit/prgsbar.hxx>
+#include <vcl/scheduler.hxx>
+#include <vcl/toolkit/lstbox.hxx>
+#include <vcl/toolkit/longcurr.hxx>
+#include <vcl/toolkit/menubtn.hxx>
+#include <vcl/stdtext.hxx>
+#include <vcl/toolkit/scrbar.hxx>
+#include <vcl/split.hxx>
+#include <vcl/splitwin.hxx>
+#include <vcl/status.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/syschild.hxx>
+#include <vcl/tabctrl.hxx>
+#include <vcl/tabpage.hxx>
+#include <vcl/toolbox.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/window.hxx>
+#include <vcl/wrkwin.hxx>
+#include <vcl/toolkit/group.hxx>
+#include <vcl/toolkit/imgctrl.hxx>
+#include <vcl/toolkit/morebtn.hxx>
+#include <vcl/toolkit/roadmap.hxx>
+#include <vcl/toolkit/spin.hxx>
+#include <vcl/toolkit/tabdlg.hxx>
+#include <vcl/toolkit/throbber.hxx>
+#if HAVE_FEATURE_OPENGL
+#include <vcl/opengl/OpenGLWrapper.hxx>
+#endif
+#include <awt/vclxspinbutton.hxx>
+#include <tools/debug.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <comphelper/interfacecontainer3.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/profilezone.hxx>
+
+#include <helper/msgbox.hxx>
+#include <helper/scrollabledialog.hxx>
+#include <helper/unowrapper.hxx>
+
+#if defined(_WIN32)
+#define SYSTEM_DEPENDENT_TYPE css::lang::SystemDependent::SYSTEM_WIN32
+#elif defined(MACOSX)
+#define SYSTEM_DEPENDENT_TYPE css::lang::SystemDependent::SYSTEM_MAC
+#elif defined(UNX)
+#define SYSTEM_DEPENDENT_TYPE css::lang::SystemDependent::SYSTEM_XWINDOW
+#endif
+
+void MessBox::ImplInitButtons()
+{
+ ButtonDialogFlags nOKFlags = ButtonDialogFlags::OK;
+ ButtonDialogFlags nCancelFlags = ButtonDialogFlags::Cancel;
+ ButtonDialogFlags nRetryFlags = ButtonDialogFlags::NONE;
+ ButtonDialogFlags nYesFlags = ButtonDialogFlags::NONE;
+ ButtonDialogFlags nNoFlags = ButtonDialogFlags::NONE;
+
+ if ( mnMessBoxStyle & MessBoxStyle::OkCancel )
+ {
+ if ( mnMessBoxStyle & MessBoxStyle::DefaultCancel )
+ nCancelFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
+ else // MessBoxStyle::DefaultOk
+ nOKFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
+
+ AddButton( StandardButtonType::OK, RET_OK, nOKFlags );
+ AddButton( StandardButtonType::Cancel, RET_CANCEL, nCancelFlags );
+ }
+ else if ( mnMessBoxStyle & MessBoxStyle::YesNo )
+ {
+ if ( mnMessBoxStyle & MessBoxStyle::DefaultYes )
+ nYesFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
+ else // MessBoxStyle::DefaultNo
+ nNoFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
+ nNoFlags |= ButtonDialogFlags::Cancel;
+
+ AddButton( StandardButtonType::Yes, RET_YES, nYesFlags );
+ AddButton( StandardButtonType::No, RET_NO, nNoFlags );
+ }
+ else if ( mnMessBoxStyle & MessBoxStyle::YesNoCancel )
+ {
+ if ( mnMessBoxStyle & MessBoxStyle::DefaultYes )
+ nYesFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
+ else if ( mnMessBoxStyle & MessBoxStyle::DefaultNo )
+ nNoFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
+ else
+ nCancelFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
+
+ AddButton( StandardButtonType::Yes, RET_YES, nYesFlags );
+ AddButton( StandardButtonType::No, RET_NO, nNoFlags );
+ AddButton( StandardButtonType::Cancel, RET_CANCEL, nCancelFlags );
+ }
+ else if ( mnMessBoxStyle & MessBoxStyle::RetryCancel )
+ {
+ if ( mnMessBoxStyle & MessBoxStyle::DefaultCancel )
+ nCancelFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
+ else // MessBoxStyle::DefaultRetry
+ nRetryFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
+
+ AddButton( StandardButtonType::Retry, RET_RETRY, nRetryFlags );
+ AddButton( StandardButtonType::Cancel, RET_CANCEL, nCancelFlags );
+ }
+ else if ( mnMessBoxStyle & MessBoxStyle::AbortRetryIgnore )
+ {
+ ButtonDialogFlags nAbortFlags = ButtonDialogFlags::NONE;
+ ButtonDialogFlags nIgnoreFlags = ButtonDialogFlags::NONE;
+
+ if ( mnMessBoxStyle & MessBoxStyle::DefaultCancel )
+ nAbortFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
+ else if ( mnMessBoxStyle & MessBoxStyle::DefaultRetry )
+ nRetryFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
+ else if ( mnMessBoxStyle & MessBoxStyle::DefaultIgnore )
+ nIgnoreFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
+
+ AddButton( StandardButtonType::Abort, RET_CANCEL, nAbortFlags );
+ AddButton( StandardButtonType::Retry, RET_RETRY, nRetryFlags );
+ AddButton( StandardButtonType::Ignore, RET_IGNORE, nIgnoreFlags );
+ }
+ else if ( mnMessBoxStyle & MessBoxStyle::Ok )
+ {
+ nOKFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
+
+ AddButton( StandardButtonType::OK, RET_OK, nOKFlags );
+ }
+}
+
+MessBox::MessBox(vcl::Window* pParent, MessBoxStyle nMessBoxStyle, WinBits nWinBits,
+ const OUString& rTitle, OUString aMessage) :
+ ButtonDialog( WindowType::MESSBOX ),
+ mbHelpBtn( false ),
+ mnMessBoxStyle( nMessBoxStyle ),
+ maMessText(std::move( aMessage ))
+{
+ ImplLOKNotifier(pParent);
+ ImplInitDialog(pParent, nWinBits | WB_MOVEABLE | WB_HORZ | WB_CENTER);
+ ImplInitButtons();
+
+ if ( !rTitle.isEmpty() )
+ SetText( rTitle );
+}
+
+MessBox::~MessBox()
+{
+ disposeOnce();
+}
+
+void MessBox::dispose()
+{
+ mpVCLMultiLineEdit.disposeAndClear();
+ mpFixedImage.disposeAndClear();
+ ButtonDialog::dispose();
+}
+
+void MessBox::ImplPosControls()
+{
+ if ( !GetHelpId().isEmpty() )
+ {
+ if ( !mbHelpBtn )
+ {
+ AddButton( StandardButtonType::Help, RET_HELP, ButtonDialogFlags::Help, 3 );
+ mbHelpBtn = true;
+ }
+ }
+ else
+ {
+ if ( mbHelpBtn )
+ {
+ RemoveButton( RET_HELP );
+ mbHelpBtn = false;
+ }
+ }
+
+ TextRectInfo aTextInfo;
+ tools::Rectangle aRect( 0, 0, 30000, 30000 );
+ tools::Rectangle aFormatRect;
+ Point aTextPos( IMPL_DIALOG_OFFSET, IMPL_DIALOG_OFFSET+IMPL_MSGBOX_OFFSET_EXTRA_Y );
+ Size aImageSize;
+ Size aPageSize;
+ Size aMEditSize;
+ tools::Long nTitleWidth;
+ tools::Long nButtonSize = ImplGetButtonSize();
+ tools::Long nMaxLineWidth;
+ tools::Long nWidth;
+ WinBits nWinStyle = WB_LEFT | WB_NOLABEL;
+ DrawTextFlags nTextStyle = DrawTextFlags::MultiLine | DrawTextFlags::Top | DrawTextFlags::Left;
+
+ mpVCLMultiLineEdit.disposeAndClear();
+ mpFixedImage.disposeAndClear();
+
+ // Clean up message text with tabs
+ OUString aMessText(maMessText.replaceAll("\t", " "));
+
+ //If window too small, we make dialog box be wider
+ tools::Long nMaxWidth = 630 * GetDPIScaleFactor();
+
+ // MessagBox should be at least as wide as to see the title
+ // Extra-Width for Close button, because Close button is set after this call
+ nTitleWidth = CalcTitleWidth();
+
+ nMaxWidth -= (IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_X*2);
+
+ // for an image, get its size, create a suitable control and position it
+ aImageSize = maImage.GetSizePixel();
+ if ( aImageSize.Width() )
+ {
+ aImageSize.AdjustWidth(4 );
+ aImageSize.AdjustHeight(4 );
+ aTextPos.AdjustX(aImageSize.Width()+IMPL_SEP_MSGBOX_IMAGE );
+ mpFixedImage = VclPtr<FixedImage>::Create( this );
+ mpFixedImage->SetPosSizePixel( Point( IMPL_DIALOG_OFFSET-2+IMPL_MSGBOX_OFFSET_EXTRA_X,
+ IMPL_DIALOG_OFFSET-2+IMPL_MSGBOX_OFFSET_EXTRA_Y ),
+ aImageSize );
+ mpFixedImage->SetImage( maImage );
+ mpFixedImage->Show();
+ nMaxWidth -= aImageSize.Width()+IMPL_SEP_MSGBOX_IMAGE;
+ }
+ else
+ aTextPos.AdjustX(IMPL_MSGBOX_OFFSET_EXTRA_X );
+
+ // Determine maximum line length without wordbreak
+ aFormatRect = GetTextRect( aRect, aMessText, nTextStyle, &aTextInfo );
+ nMaxLineWidth = aFormatRect.GetWidth();
+ nTextStyle |= DrawTextFlags::WordBreak;
+
+ // Determine the width for text formatting
+ if ( nMaxLineWidth > 450 )
+ nWidth = 450;
+ else if ( nMaxLineWidth > 300 )
+ nWidth = nMaxLineWidth+5;
+ else
+ nWidth = 300;
+
+ nWidth *= GetDPIScaleFactor();
+
+ if ( nButtonSize > nWidth )
+ nWidth = nButtonSize-(aTextPos.X()-IMPL_DIALOG_OFFSET);
+ if ( nWidth > nMaxWidth )
+ nWidth = nMaxWidth;
+
+ aRect.SetRight( nWidth );
+ aFormatRect = GetTextRect( aRect, aMessText, nTextStyle, &aTextInfo );
+ if ( aTextInfo.GetMaxLineWidth() > nWidth )
+ {
+ nWidth = aTextInfo.GetMaxLineWidth()+8;
+ aRect.SetRight( nWidth );
+ aFormatRect = GetTextRect( aRect, aMessText, nTextStyle, &aTextInfo );
+ }
+
+ // get Style for VCLMultiLineEdit
+ aMEditSize.setWidth( aTextInfo.GetMaxLineWidth()+1 );
+ aMEditSize.setHeight( aFormatRect.GetHeight() );
+ aPageSize.setWidth( aImageSize.Width() );
+ if ( aMEditSize.Height() < aImageSize.Height() )
+ {
+ nWinStyle |= WB_VCENTER;
+ aPageSize.setHeight( aImageSize.Height() );
+ aMEditSize.setHeight( aImageSize.Height() );
+ }
+ else
+ {
+ nWinStyle |= WB_TOP;
+ aPageSize.setHeight( aMEditSize.Height() );
+ }
+ if ( aImageSize.Width() )
+ aPageSize.AdjustWidth(IMPL_SEP_MSGBOX_IMAGE );
+ aPageSize.AdjustWidth((IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_X*2) );
+ aPageSize.AdjustWidth(aMEditSize.Width()+1 );
+ aPageSize.AdjustHeight((IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_Y*2) );
+
+ if ( aPageSize.Width() < IMPL_MINSIZE_MSGBOX_WIDTH )
+ aPageSize.setWidth( IMPL_MINSIZE_MSGBOX_WIDTH );
+ if ( aPageSize.Width() < nTitleWidth )
+ aPageSize.setWidth( nTitleWidth );
+
+ mpVCLMultiLineEdit = VclPtr<VclMultiLineEdit>::Create( this, nWinStyle );
+ mpVCLMultiLineEdit->SetText( aMessText );
+ mpVCLMultiLineEdit->SetPosSizePixel( aTextPos, aMEditSize );
+ mpVCLMultiLineEdit->Show();
+ mpVCLMultiLineEdit->SetPaintTransparent(true);
+ mpVCLMultiLineEdit->EnableCursor(false);
+ SetPageSizePixel( aPageSize );
+}
+
+void MessBox::StateChanged( StateChangedType nType )
+{
+ if ( nType == StateChangedType::InitShow )
+ {
+ ImplPosControls();
+ }
+ ButtonDialog::StateChanged( nType );
+}
+
+Size MessBox::GetOptimalSize() const
+{
+ // FIXME: base me on the font size ?
+ return Size( 250, 100 );
+}
+
+
+namespace {
+
+class Pause : public Idle
+{
+public:
+ explicit Pause(sal_Int32 nPauseMilliseconds) :
+ Idle("pause"),
+ m_nPauseMilliseconds(nPauseMilliseconds)
+ {
+ SetPriority(TaskPriority::HIGHEST);
+ Start();
+ }
+
+ virtual void Invoke() override
+ {
+ SolarMutexGuard aSolarGuard;
+ std::this_thread::sleep_for(std::chrono::milliseconds(m_nPauseMilliseconds));
+ Stop();
+ delete this;
+ }
+
+ sal_Int32 m_nPauseMilliseconds;
+};
+
+class VCLXToolkit : public cppu::BaseMutex,
+ public cppu::WeakComponentImplHelper<
+ css::awt::XToolkitExperimental,
+ css::awt::XToolkitRobot,
+ css::lang::XServiceInfo >
+{
+ css::uno::Reference< css::datatransfer::clipboard::XClipboard > mxClipboard;
+ css::uno::Reference< css::datatransfer::clipboard::XClipboard > mxSelection;
+
+ ::comphelper::OInterfaceContainerHelper3<css::awt::XTopWindowListener> m_aTopWindowListeners;
+ ::comphelper::OInterfaceContainerHelper3<css::awt::XKeyHandler> m_aKeyHandlers;
+ ::comphelper::OInterfaceContainerHelper3<css::awt::XFocusListener> m_aFocusListeners;
+ ::Link<VclSimpleEvent&,void> m_aEventListenerLink;
+ ::Link<VclWindowEvent&,bool> m_aKeyListenerLink;
+ bool m_bEventListener;
+ bool m_bKeyListener;
+
+ DECL_LINK(eventListenerHandler, ::VclSimpleEvent&, void);
+
+ DECL_LINK(keyListenerHandler, ::VclWindowEvent&, bool);
+
+ void callTopWindowListeners(
+ ::VclSimpleEvent const * pEvent,
+ void (SAL_CALL css::awt::XTopWindowListener::* pFn)(
+ css::lang::EventObject const &));
+
+ bool callKeyHandlers(::VclSimpleEvent const * pEvent, bool bPressed);
+
+ void callFocusListeners(::VclSimpleEvent const * pEvent, bool bGained);
+
+protected:
+ ::osl::Mutex& GetMutex() { return m_aMutex; }
+
+ virtual void SAL_CALL disposing() override;
+
+ static vcl::Window* ImplCreateWindow( rtl::Reference<VCLXWindow>* ppNewComp, const css::awt::WindowDescriptor& rDescriptor, vcl::Window* pParent,
+ WinBits nWinBits, MessBoxStyle nMessBoxStyle );
+ css::uno::Reference< css::awt::XWindowPeer > ImplCreateWindow( const css::awt::WindowDescriptor& Descriptor,
+ MessBoxStyle nForceMessBoxStyle );
+
+public:
+
+ VCLXToolkit();
+
+ // css::awt::XToolkitExperimental
+ virtual void SAL_CALL processEventsToIdle() override;
+
+ virtual sal_Int64 SAL_CALL getOpenGLBufferSwapCounter() override;
+
+ virtual void SAL_CALL setDeterministicScheduling(sal_Bool bDeterministicMode) override;
+
+ virtual void SAL_CALL pause(sal_Int32 nMilliseconds) override;
+
+ virtual void SAL_CALL startRecording() override;
+
+ virtual void SAL_CALL stopRecording() override;
+
+ css::uno::Sequence< OUString > SAL_CALL getRecordingAndClear() override;
+
+ virtual void SAL_CALL waitUntilAllIdlesDispatched() override;
+
+ // css::awt::XToolkit
+ css::uno::Reference< css::awt::XWindowPeer > SAL_CALL getDesktopWindow( ) override;
+ css::awt::Rectangle SAL_CALL getWorkArea( ) override;
+ css::uno::Reference< css::awt::XWindowPeer > SAL_CALL createWindow( const css::awt::WindowDescriptor& Descriptor ) override;
+ css::uno::Sequence< css::uno::Reference< css::awt::XWindowPeer > > SAL_CALL createWindows( const css::uno::Sequence< css::awt::WindowDescriptor >& Descriptors ) override;
+ css::uno::Reference< css::awt::XDevice > SAL_CALL createScreenCompatibleDevice( sal_Int32 Width, sal_Int32 Height ) override;
+ css::uno::Reference< css::awt::XRegion > SAL_CALL createRegion( ) override;
+
+ // css::awt::XSystemChildFactory
+ css::uno::Reference< css::awt::XWindowPeer > SAL_CALL createSystemChild( const css::uno::Any& Parent, const css::uno::Sequence< sal_Int8 >& ProcessId, sal_Int16 SystemType ) override;
+
+ // css::awt::XMessageBoxFactory
+ virtual css::uno::Reference< css::awt::XMessageBox > SAL_CALL createMessageBox( const css::uno::Reference< css::awt::XWindowPeer >& aParent, css::awt::MessageBoxType eType, ::sal_Int32 aButtons, const OUString& aTitle, const OUString& aMessage ) override;
+
+ // css::awt::XDataTransfer
+ css::uno::Reference< css::datatransfer::dnd::XDragGestureRecognizer > SAL_CALL getDragGestureRecognizer( const css::uno::Reference< css::awt::XWindow >& window ) override;
+ css::uno::Reference< css::datatransfer::dnd::XDragSource > SAL_CALL getDragSource( const css::uno::Reference< css::awt::XWindow >& window ) override;
+ css::uno::Reference< css::datatransfer::dnd::XDropTarget > SAL_CALL getDropTarget( const css::uno::Reference< css::awt::XWindow >& window ) override;
+ css::uno::Reference< css::datatransfer::clipboard::XClipboard > SAL_CALL getClipboard( const OUString& clipboardName ) override;
+
+ // css::lang::XServiceInfo
+ OUString SAL_CALL getImplementationName( ) override;
+ sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // css::awt::XExtendedToolkit:
+
+ virtual ::sal_Int32 SAL_CALL getTopWindowCount() override;
+
+ virtual css::uno::Reference< css::awt::XTopWindow >
+ SAL_CALL getTopWindow(::sal_Int32 nIndex) override;
+
+ virtual css::uno::Reference< css::awt::XTopWindow >
+ SAL_CALL getActiveTopWindow() override;
+
+ virtual void SAL_CALL addTopWindowListener(
+ css::uno::Reference<
+ css::awt::XTopWindowListener > const & rListener) override;
+
+ virtual void SAL_CALL removeTopWindowListener(
+ css::uno::Reference<
+ css::awt::XTopWindowListener > const & rListener) override;
+
+ virtual void SAL_CALL addKeyHandler(
+ css::uno::Reference<
+ css::awt::XKeyHandler > const & rHandler) override;
+
+ virtual void SAL_CALL removeKeyHandler(
+ css::uno::Reference<
+ css::awt::XKeyHandler > const & rHandler) override;
+
+ virtual void SAL_CALL addFocusListener(
+ css::uno::Reference<
+ css::awt::XFocusListener > const & rListener) override;
+
+ virtual void SAL_CALL removeFocusListener(
+ css::uno::Reference<
+ css::awt::XFocusListener > const & rListener) override;
+
+ virtual void SAL_CALL fireFocusGained(
+ css::uno::Reference<
+ css::uno::XInterface > const & source) override;
+
+ virtual void SAL_CALL fireFocusLost(
+ css::uno::Reference<
+ css::uno::XInterface > const & source) override;
+
+ // css::awt::XReschedule:
+ virtual void SAL_CALL reschedule() override;
+
+ // css::awt::XFontMappingUse:
+ virtual void SAL_CALL startTrackingFontMappingUse() override;
+
+ virtual css::uno::Sequence<css::awt::XFontMappingUseItem> SAL_CALL finishTrackingFontMappingUse() override;
+
+ // css:awt:XToolkitRobot
+ virtual void SAL_CALL keyPress( const css::awt::KeyEvent & aKeyEvent ) override;
+
+ virtual void SAL_CALL keyRelease( const css::awt::KeyEvent & aKeyEvent ) override;
+
+ virtual void SAL_CALL mousePress( const css::awt::MouseEvent & aMouseEvent ) override;
+
+ virtual void SAL_CALL mouseRelease( const css::awt::MouseEvent & aMouseEvent ) override;
+
+ virtual void SAL_CALL mouseMove( const css::awt::MouseEvent & aMouseEvent ) override;
+
+};
+
+std::pair<WinBits,MessBoxStyle> ImplGetWinBits( sal_uInt32 nComponentAttribs, WindowType nCompType )
+{
+ WinBits nWinBits = 0;
+ MessBoxStyle nStyle = MessBoxStyle::NONE;
+
+ bool bMessBox = false;
+ if ( ( nCompType == WindowType::INFOBOX ) ||
+ ( nCompType == WindowType::MESSBOX ) ||
+ ( nCompType == WindowType::QUERYBOX ) ||
+ ( nCompType == WindowType::WARNINGBOX ) ||
+ ( nCompType == WindowType::ERRORBOX ) )
+ {
+ bMessBox = true;
+ }
+
+ bool bDecoratedWindow = false;
+ if ( bMessBox
+ || ( nCompType == WindowType::DIALOG )
+ || ( nCompType == WindowType::MODELESSDIALOG )
+ || ( nCompType == WindowType::DOCKINGWINDOW )
+ || ( nCompType == WindowType::TABDIALOG )
+ || ( nCompType == WindowType::BUTTONDIALOG )
+ || ( nCompType == WindowType::SYSTEMCHILDWINDOW )
+ )
+ {
+ bDecoratedWindow = true;
+ }
+
+ if( nComponentAttribs & css::awt::WindowAttribute::BORDER )
+ nWinBits |= WB_BORDER;
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::NOBORDER )
+ nWinBits |= WB_NOBORDER;
+ if( nComponentAttribs & css::awt::WindowAttribute::SIZEABLE )
+ nWinBits |= WB_SIZEABLE;
+ if( nComponentAttribs & css::awt::WindowAttribute::MOVEABLE )
+ nWinBits |= WB_MOVEABLE;
+ if( nComponentAttribs & css::awt::WindowAttribute::CLOSEABLE )
+ nWinBits |= WB_CLOSEABLE;
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::HSCROLL )
+ nWinBits |= WB_HSCROLL;
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::VSCROLL )
+ nWinBits |= WB_VSCROLL;
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::LEFT )
+ nWinBits |= WB_LEFT;
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::CENTER )
+ nWinBits |= WB_CENTER;
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::RIGHT )
+ nWinBits |= WB_RIGHT;
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::SPIN )
+ nWinBits |= WB_SPIN;
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::SORT )
+ nWinBits |= WB_SORT;
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::DROPDOWN )
+ nWinBits |= WB_DROPDOWN;
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::DEFBUTTON )
+ nWinBits |= WB_DEFBUTTON;
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::READONLY )
+ nWinBits |= WB_READONLY;
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::CLIPCHILDREN )
+ nWinBits |= WB_CLIPCHILDREN;
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::GROUP )
+ nWinBits |= WB_GROUP;
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::NOLABEL ) //added for issue79712
+ nWinBits |= WB_NOLABEL;
+
+ // These bits are not unique
+ if ( bMessBox )
+ {
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::OK )
+ nStyle |= MessBoxStyle::Ok;
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::OK_CANCEL )
+ nStyle |= MessBoxStyle::OkCancel;
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::YES_NO )
+ nStyle |= MessBoxStyle::YesNo;
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::YES_NO_CANCEL )
+ nStyle |= MessBoxStyle::YesNoCancel;
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::RETRY_CANCEL )
+ nStyle |= MessBoxStyle::RetryCancel;
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::DEF_OK )
+ nStyle |= MessBoxStyle::DefaultOk;
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::DEF_CANCEL )
+ nStyle |= MessBoxStyle::DefaultCancel;
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::DEF_RETRY )
+ nStyle |= MessBoxStyle::DefaultRetry;
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::DEF_YES )
+ nStyle |= MessBoxStyle::DefaultYes;
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::DEF_NO )
+ nStyle |= MessBoxStyle::DefaultNo;
+ }
+ if ( nCompType == WindowType::MULTILINEEDIT || nCompType == WindowType::DIALOG
+ || nCompType == WindowType::GROUPBOX || nCompType == WindowType::TABPAGE )
+ {
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::AUTOHSCROLL )
+ nWinBits |= WB_AUTOHSCROLL;
+ if( nComponentAttribs & css::awt::VclWindowPeerAttribute::AUTOVSCROLL )
+ nWinBits |= WB_AUTOVSCROLL;
+ }
+
+
+ if ( bDecoratedWindow )
+ {
+ if( nComponentAttribs & css::awt::WindowAttribute::NODECORATION )
+ {
+ // No decoration removes several window attributes and must
+ // set WB_NOBORDER!
+ nWinBits &= ~WB_BORDER;
+ nWinBits &= ~WB_SIZEABLE;
+ nWinBits &= ~WB_MOVEABLE;
+ nWinBits &= ~WB_CLOSEABLE;
+ nWinBits |= WB_NOBORDER;
+ }
+ }
+
+ return { nWinBits, nStyle };
+}
+
+struct ComponentInfo
+{
+ std::u16string_view sName;
+ WindowType nWinType;
+};
+
+ComponentInfo const aComponentInfos [] =
+{
+ { std::u16string_view(u"animatedimages"), WindowType::CONTROL },
+ { std::u16string_view(u"buttondialog"), WindowType::BUTTONDIALOG },
+ { std::u16string_view(u"cancelbutton"), WindowType::CANCELBUTTON },
+ { std::u16string_view(u"checkbox"), WindowType::CHECKBOX },
+ { std::u16string_view(u"combobox"), WindowType::COMBOBOX },
+ { std::u16string_view(u"control"), WindowType::CONTROL },
+ { std::u16string_view(u"currencybox"), WindowType::CURRENCYBOX },
+ { std::u16string_view(u"currencyfield"), WindowType::CURRENCYFIELD },
+ { std::u16string_view(u"datebox"), WindowType::DATEBOX },
+ { std::u16string_view(u"datefield"), WindowType::CONTROL },
+ { std::u16string_view(u"dialog"), WindowType::DIALOG },
+ { std::u16string_view(u"dockingarea"), WindowType::DOCKINGAREA },
+ { std::u16string_view(u"dockingwindow"), WindowType::DOCKINGWINDOW },
+ { std::u16string_view(u"edit"), WindowType::EDIT },
+ { std::u16string_view(u"errorbox"), WindowType::ERRORBOX },
+ { std::u16string_view(u"filecontrol"), WindowType::CONTROL },
+ { std::u16string_view(u"fixedbitmap"), WindowType::FIXEDBITMAP },
+ { std::u16string_view(u"fixedhyperlink"), WindowType::CONTROL },
+ { std::u16string_view(u"fixedimage"), WindowType::FIXEDIMAGE },
+ { std::u16string_view(u"fixedline"), WindowType::FIXEDLINE },
+ { std::u16string_view(u"fixedtext"), WindowType::FIXEDTEXT },
+ { std::u16string_view(u"floatingwindow"), WindowType::FLOATINGWINDOW },
+ { std::u16string_view(u"formattedfield"), WindowType::CONTROL },
+ { std::u16string_view(u"frame"), WindowType::GROUPBOX },
+ { std::u16string_view(u"framewindow"), WindowType::TOOLKIT_FRAMEWINDOW },
+ { std::u16string_view(u"grid"), WindowType::CONTROL },
+ { std::u16string_view(u"groupbox"), WindowType::GROUPBOX },
+ { std::u16string_view(u"helpbutton"), WindowType::HELPBUTTON },
+ { std::u16string_view(u"imagebutton"), WindowType::IMAGEBUTTON },
+ { std::u16string_view(u"infobox"), WindowType::INFOBOX },
+ { std::u16string_view(u"listbox"), WindowType::LISTBOX },
+ { std::u16string_view(u"longcurrencybox"), WindowType::LONGCURRENCYBOX },
+ { std::u16string_view(u"longcurrencyfield"), WindowType::CONTROL },
+ { std::u16string_view(u"menubutton"), WindowType::MENUBUTTON },
+ { std::u16string_view(u"messbox"), WindowType::MESSBOX },
+ { std::u16string_view(u"metricbox"), WindowType::METRICBOX },
+ { std::u16string_view(u"metricfield"), WindowType::METRICFIELD },
+ { std::u16string_view(u"modelessdialog"), WindowType::MODELESSDIALOG },
+ { std::u16string_view(u"morebutton"), WindowType::MOREBUTTON },
+ { std::u16string_view(u"multilineedit"), WindowType::MULTILINEEDIT },
+ { std::u16string_view(u"multilistbox"), WindowType::MULTILISTBOX },
+ { std::u16string_view(u"numericbox"), WindowType::NUMERICBOX },
+ { std::u16string_view(u"numericfield"), WindowType::CONTROL },
+ { std::u16string_view(u"okbutton"), WindowType::OKBUTTON },
+ { std::u16string_view(u"patternbox"), WindowType::PATTERNBOX },
+ { std::u16string_view(u"patternfield"), WindowType::PATTERNFIELD },
+ { std::u16string_view(u"progressbar"), WindowType::CONTROL },
+ { std::u16string_view(u"pushbutton"), WindowType::PUSHBUTTON },
+ { std::u16string_view(u"querybox"), WindowType::QUERYBOX },
+ { std::u16string_view(u"radiobutton"), WindowType::RADIOBUTTON },
+ { std::u16string_view(u"roadmap"), WindowType::CONTROL },
+ { std::u16string_view(u"scrollbar"), WindowType::SCROLLBAR },
+ { std::u16string_view(u"scrollbarbox"), WindowType::SCROLLBARBOX },
+ { std::u16string_view(u"spinbutton"), WindowType::SPINBUTTON },
+ { std::u16string_view(u"spinfield"), WindowType::SPINFIELD },
+ { std::u16string_view(u"splitter"), WindowType::SPLITTER },
+ { std::u16string_view(u"splitwindow"), WindowType::SPLITWINDOW },
+ { std::u16string_view(u"statusbar"), WindowType::STATUSBAR },
+ { std::u16string_view(u"systemchildwindow"), WindowType::TOOLKIT_SYSTEMCHILDWINDOW },
+ { std::u16string_view(u"tabcontrol"), WindowType::TABCONTROL },
+ { std::u16string_view(u"tabdialog"), WindowType::TABDIALOG },
+ { std::u16string_view(u"tabpage"), WindowType::TABPAGE },
+ { std::u16string_view(u"tabpagecontainer"), WindowType::CONTROL },
+ { std::u16string_view(u"tabpagemodel"), WindowType::TABPAGE },
+ { std::u16string_view(u"timebox"), WindowType::TIMEBOX },
+ { std::u16string_view(u"timefield"), WindowType::TIMEFIELD },
+ { std::u16string_view(u"toolbox"), WindowType::TOOLBOX },
+ { std::u16string_view(u"tree"), WindowType::CONTROL },
+ { std::u16string_view(u"tristatebox"), WindowType::TRISTATEBOX },
+ { std::u16string_view(u"warningbox"), WindowType::WARNINGBOX },
+ { std::u16string_view(u"window"), WindowType::WINDOW },
+ { std::u16string_view(u"workwindow"), WindowType::WORKWINDOW }
+};
+
+bool ComponentInfoFindCompare( const ComponentInfo & lhs, const OUString & s)
+{
+ return rtl_ustr_compareIgnoreAsciiCase_WithLength(s.pData->buffer, s.pData->length,
+ lhs.sName.data(), lhs.sName.size()) > 0;
+}
+
+WindowType ImplGetComponentType( const OUString& rServiceName )
+{
+ static bool bSorted = false;
+ if( !bSorted )
+ {
+ assert( std::is_sorted( std::begin(aComponentInfos), std::end(aComponentInfos),
+ [](const ComponentInfo & lhs, const ComponentInfo & rhs) {
+ return
+ rtl_ustr_compare_WithLength(
+ lhs.sName.data(), lhs.sName.size(), rhs.sName.data(),
+ rhs.sName.size())
+ < 0;
+ } ) );
+ bSorted = true;
+ }
+
+ OUString sSearch;
+ if ( !rServiceName.isEmpty() )
+ sSearch = rServiceName;
+ else
+ sSearch = "window";
+
+ auto it = std::lower_bound( std::begin(aComponentInfos), std::end(aComponentInfos), sSearch,
+ ComponentInfoFindCompare );
+ if (it != std::end(aComponentInfos) &&
+ rtl_ustr_compareIgnoreAsciiCase_WithLength(sSearch.pData->buffer, sSearch.pData->length, it->sName.data(), it->sName.size()) == 0)
+ return it->nWinType;
+ return WindowType::NONE;
+}
+
+struct MessageBoxTypeInfo
+{
+ css::awt::MessageBoxType eType;
+ const char *pName;
+ sal_Int32 nLen;
+};
+
+const MessageBoxTypeInfo aMessageBoxTypeInfo[] =
+{
+ { css::awt::MessageBoxType_MESSAGEBOX, RTL_CONSTASCII_STRINGPARAM("messbox") },
+ { css::awt::MessageBoxType_INFOBOX, RTL_CONSTASCII_STRINGPARAM("infobox") },
+ { css::awt::MessageBoxType_WARNINGBOX, RTL_CONSTASCII_STRINGPARAM("warningbox") },
+ { css::awt::MessageBoxType_ERRORBOX, RTL_CONSTASCII_STRINGPARAM("errorbox") },
+ { css::awt::MessageBoxType_QUERYBOX, RTL_CONSTASCII_STRINGPARAM("querybox") },
+ { css::awt::MessageBoxType::MessageBoxType_MAKE_FIXED_SIZE, nullptr, 0 }
+};
+
+bool lcl_convertMessageBoxType(
+ OUString &sType,
+ css::awt::MessageBoxType eType )
+{
+ const MessageBoxTypeInfo *pMap = aMessageBoxTypeInfo;
+ css::awt::MessageBoxType eVal = css::awt::MessageBoxType::MessageBoxType_MAKE_FIXED_SIZE;
+
+ while ( pMap->pName )
+ {
+ if ( pMap->eType == eType )
+ {
+ eVal = eType;
+ sType = OUString( pMap->pName, pMap->nLen, RTL_TEXTENCODING_ASCII_US );
+ break;
+ }
+ pMap++;
+ }
+
+ return ( eVal != css::awt::MessageBoxType::MessageBoxType_MAKE_FIXED_SIZE );
+}
+
+#ifndef IOS
+
+sal_Int32 nVCLToolkitInstanceCount = 0;
+bool bInitedByVCLToolkit = false;
+
+osl::Mutex & getInitMutex()
+{
+ static osl::Mutex aMutex;
+ return aMutex;
+}
+
+osl::Condition & getInitCondition()
+{
+ static osl::Condition aCondition;
+ return aCondition;
+}
+
+extern "C"
+{
+static void ToolkitWorkerFunction( void* pArgs )
+{
+ osl_setThreadName("VCLXToolkit VCL main thread");
+
+ css::uno::Reference<css::lang::XMultiServiceFactory> xServiceManager;
+ try
+ {
+ xServiceManager = ::comphelper::getProcessServiceFactory();
+ }
+ catch (const css::uno::DeploymentException&)
+ {
+ }
+ if (!xServiceManager.is())
+ {
+ css::uno::Reference<css::uno::XComponentContext> xContext =
+ ::cppu::defaultBootstrap_InitialComponentContext();
+
+ xServiceManager.set( xContext->getServiceManager(), css::uno::UNO_QUERY_THROW );
+ // set global process service factory used by unotools config helpers
+ ::comphelper::setProcessServiceFactory( xServiceManager );
+ }
+
+ VCLXToolkit * pTk = static_cast<VCLXToolkit *>(pArgs);
+ bInitedByVCLToolkit = !IsVCLInit() && InitVCL();
+ if( bInitedByVCLToolkit )
+ {
+ UnoWrapper* pUnoWrapper = new UnoWrapper( pTk );
+ UnoWrapperBase::SetUnoWrapper( pUnoWrapper );
+ }
+ getInitCondition().set();
+ if( bInitedByVCLToolkit )
+ {
+ {
+ SolarMutexGuard aGuard;
+ Application::Execute();
+ }
+ try
+ {
+ pTk->dispose();
+ }
+ catch( css::uno::Exception & )
+ {
+ }
+ DeInitVCL();
+ }
+ else
+ {
+ // having the thread join itself is pretty stupid.
+ // but we can't get the osl_Thread to destroy here so just leak it.
+ }
+}
+}
+
+#endif
+
+// constructor, which might initialize VCL
+VCLXToolkit::VCLXToolkit():
+ cppu::WeakComponentImplHelper<
+ css::awt::XToolkitExperimental,
+ css::awt::XToolkitRobot,
+ css::lang::XServiceInfo>( GetMutex() ),
+ m_aTopWindowListeners(rBHelper.rMutex),
+ m_aKeyHandlers(rBHelper.rMutex),
+ m_aFocusListeners(rBHelper.rMutex),
+ m_aEventListenerLink(LINK(this, VCLXToolkit, eventListenerHandler)),
+ m_aKeyListenerLink(LINK(this, VCLXToolkit, keyListenerHandler)),
+ m_bEventListener(false),
+ m_bKeyListener(false)
+{
+#ifndef IOS
+ osl::Guard< osl::Mutex > aGuard( getInitMutex() );
+ nVCLToolkitInstanceCount++;
+ if( ( nVCLToolkitInstanceCount == 1 ) && ( !Application::IsInMain() ) )
+ {
+ // setup execute thread
+ CreateMainLoopThread( ToolkitWorkerFunction, this );
+ getInitCondition().wait();
+ }
+#endif
+}
+
+void SAL_CALL VCLXToolkit::disposing()
+{
+#ifndef IOS
+ {
+ osl::Guard< osl::Mutex > aGuard( getInitMutex() );
+ if( --nVCLToolkitInstanceCount == 0 )
+ {
+ if( bInitedByVCLToolkit )
+ {
+ Application::Quit();
+ JoinMainLoopThread();
+ bInitedByVCLToolkit = false;
+ }
+ }
+ }
+#endif
+ if (m_bEventListener)
+ {
+ ::Application::RemoveEventListener(m_aEventListenerLink);
+ m_bEventListener = false;
+ }
+ if (m_bKeyListener)
+ {
+ ::Application::RemoveKeyListener(m_aKeyListenerLink);
+ m_bKeyListener = false;
+ }
+ css::lang::EventObject aEvent(
+ getXWeak());
+ m_aTopWindowListeners.disposeAndClear(aEvent);
+ m_aKeyHandlers.disposeAndClear(aEvent);
+ m_aFocusListeners.disposeAndClear(aEvent);
+}
+
+
+css::uno::Reference< css::awt::XWindowPeer > VCLXToolkit::getDesktopWindow( )
+{
+ css::uno::Reference< css::awt::XWindowPeer > xRef;
+ // 07/00: AppWindow doesn't exist anymore...
+ return xRef;
+}
+
+css::awt::Rectangle VCLXToolkit::getWorkArea( )
+{
+ sal_Int32 nDisplay = Application::GetDisplayBuiltInScreen();
+ AbsoluteScreenPixelRectangle aWorkRect = Application::GetScreenPosSizePixel( nDisplay );
+ css::awt::Rectangle aNotherRect;
+ aNotherRect.X = aWorkRect.Left();
+ aNotherRect.Y = aWorkRect.Top();
+ aNotherRect.Width = aWorkRect.getOpenWidth();
+ aNotherRect.Height = aWorkRect.getOpenHeight();
+ return aNotherRect;
+}
+
+css::uno::Reference< css::awt::XWindowPeer > VCLXToolkit::createWindow( const css::awt::WindowDescriptor& rDescriptor )
+{
+ return ImplCreateWindow( rDescriptor, MessBoxStyle::NONE );
+}
+
+css::uno::Reference< css::awt::XDevice > VCLXToolkit::createScreenCompatibleDevice( sal_Int32 Width, sal_Int32 Height )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ rtl::Reference<VCLXVirtualDevice> pVDev = new VCLXVirtualDevice;
+
+ SolarMutexGuard aSolarGuard;
+
+ VclPtrInstance<VirtualDevice> pV;
+ pV->SetOutputSizePixel( Size( Width, Height ) );
+ pVDev->SetVirtualDevice( pV );
+
+ return pVDev;
+}
+
+css::uno::Reference< css::awt::XRegion > VCLXToolkit::createRegion( )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ css::uno::Reference< css::awt::XRegion > xRef = new VCLXRegion;
+ return xRef;
+}
+
+class InfoBox : public MessBox
+{
+public:
+ InfoBox(vcl::Window* pParent, const OUString& rMessage)
+ : MessBox(pParent, MessBoxStyle::Ok | MessBoxStyle::DefaultOk, 0, OUString(), rMessage)
+ {
+ // Default Text is the display title from the application
+ if (GetText().isEmpty())
+ SetText(GetStandardInfoBoxText());
+ SetImage(GetStandardInfoBoxImage());
+ }
+};
+
+class ErrorBox : public MessBox
+{
+public:
+ ErrorBox(vcl::Window* pParent, MessBoxStyle nStyle, WinBits nWinBits, const OUString& rMessage)
+ : MessBox(pParent, nStyle, nWinBits, OUString(), rMessage)
+ {
+ // Default Text is the display title from the application
+ if (GetText().isEmpty())
+ SetText(GetStandardErrorBoxText());
+ SetImage(GetStandardErrorBoxImage());
+ }
+};
+
+class QueryBox : public MessBox
+{
+public:
+ QueryBox(vcl::Window* pParent, MessBoxStyle nStyle, WinBits nWinBits, const OUString& rMessage)
+ : MessBox(pParent, nStyle, nWinBits, OUString(), rMessage)
+ {
+ // Default Text is the display title from the application
+ if (GetText().isEmpty())
+ SetText(GetStandardQueryBoxText());
+ SetImage(GetStandardQueryBoxImage());
+ }
+};
+
+class WarningBox : public MessBox
+{
+public:
+ WarningBox(vcl::Window* pParent, MessBoxStyle nStyle, WinBits nWinBits, const OUString& rMessage)
+ : MessBox(pParent, nStyle, nWinBits, OUString(), rMessage)
+ {
+ // Default Text is the display title from the application
+ if (GetText().isEmpty())
+ SetText(GetStandardWarningBoxText());
+ SetImage(GetStandardWarningBoxImage());
+ }
+};
+
+
+struct RMItemData
+{
+ bool b_Enabled;
+ sal_Int32 n_ID;
+ OUString Label;
+};
+
+typedef ::cppu::ImplInheritanceHelper < VCLXGraphicControl
+ , css::container::XContainerListener
+ , css::beans::XPropertyChangeListener
+ , css::awt::XItemEventBroadcaster
+ > SVTXRoadmap_Base;
+class SVTXRoadmap final : public SVTXRoadmap_Base
+{
+public:
+ SVTXRoadmap();
+
+ void SAL_CALL disposing( const css::lang::EventObject& Source ) override { VCLXWindow::disposing( Source ); }
+
+ // css::awt::XVclWindowPeer
+ void SAL_CALL setProperty( const OUString& PropertyName, const css::uno::Any& Value ) override;
+
+ css::uno::Any SAL_CALL getProperty( const OUString& PropertyName ) override;
+
+ // XContainerListener
+ void SAL_CALL elementInserted( const css::container::ContainerEvent& rEvent ) override;
+ void SAL_CALL elementRemoved( const css::container::ContainerEvent& rEvent ) override;
+ void SAL_CALL elementReplaced( const css::container::ContainerEvent& rEvent ) override;
+
+ // XItemEventBroadcaster
+ virtual void SAL_CALL addItemListener( const css::uno::Reference< css::awt::XItemListener >& l ) override;
+ virtual void SAL_CALL removeItemListener( const css::uno::Reference< css::awt::XItemListener >& l ) override;
+
+ // XPropertyChangeListener
+ virtual void SAL_CALL propertyChange( const css::beans::PropertyChangeEvent& evt ) override;
+
+private:
+
+ // VCLXGraphicControl overridables
+ virtual void ImplSetNewImage() override;
+
+ static void ImplGetPropertyIds( std::vector< sal_uInt16 > &aIds );
+ virtual void GetPropertyIds( std::vector< sal_uInt16 > &aIds ) override { return ImplGetPropertyIds( aIds ); }
+
+ static RMItemData GetRMItemData( const css::container::ContainerEvent& _rEvent );
+
+ virtual void ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) override;
+
+ virtual ~SVTXRoadmap() override;
+
+ ItemListenerMultiplexer maItemListeners;
+};
+
+
+
+
+SVTXRoadmap::SVTXRoadmap() : maItemListeners( *this )
+{
+}
+
+SVTXRoadmap::~SVTXRoadmap()
+{
+}
+
+void SVTXRoadmap::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::RoadmapItemSelected:
+ {
+ SolarMutexGuard aGuard;
+ VclPtr<::vcl::ORoadmap> pField = GetAs< vcl::ORoadmap >();
+ if ( pField )
+ {
+ sal_Int16 CurItemID = pField->GetCurrentRoadmapItemID();
+ css::awt::ItemEvent aEvent;
+ aEvent.Selected = CurItemID;
+ aEvent.Highlighted = CurItemID;
+ aEvent.ItemId = CurItemID;
+ maItemListeners.itemStateChanged( aEvent );
+ }
+ }
+ break;
+ default:
+ SVTXRoadmap_Base::ProcessWindowEvent( rVclWindowEvent );
+ break;
+ }
+}
+
+void SVTXRoadmap::propertyChange( const css::beans::PropertyChangeEvent& evt )
+{
+ SolarMutexGuard aGuard;
+ VclPtr<::vcl::ORoadmap> pField = GetAs< vcl::ORoadmap >();
+ if ( !pField )
+ return;
+
+ css::uno::Reference< css::uno::XInterface > xRoadmapItem = evt.Source;
+ sal_Int32 nID = 0;
+ css::uno::Reference< css::beans::XPropertySet > xPropertySet( xRoadmapItem, css::uno::UNO_QUERY );
+ css::uno::Any aValue = xPropertySet->getPropertyValue("ID");
+ aValue >>= nID;
+
+ OUString sPropertyName = evt.PropertyName;
+ if ( sPropertyName == "Enabled" )
+ {
+ bool bEnable = false;
+ evt.NewValue >>= bEnable;
+ pField->EnableRoadmapItem( static_cast<vcl::RoadmapTypes::ItemId>(nID) , bEnable );
+ }
+ else if ( sPropertyName == "Label" )
+ {
+ OUString sLabel;
+ evt.NewValue >>= sLabel;
+ pField->ChangeRoadmapItemLabel( static_cast<vcl::RoadmapTypes::ItemId>(nID) , sLabel );
+ }
+ else if ( sPropertyName == "ID" )
+ {
+ sal_Int32 nNewID = 0;
+ evt.NewValue >>= nNewID;
+ evt.OldValue >>= nID;
+ pField->ChangeRoadmapItemID( static_cast<vcl::RoadmapTypes::ItemId>(nID), static_cast<vcl::RoadmapTypes::ItemId>(nNewID) );
+ }
+// else
+ // TODO handle Interactive appropriately
+}
+
+void SVTXRoadmap::addItemListener( const css::uno::Reference< css::awt::XItemListener >& l )
+{
+ maItemListeners.addInterface( l );
+}
+
+void SVTXRoadmap::removeItemListener( const css::uno::Reference< css::awt::XItemListener >& l )
+{
+ maItemListeners.removeInterface( l );
+}
+
+RMItemData SVTXRoadmap::GetRMItemData( const css::container::ContainerEvent& _rEvent )
+{
+ RMItemData aCurRMItemData;
+ css::uno::Reference< css::uno::XInterface > xRoadmapItem;
+ _rEvent.Element >>= xRoadmapItem;
+ css::uno::Reference< css::beans::XPropertySet > xPropertySet( xRoadmapItem, css::uno::UNO_QUERY );
+ if ( xPropertySet.is() )
+ {
+ css::uno::Any aValue = xPropertySet->getPropertyValue("Label");
+ aValue >>= aCurRMItemData.Label;
+ aValue = xPropertySet->getPropertyValue("ID");
+ aValue >>= aCurRMItemData.n_ID;
+ aValue = xPropertySet->getPropertyValue("Enabled");
+ aValue >>= aCurRMItemData.b_Enabled;
+ }
+ else
+ {
+ aCurRMItemData.b_Enabled = false;
+ aCurRMItemData.n_ID = 0;
+ }
+ return aCurRMItemData;
+}
+
+void SVTXRoadmap::elementInserted( const css::container::ContainerEvent& _rEvent )
+{
+ SolarMutexGuard aGuard;
+ VclPtr<::vcl::ORoadmap> pField = GetAs< vcl::ORoadmap >();
+ if ( pField )
+ {
+ RMItemData CurItemData = GetRMItemData( _rEvent );
+ sal_Int32 InsertIndex = 0;
+ _rEvent.Accessor >>= InsertIndex;
+ pField->InsertRoadmapItem( InsertIndex, CurItemData.Label, static_cast<vcl::RoadmapTypes::ItemId>(CurItemData.n_ID), CurItemData.b_Enabled );
+ }
+}
+
+void SVTXRoadmap::elementRemoved( const css::container::ContainerEvent& _rEvent )
+{
+ SolarMutexGuard aGuard;
+ VclPtr<::vcl::ORoadmap> pField = GetAs< vcl::ORoadmap >();
+ if ( pField )
+ {
+ sal_Int32 DelIndex = 0;
+ _rEvent.Accessor >>= DelIndex;
+ pField->DeleteRoadmapItem(DelIndex);
+ }
+}
+
+void SVTXRoadmap::elementReplaced( const css::container::ContainerEvent& _rEvent )
+{
+ SolarMutexGuard aGuard;
+ VclPtr<::vcl::ORoadmap> pField = GetAs< vcl::ORoadmap >();
+ if ( pField )
+ {
+ RMItemData CurItemData = GetRMItemData( _rEvent );
+ sal_Int32 ReplaceIndex = 0;
+ _rEvent.Accessor >>= ReplaceIndex;
+ pField->ReplaceRoadmapItem( ReplaceIndex, CurItemData.Label, static_cast<vcl::RoadmapTypes::ItemId>(CurItemData.n_ID), CurItemData.b_Enabled );
+ }
+}
+
+void SVTXRoadmap::setProperty( const OUString& PropertyName, const css::uno::Any& Value)
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<::vcl::ORoadmap> pField = GetAs< vcl::ORoadmap >();
+ if ( pField )
+ {
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch (nPropType)
+ {
+ case BASEPROPERTY_COMPLETE:
+ {
+ bool b = false;
+ Value >>= b;
+ pField->SetRoadmapComplete( b);
+ }
+ break;
+
+ case BASEPROPERTY_ACTIVATED:
+ {
+ bool b = false;
+ Value >>= b;
+ pField->SetRoadmapInteractive( b);
+ }
+ break;
+
+ case BASEPROPERTY_CURRENTITEMID:
+ {
+ sal_Int32 nId = 0;
+ Value >>= nId;
+ pField->SelectRoadmapItemByID( static_cast<vcl::RoadmapTypes::ItemId>(nId) );
+ }
+ break;
+
+ case BASEPROPERTY_TEXT:
+ {
+ OUString aStr;
+ Value >>= aStr;
+ pField->SetText( aStr );
+ pField->Invalidate();
+ }
+ break;
+
+ default:
+ SVTXRoadmap_Base::setProperty( PropertyName, Value );
+ break;
+ }
+
+ }
+ else
+ SVTXRoadmap_Base::setProperty( PropertyName, Value );
+}
+
+
+css::uno::Any SVTXRoadmap::getProperty( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Any aReturn;
+
+ VclPtr<::vcl::ORoadmap> pField = GetAs< vcl::ORoadmap >();
+ if ( pField )
+ {
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch (nPropType)
+ {
+ case BASEPROPERTY_COMPLETE:
+ aReturn <<= pField->IsRoadmapComplete();
+ break;
+ case BASEPROPERTY_ACTIVATED:
+ aReturn <<= pField->IsRoadmapInteractive();
+ break;
+ case BASEPROPERTY_CURRENTITEMID:
+ aReturn <<= pField->GetCurrentRoadmapItemID();
+ break;
+ default:
+ aReturn = SVTXRoadmap_Base::getProperty(PropertyName);
+ break;
+ }
+ }
+ return aReturn;
+}
+
+void SVTXRoadmap::ImplSetNewImage()
+{
+ OSL_PRECOND( GetWindow(), "SVTXRoadmap::ImplSetNewImage: window is required to be not-NULL!" );
+ VclPtr< ::vcl::ORoadmap > pButton = GetAs< ::vcl::ORoadmap >();
+ pButton->SetRoadmapBitmap( GetImage().GetBitmapEx() );
+}
+
+void SVTXRoadmap::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ BASEPROPERTY_COMPLETE,
+ BASEPROPERTY_ACTIVATED,
+ BASEPROPERTY_CURRENTITEMID,
+ BASEPROPERTY_TEXT,
+ 0);
+ VCLXWindow::ImplGetPropertyIds( rIds, true );
+ VCLXGraphicControl::ImplGetPropertyIds( rIds );
+}
+
+vcl::Window* VCLXToolkit::ImplCreateWindow( rtl::Reference<VCLXWindow>* ppNewComp,
+ const css::awt::WindowDescriptor& rDescriptor,
+ vcl::Window* pParent, WinBits nWinBits, MessBoxStyle nMessBoxStyle )
+{
+ OUString aServiceName = rDescriptor.WindowServiceName.toAsciiLowerCase();
+
+ VclPtr<vcl::Window> pNewWindow;
+ WindowType nType = ImplGetComponentType( aServiceName );
+ bool bFrameControl = false;
+ if ( aServiceName == "frame" )
+ bFrameControl = true;
+ if ( aServiceName == "tabcontrolnotabs" )
+ {
+ nWinBits |= WB_NOBORDER;
+ nType = ImplGetComponentType( "tabcontrol" );
+ }
+ if ( !pParent )
+ {
+ // If the component needs a parent, then return NULL,
+ // some time later css::uno::Exception...
+ bool bException = true;
+ if ( ( nType == WindowType::DIALOG )
+ || ( nType == WindowType::MODELESSDIALOG )
+ || ( nType == WindowType::MESSBOX )
+ || ( nType == WindowType::INFOBOX )
+ || ( nType == WindowType::WARNINGBOX )
+ || ( nType == WindowType::ERRORBOX )
+ || ( nType == WindowType::QUERYBOX )
+ )
+ bException = false;
+ else if ( ( nType == WindowType::WINDOW ) ||
+ ( nType == WindowType::WORKWINDOW ) ||
+ ( nType == WindowType::TOOLKIT_FRAMEWINDOW ) )
+ {
+ if ( rDescriptor.Type == css::awt::WindowClass_TOP )
+ bException = false;
+ }
+
+ if ( bException )
+ {
+ *ppNewComp = nullptr;
+ return nullptr;
+ }
+ }
+
+ if ( nType != WindowType::NONE )
+ {
+ SolarMutexGuard aVclGuard;
+ switch ( nType )
+ {
+ case WindowType::CANCELBUTTON:
+ pNewWindow = VclPtr<CancelButton>::Create( pParent, nWinBits );
+ *ppNewComp = new VCLXButton;
+ break;
+ case WindowType::CHECKBOX:
+ pNewWindow = VclPtr<CheckBox>::Create( pParent, nWinBits );
+ *ppNewComp = new VCLXCheckBox;
+ break;
+ case WindowType::COMBOBOX:
+ pNewWindow = VclPtr<ComboBox>::Create( pParent, nWinBits|WB_AUTOHSCROLL );
+ static_cast<ComboBox*>(pNewWindow.get())->EnableAutoSize( false );
+ *ppNewComp = new VCLXComboBox;
+ break;
+ case WindowType::CURRENCYBOX:
+ pNewWindow = VclPtr<CurrencyBox>::Create( pParent, nWinBits );
+ break;
+ case WindowType::CURRENCYFIELD:
+ pNewWindow = VclPtr<CurrencyField>::Create( pParent, nWinBits );
+ static_cast<CurrencyField*>(pNewWindow.get())->EnableEmptyFieldValue( true );
+ *ppNewComp = new VCLXNumericField;
+ static_cast<VCLXFormattedSpinField*>((*ppNewComp).get())->SetFormatter( static_cast<FormatterBase*>(static_cast<CurrencyField*>(pNewWindow.get())) );
+ break;
+ case WindowType::DATEBOX:
+ pNewWindow = VclPtr<DateBox>::Create( pParent, nWinBits );
+ break;
+ case WindowType::DOCKINGAREA:
+ pNewWindow = VclPtr<DockingAreaWindow>::Create( pParent );
+ break;
+ case WindowType::MULTILINEEDIT:
+ pNewWindow = VclPtr<MultiLineEdit>::Create(pParent, nWinBits|WB_IGNORETAB);
+ static_cast<MultiLineEdit*>(pNewWindow.get())->DisableSelectionOnFocus();
+ *ppNewComp = new VCLXMultiLineEdit;
+ break;
+ case WindowType::EDIT:
+ pNewWindow = VclPtr<Edit>::Create( pParent, nWinBits );
+ *ppNewComp = new VCLXEdit;
+ break;
+ case WindowType::ERRORBOX:
+ pNewWindow = VclPtr<ErrorBox>::Create( pParent, nMessBoxStyle, nWinBits, OUString() );
+ *ppNewComp = new VCLXMessageBox;
+ break;
+ case WindowType::FIXEDBITMAP:
+ pNewWindow = VclPtr<FixedBitmap>::Create( pParent, nWinBits );
+ break;
+ case WindowType::FIXEDIMAGE:
+ pNewWindow = VclPtr<ImageControl>::Create( pParent, nWinBits );
+ *ppNewComp = new VCLXImageControl;
+ break;
+ case WindowType::FIXEDLINE:
+ pNewWindow = VclPtr<FixedLine>::Create( pParent, nWinBits );
+ break;
+ case WindowType::FIXEDTEXT:
+ pNewWindow = VclPtr<FixedText>::Create( pParent, nWinBits );
+ *ppNewComp = new VCLXFixedText;
+ break;
+ case WindowType::FLOATINGWINDOW:
+ pNewWindow = VclPtr<FloatingWindow>::Create( pParent, nWinBits );
+ break;
+ case WindowType::GROUPBOX:
+ pNewWindow = VclPtr<GroupBox>::Create( pParent, nWinBits );
+ if ( bFrameControl )
+ {
+ GroupBox* pGroupBox = static_cast< GroupBox* >( pNewWindow.get() );
+ *ppNewComp = new VCLXFrame;
+ // Frame control needs to receive
+ // Mouse events
+ pGroupBox->SetMouseTransparent( false );
+ }
+ break;
+ case WindowType::HELPBUTTON:
+ pNewWindow = VclPtr<HelpButton>::Create( pParent, nWinBits );
+ *ppNewComp = new VCLXButton;
+ break;
+ case WindowType::IMAGEBUTTON:
+ pNewWindow = VclPtr<ImageButton>::Create( pParent, nWinBits );
+ *ppNewComp = new VCLXButton;
+ break;
+ case WindowType::INFOBOX:
+ pNewWindow = VclPtr<InfoBox>::Create( pParent, OUString() );
+ *ppNewComp = new VCLXMessageBox;
+ break;
+ case WindowType::LISTBOX:
+ pNewWindow = VclPtr<ListBox>::Create( pParent, nWinBits|WB_SIMPLEMODE|WB_AUTOHSCROLL );
+ static_cast<ListBox*>(pNewWindow.get())->EnableAutoSize( false );
+ *ppNewComp = new VCLXListBox;
+ break;
+ case WindowType::LONGCURRENCYBOX:
+ pNewWindow = VclPtr<LongCurrencyBox>::Create( pParent, nWinBits );
+ break;
+ case WindowType::MENUBUTTON:
+ pNewWindow = VclPtr<MenuButton>::Create( pParent, nWinBits );
+ *ppNewComp = new VCLXButton;
+ break;
+ case WindowType::MESSBOX:
+ pNewWindow = VclPtr<MessBox>::Create( pParent, nMessBoxStyle, nWinBits, OUString(), OUString() );
+ *ppNewComp = new VCLXMessageBox;
+ break;
+ case WindowType::METRICBOX:
+ pNewWindow = VclPtr<MetricBox>::Create( pParent, nWinBits );
+ break;
+ case WindowType::METRICFIELD:
+ pNewWindow = VclPtr<MetricField>::Create( pParent, nWinBits );
+ *ppNewComp = new VCLXMetricField;
+ static_cast<VCLXFormattedSpinField*>((*ppNewComp).get())->SetFormatter( static_cast<FormatterBase*>(static_cast<MetricField*>(pNewWindow.get())) );
+ break;
+ case WindowType::DIALOG:
+ case WindowType::MODELESSDIALOG:
+ {
+ // Modal/Modeless only via Show/Execute
+ if ( (pParent == nullptr ) && ( rDescriptor.ParentIndex == -1 ) )
+ pNewWindow = VclPtr<toolkit::ScrollableDialog>::Create( nullptr, nWinBits, Dialog::InitFlag::NoParent );
+ else
+ pNewWindow = VclPtr<toolkit::ScrollableDialog>::Create( pParent, nWinBits );
+ // #i70217# Don't always create a new component object. It's possible that VCL has called
+ // GetComponentInterface( sal_True ) in the Dialog ctor itself (see Window::IsTopWindow() )
+ // which creates a component object.
+ css::uno::Reference< css::awt::XWindowPeer > xWinPeer = pNewWindow->GetComponentInterface( false );
+ if ( xWinPeer.is() )
+ *ppNewComp = dynamic_cast< VCLXDialog* >( xWinPeer.get() );
+ else
+ *ppNewComp = new VCLXDialog;
+ }
+ break;
+ case WindowType::MOREBUTTON:
+ pNewWindow = VclPtr<MoreButton>::Create( pParent, nWinBits );
+ *ppNewComp = new VCLXButton;
+ break;
+ case WindowType::MULTILISTBOX:
+ pNewWindow = VclPtr<MultiListBox>::Create( pParent, nWinBits );
+ *ppNewComp = new VCLXListBox;
+ break;
+ case WindowType::NUMERICBOX:
+ pNewWindow = VclPtr<NumericBox>::Create( pParent, nWinBits );
+ break;
+ case WindowType::OKBUTTON:
+ pNewWindow = VclPtr<OKButton>::Create( pParent, nWinBits );
+ *ppNewComp = new VCLXButton;
+ break;
+ case WindowType::PATTERNBOX:
+ pNewWindow = VclPtr<PatternBox>::Create( pParent, nWinBits );
+ break;
+ case WindowType::PATTERNFIELD:
+ pNewWindow = VclPtr<PatternField>::Create( pParent, nWinBits );
+ *ppNewComp = new VCLXPatternField;
+ static_cast<VCLXFormattedSpinField*>((*ppNewComp).get())->SetFormatter( static_cast<FormatterBase*>(static_cast<PatternField*>(pNewWindow.get())) );
+ break;
+ case WindowType::PUSHBUTTON:
+ pNewWindow = VclPtr<PushButton>::Create( pParent, nWinBits );
+ *ppNewComp = new VCLXButton;
+ break;
+ case WindowType::QUERYBOX:
+ pNewWindow = VclPtr<QueryBox>::Create( pParent, nMessBoxStyle, nWinBits, OUString() );
+ *ppNewComp = new VCLXMessageBox;
+ break;
+ case WindowType::RADIOBUTTON:
+ pNewWindow = VclPtr<RadioButton>::Create(pParent, false, nWinBits);
+ *ppNewComp = new VCLXRadioButton;
+
+ // by default, disable RadioCheck
+ // Since the VCLXRadioButton really cares for its RadioCheck settings, this is important:
+ // if we enable it, the VCLXRadioButton will use RadioButton::Check instead of RadioButton::SetState
+ // This leads to a strange behaviour if the control is newly created: when settings the initial
+ // state to "checked", the RadioButton::Check (called because RadioCheck=sal_True) will uncheck
+ // _all_other_ radio buttons in the same group. However, at this moment the grouping of the controls
+ // is not really valid: the controls are grouped after they have been created, but we're still in
+ // the creation process, so the RadioButton::Check relies on invalid grouping information.
+ // 07.08.2001 - #87254# - frank.schoenheit@sun.com
+ static_cast<RadioButton*>(pNewWindow.get())->EnableRadioCheck( false );
+ break;
+ case WindowType::SCROLLBAR:
+ pNewWindow = VclPtr<ScrollBar>::Create( pParent, nWinBits );
+ *ppNewComp = new VCLXScrollBar;
+ break;
+ case WindowType::SCROLLBARBOX:
+ pNewWindow = VclPtr<ScrollBarBox>::Create( pParent, nWinBits );
+ break;
+ case WindowType::SPINBUTTON:
+ pNewWindow = VclPtr<SpinButton>::Create( pParent, nWinBits );
+ *ppNewComp = new ::toolkit::VCLXSpinButton;
+ break;
+ case WindowType::SPINFIELD:
+ pNewWindow = VclPtr<SpinField>::Create( pParent, nWinBits );
+ *ppNewComp = new VCLXNumericField;
+ break;
+ case WindowType::SPLITTER:
+ pNewWindow = VclPtr<Splitter>::Create( pParent, nWinBits );
+ break;
+ case WindowType::SPLITWINDOW:
+ pNewWindow = VclPtr<SplitWindow>::Create( pParent, nWinBits );
+ break;
+ case WindowType::STATUSBAR:
+ pNewWindow = VclPtr<StatusBar>::Create( pParent, nWinBits );
+ break;
+ case WindowType::TOOLKIT_SYSTEMCHILDWINDOW:
+ pNewWindow = VclPtr<SystemChildWindow>::Create( pParent, nWinBits );
+ *ppNewComp = new VCLXSystemDependentWindow();
+ break;
+ case WindowType::TABCONTROL:
+ pNewWindow = VclPtr<TabControl>::Create( pParent, nWinBits );
+ *ppNewComp = new VCLXMultiPage;
+ break;
+ case WindowType::TABDIALOG:
+ pNewWindow = VclPtr<TabDialog>::Create( pParent, nWinBits );
+ break;
+ case WindowType::TABPAGE:
+ {
+ pNewWindow = VclPtr<TabPage>::Create( pParent, nWinBits );
+ *ppNewComp = new VCLXTabPage;
+ }
+ break;
+ case WindowType::TIMEBOX:
+ pNewWindow = VclPtr<TimeBox>::Create( pParent, nWinBits );
+ break;
+ case WindowType::TIMEFIELD:
+ pNewWindow = VclPtr<TimeField>::Create( pParent, nWinBits );
+ static_cast<TimeField*>(pNewWindow.get())->EnableEmptyFieldValue( true );
+ *ppNewComp = new VCLXTimeField;
+ static_cast<VCLXFormattedSpinField*>((*ppNewComp).get())->SetFormatter( static_cast<FormatterBase*>(static_cast<TimeField*>(pNewWindow.get())) );
+ break;
+ case WindowType::TOOLBOX:
+ pNewWindow = VclPtr<ToolBox>::Create( pParent, nWinBits );
+ *ppNewComp = new VCLXToolBox;
+ break;
+ case WindowType::TRISTATEBOX:
+ pNewWindow = VclPtr<CheckBox>::Create( pParent, nWinBits );
+ static_cast<CheckBox*>(pNewWindow.get())->EnableTriState(true);
+ break;
+ case WindowType::WARNINGBOX:
+ pNewWindow = VclPtr<WarningBox>::Create( pParent, nMessBoxStyle, nWinBits, OUString() );
+ *ppNewComp = new VCLXMessageBox;
+ break;
+ case WindowType::WORKWINDOW:
+ case WindowType::WINDOW:
+ case WindowType::TOOLKIT_FRAMEWINDOW:
+ case WindowType::DOCKINGWINDOW:
+ if ( rDescriptor.Type == css::awt::WindowClass_TOP )
+ {
+ if (nType == WindowType::DOCKINGWINDOW )
+ pNewWindow = VclPtr<DockingWindow>::Create( pParent, nWinBits );
+ else
+ {
+ if ((pParent == nullptr) && rDescriptor.Parent.is())
+ {
+ // try to get a system dependent window handle
+ css::uno::Reference< css::awt::XSystemDependentWindowPeer > xSystemDepParent(rDescriptor.Parent, css::uno::UNO_QUERY);
+
+ if (xSystemDepParent.is())
+ {
+ sal_Int8 processID[16];
+
+ rtl_getGlobalProcessId( reinterpret_cast<sal_uInt8*>(processID) );
+
+ // coverity[overrun-buffer-arg : FALSE] - coverity has difficulty with css::uno::Sequence
+ css::uno::Sequence<sal_Int8> processIdSeq(processID, 16);
+
+ css::uno::Any anyHandle = xSystemDepParent->getWindowHandle(processIdSeq, SYSTEM_DEPENDENT_TYPE);
+
+ // use sal_Int64 here to accommodate all int types
+ // uno::Any shift operator will upcast if necessary
+ sal_Int64 nWindowHandle = 0;
+ bool bXEmbed = false;
+
+ bool bUseParentData = true;
+ if( ! (anyHandle >>= nWindowHandle) )
+ {
+ css::uno::Sequence< css::beans::NamedValue > aProps;
+ if( anyHandle >>= aProps )
+ {
+ for( const css::beans::NamedValue& rProp : std::as_const(aProps) )
+ {
+ if ( rProp.Name == "WINDOW" )
+ rProp.Value >>= nWindowHandle;
+ else if ( rProp.Name == "XEMBED" )
+ rProp.Value >>= bXEmbed;
+ }
+ }
+ else
+ bUseParentData = false;
+ }
+
+ if( bUseParentData )
+ {
+ SystemParentData aParentData;
+ aParentData.nSize = sizeof( aParentData );
+ #if defined MACOSX
+ aParentData.pView = reinterpret_cast<NSView*>(nWindowHandle);
+ #elif defined ANDROID
+ // Nothing
+ #elif defined IOS
+ // Nothing
+ #elif defined UNX
+ aParentData.aWindow = nWindowHandle;
+ aParentData.bXEmbedSupport = bXEmbed;
+ #elif defined _WIN32
+ aParentData.hWnd = reinterpret_cast<HWND>(nWindowHandle);
+ #endif
+ pNewWindow = VclPtr<WorkWindow>::Create( &aParentData );
+ }
+ }
+ }
+
+ if (!pNewWindow)
+ pNewWindow = VclPtr<WorkWindow>::Create( pParent, nWinBits );
+ }
+
+ *ppNewComp = new VCLXTopWindow();
+ }
+ else if ( rDescriptor.Type == css::awt::WindowClass_CONTAINER )
+ {
+ if (nType == WindowType::DOCKINGWINDOW )
+ pNewWindow = VclPtr<DockingWindow>::Create( pParent, nWinBits );
+ else
+ pNewWindow = VclPtr<vcl::Window>::Create( pParent, nWinBits );
+ *ppNewComp = new VCLXContainer;
+ }
+ else
+ {
+ if (nType == WindowType::DOCKINGWINDOW )
+ pNewWindow = VclPtr<DockingWindow>::Create( pParent, nWinBits );
+ else
+ pNewWindow = VclPtr<vcl::Window>::Create( pParent, nWinBits );
+ *ppNewComp = new VCLXWindow;
+ }
+ break;
+ case WindowType::CONTROL:
+ if ( aServiceName == "tabpagecontainer" )
+ {
+ // TabControl has a special case for tabs without border: they are displayed
+ // in a different way, so we need to ensure that this style is not set, so
+ // we can guarantee normal tab behavior
+ pNewWindow = VclPtr<TabControl>::Create( pParent, nWinBits & (~WB_NOBORDER));
+ *ppNewComp = new VCLXTabPageContainer;
+ }
+ else if ( aServiceName == "animatedimages" )
+ {
+ pNewWindow = VclPtr<Throbber>::Create( pParent, nWinBits );
+ *ppNewComp = new ::toolkit::AnimatedImagesPeer;
+ }
+ else if (aServiceName == "roadmap")
+ {
+ pNewWindow = VclPtr<::vcl::ORoadmap>::Create( pParent, WB_TABSTOP );
+ *ppNewComp = new SVTXRoadmap;
+ }
+ else if (aServiceName == "fixedhyperlink")
+ {
+ pNewWindow = VclPtr<FixedHyperlink>::Create( pParent, nWinBits );
+ *ppNewComp = new VCLXFixedHyperlink;
+ }
+ else if (aServiceName == "progressbar")
+ {
+ pNewWindow = VclPtr<ProgressBar>::Create( pParent, nWinBits, ProgressBar::BarStyle::Progress );
+ *ppNewComp = new VCLXProgressBar;
+ }
+ else if (aServiceName == "filecontrol")
+ {
+ pNewWindow = VclPtr<FileControl>::Create( pParent, nWinBits );
+ *ppNewComp = new VCLXFileControl;
+ }
+ else if (aServiceName == "tree")
+ {
+ rtl::Reference<TreeControlPeer> pPeer = new TreeControlPeer;
+ *ppNewComp = pPeer;
+ pNewWindow = pPeer->createVclControl( pParent, nWinBits );
+ }
+ else if (aServiceName == "formattedfield")
+ {
+ pNewWindow = VclPtr<FormattedField>::Create( pParent, nWinBits );
+ *ppNewComp = new SVTXFormattedField;
+ }
+ else if (aServiceName == "numericfield")
+ {
+ pNewWindow = VclPtr<DoubleNumericField>::Create( pParent, nWinBits );
+ *ppNewComp = new SVTXNumericField;
+ }
+ else if (aServiceName == "longcurrencyfield")
+ {
+ pNewWindow = VclPtr<DoubleCurrencyField>::Create( pParent, nWinBits );
+ *ppNewComp = new SVTXCurrencyField;
+ }
+ else if (aServiceName == "datefield")
+ {
+ pNewWindow = VclPtr<CalendarField>::Create(pParent, nWinBits);
+ static_cast<CalendarField*>(pNewWindow.get())->EnableToday();
+ static_cast<CalendarField*>(pNewWindow.get())->EnableNone();
+ static_cast<CalendarField*>(pNewWindow.get())->EnableEmptyFieldValue( true );
+ rtl::Reference<SVTXDateField> newComp = new SVTXDateField;
+ *ppNewComp = newComp;
+ newComp->SetFormatter( static_cast<FormatterBase*>(static_cast<DateField*>(pNewWindow.get())) );
+ }
+ else if (aServiceName == "grid")
+ {
+ pNewWindow = VclPtr<::svt::table::TableControl>::Create(pParent, nWinBits);
+ *ppNewComp = new SVTXGridControl;
+ }
+ break;
+ default:
+ OSL_ENSURE( false, "VCLXToolkit::ImplCreateWindow: unknown window type!" );
+ break;
+ }
+ }
+
+ // tdf#126717 default that formcontrols show accelerators
+ if (Control* pControl = dynamic_cast<Control*>(pNewWindow.get()))
+ pControl->SetShowAccelerator(true);
+ return pNewWindow;
+}
+
+css::uno::Reference< css::awt::XWindowPeer > VCLXToolkit::ImplCreateWindow(
+ const css::awt::WindowDescriptor& rDescriptor,
+ MessBoxStyle nForceMessBoxStyle )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ SolarMutexGuard aSolarGuard;
+
+ css::uno::Reference< css::awt::XVclWindowPeer > xRef;
+
+ VclPtr<vcl::Window> pParent;
+ if ( rDescriptor.Parent.is() )
+ {
+ VCLXWindow* pParentComponent = dynamic_cast<VCLXWindow*>( rDescriptor.Parent.get() );
+
+ // #103939# Don't throw assertion, may be it's a system dependent window, used in ImplCreateWindow.
+ // DBG_ASSERT( pParentComponent, "ParentComponent not valid" );
+
+ if ( pParentComponent )
+ pParent = pParentComponent->GetWindow();
+ }
+ std::pair<WinBits, MessBoxStyle> aPair = ImplGetWinBits( rDescriptor.WindowAttributes,
+ ImplGetComponentType( rDescriptor.WindowServiceName ) );
+ WinBits nWinBits = aPair.first;
+ aPair.second |= nForceMessBoxStyle;
+
+ rtl::Reference<VCLXWindow> pNewComp;
+
+ vcl::Window* pNewWindow = ImplCreateWindow( &pNewComp, rDescriptor, pParent, nWinBits, aPair.second );
+
+ DBG_ASSERT( pNewWindow, "createWindow: Unknown Component!" );
+ SAL_INFO_IF( !pNewComp, "toolkit", "createWindow: No special Interface!" );
+
+ if ( pNewWindow )
+ {
+ pNewWindow->SetCreatedWithToolkit( true );
+ //pNewWindow->SetPosPixel( Point() ); // do not force (0,0) position, keep default pos instead
+
+ if ( rDescriptor.WindowAttributes & css::awt::WindowAttribute::MINSIZE )
+ {
+ pNewWindow->SetSizePixel( Size() );
+ }
+ else if ( rDescriptor.WindowAttributes & css::awt::WindowAttribute::FULLSIZE )
+ {
+ if ( pParent )
+ pNewWindow->SetSizePixel( pParent->GetOutputSizePixel() );
+ }
+ else if ( !VCLUnoHelper::IsZero( rDescriptor.Bounds ) )
+ {
+ tools::Rectangle aRect = VCLRectangle( rDescriptor.Bounds );
+ pNewWindow->SetPosSizePixel( aRect.TopLeft(), aRect.GetSize() );
+ }
+
+ if ( !pNewComp )
+ {
+ // Default-Interface
+ xRef = pNewWindow->GetComponentInterface();
+ }
+ else
+ {
+ xRef = pNewComp;
+ pNewWindow->SetComponentInterface( xRef );
+ }
+ DBG_ASSERT( pNewWindow->GetComponentInterface( false ) == xRef,
+ "VCLXToolkit::createWindow: did #133706# resurge?" );
+
+ if ( rDescriptor.WindowAttributes & css::awt::WindowAttribute::SHOW )
+ pNewWindow->Show();
+ }
+
+ return xRef;
+}
+
+css::uno::Sequence< css::uno::Reference< css::awt::XWindowPeer > > VCLXToolkit::createWindows( const css::uno::Sequence< css::awt::WindowDescriptor >& rDescriptors )
+{
+ ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
+
+ sal_uInt32 nComponents = rDescriptors.getLength();
+ css::uno::Sequence< css::uno::Reference< css::awt::XWindowPeer > > aSeq( nComponents );
+ for ( sal_uInt32 n = 0; n < nComponents; n++ )
+ {
+ css::awt::WindowDescriptor aDescr = rDescriptors.getConstArray()[n];
+
+ if ( aDescr.ParentIndex == -1 )
+ aDescr.Parent = nullptr;
+ else if ( ( aDescr.ParentIndex >= 0 ) && ( o3tl::make_unsigned(aDescr.ParentIndex) < n ) )
+ aDescr.Parent = aSeq.getConstArray()[aDescr.ParentIndex];
+ aSeq.getArray()[n] = createWindow( aDescr );
+ }
+ return aSeq;
+}
+
+// css::awt::XSystemChildFactory
+css::uno::Reference< css::awt::XWindowPeer > VCLXToolkit::createSystemChild( const css::uno::Any& Parent, const css::uno::Sequence< sal_Int8 >& /*ProcessId*/, sal_Int16 nSystemType )
+{
+ VclPtr<vcl::Window> pChildWindow;
+ if ( nSystemType == SYSTEM_DEPENDENT_TYPE )
+ {
+ // use sal_Int64 here to accommodate all int types
+ // uno::Any shift operator will upcast if necessary
+ sal_Int64 nWindowHandle = 0;
+ bool bXEmbed = false;
+
+ bool bUseParentData = true;
+ if( ! (Parent >>= nWindowHandle) )
+ {
+ css::uno::Sequence< css::beans::NamedValue > aProps;
+ if( Parent >>= aProps )
+ {
+ for( const css::beans::NamedValue& rProp : std::as_const(aProps) )
+ {
+ if ( rProp.Name == "WINDOW" )
+ rProp.Value >>= nWindowHandle;
+ else if ( rProp.Name == "XEMBED" )
+ rProp.Value >>= bXEmbed;
+ }
+ }
+ else
+ bUseParentData = false;
+ }
+
+ if( bUseParentData )
+ {
+ SystemParentData aParentData;
+ aParentData.nSize = sizeof( aParentData );
+ #if defined MACOSX
+ aParentData.pView = reinterpret_cast<NSView*>(nWindowHandle);
+ #elif defined ANDROID
+ // Nothing
+ #elif defined IOS
+ // Nothing
+ #elif defined UNX
+ aParentData.aWindow = nWindowHandle;
+ aParentData.bXEmbedSupport = bXEmbed;
+ #elif defined _WIN32
+ aParentData.hWnd = reinterpret_cast<HWND>(nWindowHandle);
+ #endif
+ SolarMutexGuard aGuard;
+ try
+ {
+ pChildWindow.reset( VclPtr<WorkWindow>::Create( &aParentData ) );
+ }
+ catch ( const css::uno::RuntimeException & )
+ {
+ // system child window could not be created
+ DBG_UNHANDLED_EXCEPTION("toolkit");
+ pChildWindow.clear();
+ }
+ }
+ }
+ else if (nSystemType == css::lang::SystemDependent::SYSTEM_JAVA)
+ {
+ SolarMutexGuard aGuard;
+ pChildWindow.reset(VclPtr<WorkWindow>::Create(nullptr, Parent));
+ }
+
+ css::uno::Reference< css::awt::XVclWindowPeer > xPeer;
+ if ( pChildWindow )
+ {
+ rtl::Reference<VCLXTopWindow> pPeer = new VCLXTopWindow;
+ SolarMutexGuard aGuard;
+ pPeer->SetWindow( pChildWindow );
+ xPeer = pPeer;
+ pChildWindow->SetWindowPeer(xPeer, pPeer.get());
+ }
+
+ return xPeer;
+}
+
+// css::awt::XMessageBoxFactory
+css::uno::Reference< css::awt::XMessageBox > SAL_CALL VCLXToolkit::createMessageBox(
+ const css::uno::Reference< css::awt::XWindowPeer >& aParent,
+ css::awt::MessageBoxType eType,
+ ::sal_Int32 aButtons,
+ const OUString& aTitle,
+ const OUString& aMessage )
+{
+ css::awt::WindowDescriptor aDescriptor;
+
+ sal_Int32 nWindowAttributes = css::awt::WindowAttribute::BORDER|css::awt::WindowAttribute::MOVEABLE|css::awt::WindowAttribute::CLOSEABLE;
+
+ // Map button definitions to window attributes
+ if (( aButtons & 0x0000ffffL ) == css::awt::MessageBoxButtons::BUTTONS_OK )
+ nWindowAttributes |= css::awt::VclWindowPeerAttribute::OK;
+ else if (( aButtons & 0x0000ffffL ) == css::awt::MessageBoxButtons::BUTTONS_OK_CANCEL )
+ nWindowAttributes |= css::awt::VclWindowPeerAttribute::OK_CANCEL;
+ else if (( aButtons & 0x0000ffffL ) == css::awt::MessageBoxButtons::BUTTONS_YES_NO )
+ nWindowAttributes |= css::awt::VclWindowPeerAttribute::YES_NO;
+ else if (( aButtons & 0x0000ffffL ) == css::awt::MessageBoxButtons::BUTTONS_YES_NO_CANCEL )
+ nWindowAttributes |= css::awt::VclWindowPeerAttribute::YES_NO_CANCEL;
+ else if (( aButtons & 0x0000ffffL ) == css::awt::MessageBoxButtons::BUTTONS_RETRY_CANCEL )
+ nWindowAttributes |= css::awt::VclWindowPeerAttribute::RETRY_CANCEL;
+
+ // Map default button definitions to window attributes
+ if (sal_Int32( aButtons & 0xffff0000L ) == css::awt::MessageBoxButtons::DEFAULT_BUTTON_OK )
+ nWindowAttributes |= css::awt::VclWindowPeerAttribute::DEF_OK;
+ else if (sal_Int32( aButtons & 0xffff0000L ) == css::awt::MessageBoxButtons::DEFAULT_BUTTON_CANCEL )
+ nWindowAttributes |= css::awt::VclWindowPeerAttribute::DEF_CANCEL;
+ else if (sal_Int32( aButtons & 0xffff0000L ) == css::awt::MessageBoxButtons::DEFAULT_BUTTON_YES )
+ nWindowAttributes |= css::awt::VclWindowPeerAttribute::DEF_YES;
+ else if (sal_Int32( aButtons & 0xffff0000L ) == css::awt::MessageBoxButtons::DEFAULT_BUTTON_NO )
+ nWindowAttributes |= css::awt::VclWindowPeerAttribute::DEF_NO;
+ else if (sal_Int32( aButtons & 0xffff0000L ) == css::awt::MessageBoxButtons::DEFAULT_BUTTON_RETRY )
+ nWindowAttributes |= css::awt::VclWindowPeerAttribute::DEF_RETRY;
+
+ // No more bits for VclWindowPeerAttribute possible. Mapping must be
+ // done explicitly using VCL methods
+ MessBoxStyle nAddWinBits = MessBoxStyle::NONE;
+ if (( aButtons & 0x0000ffffL ) == css::awt::MessageBoxButtons::BUTTONS_ABORT_IGNORE_RETRY )
+ nAddWinBits |= MessBoxStyle::AbortRetryIgnore;
+ if ( sal_Int32( aButtons & 0xffff0000L ) == css::awt::MessageBoxButtons::DEFAULT_BUTTON_IGNORE )
+ nAddWinBits |= MessBoxStyle::DefaultIgnore;
+
+ OUString aType;
+ lcl_convertMessageBoxType( aType, eType );
+
+ aDescriptor.Type = css::awt::WindowClass_MODALTOP;
+ aDescriptor.WindowServiceName = aType;
+ aDescriptor.ParentIndex = -1;
+ aDescriptor.Parent = aParent;
+ aDescriptor.WindowAttributes = nWindowAttributes;
+ css::uno::Reference< css::awt::XMessageBox > xMsgBox(
+ ImplCreateWindow( aDescriptor, nAddWinBits ), css::uno::UNO_QUERY );
+ css::uno::Reference< css::awt::XWindow > xWindow( xMsgBox, css::uno::UNO_QUERY );
+ if ( xMsgBox.is() && xWindow.is() )
+ {
+ VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
+ if ( pWindow )
+ {
+ SolarMutexGuard aGuard;
+ xMsgBox->setCaptionText( aTitle );
+ xMsgBox->setMessageText( aMessage );
+ }
+ }
+
+ return xMsgBox;
+}
+
+css::uno::Reference< css::datatransfer::dnd::XDragGestureRecognizer > SAL_CALL VCLXToolkit::getDragGestureRecognizer( const css::uno::Reference< css::awt::XWindow >& window )
+{
+ SolarMutexGuard g;
+
+ VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( window );
+
+ if( pWindow )
+ return pWindow->GetDragGestureRecognizer();
+
+ return css::uno::Reference< css::datatransfer::dnd::XDragGestureRecognizer >();
+}
+
+css::uno::Reference< css::datatransfer::dnd::XDragSource > SAL_CALL VCLXToolkit::getDragSource( const css::uno::Reference< css::awt::XWindow >& window )
+{
+ SolarMutexGuard g;
+
+ VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( window );
+
+ if( pWindow )
+ return pWindow->GetDragSource();
+
+ return css::uno::Reference< css::datatransfer::dnd::XDragSource >();
+}
+
+css::uno::Reference< css::datatransfer::dnd::XDropTarget > SAL_CALL VCLXToolkit::getDropTarget( const css::uno::Reference< css::awt::XWindow >& window )
+{
+ SolarMutexGuard g;
+
+ VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( window );
+
+ if( pWindow )
+ return pWindow->GetDropTarget();
+
+ return css::uno::Reference< css::datatransfer::dnd::XDropTarget >();
+}
+
+css::uno::Reference< css::datatransfer::clipboard::XClipboard > SAL_CALL VCLXToolkit::getClipboard( const OUString& clipboardName )
+{
+ if( clipboardName.isEmpty() )
+ {
+ if( !mxClipboard.is() )
+ {
+ // remember clipboard here
+ mxClipboard = css::datatransfer::clipboard::SystemClipboard::create(
+ comphelper::getProcessComponentContext());
+ }
+
+ return mxClipboard;
+ }
+
+ else if( clipboardName == "Selection" )
+ {
+ return mxSelection;
+ }
+
+ return css::uno::Reference< css::datatransfer::clipboard::XClipboard >();
+}
+
+// XServiceInfo
+OUString VCLXToolkit::getImplementationName()
+{
+ return "stardiv.Toolkit.VCLXToolkit";
+}
+
+sal_Bool VCLXToolkit::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+css::uno::Sequence< OUString > VCLXToolkit::getSupportedServiceNames()
+{
+ return css::uno::Sequence<OUString>{
+ "com.sun.star.awt.Toolkit", "stardiv.vcl.VclToolkit"};
+}
+
+// css::awt::XExtendedToolkit:
+
+// virtual
+::sal_Int32 SAL_CALL VCLXToolkit::getTopWindowCount()
+{
+ return static_cast< ::sal_Int32 >(::Application::GetTopWindowCount());
+ // XXX numeric overflow
+}
+
+// virtual
+css::uno::Reference< css::awt::XTopWindow > SAL_CALL
+VCLXToolkit::getTopWindow(::sal_Int32 nIndex)
+{
+ vcl::Window * p = ::Application::GetTopWindow(static_cast< tools::Long >(nIndex));
+ // XXX numeric overflow
+ return css::uno::Reference< css::awt::XTopWindow >(
+ p == nullptr ? nullptr : static_cast< css::awt::XWindow * >(p->GetWindowPeer()),
+ css::uno::UNO_QUERY);
+}
+
+// virtual
+css::uno::Reference< css::awt::XTopWindow > SAL_CALL
+VCLXToolkit::getActiveTopWindow()
+{
+ vcl::Window * p = ::Application::GetActiveTopWindow();
+ return css::uno::Reference< css::awt::XTopWindow >(
+ p == nullptr ? nullptr : static_cast< css::awt::XWindow * >(p->GetWindowPeer()),
+ css::uno::UNO_QUERY);
+}
+
+// virtual
+void SAL_CALL VCLXToolkit::addTopWindowListener(
+ css::uno::Reference< css::awt::XTopWindowListener > const & rListener)
+{
+ OSL_ENSURE(rListener.is(), "Null rListener");
+ ::osl::ClearableMutexGuard aGuard(rBHelper.rMutex);
+ if (rBHelper.bDisposed || rBHelper.bInDispose)
+ {
+ aGuard.clear();
+ rListener->disposing(
+ css::lang::EventObject(
+ getXWeak()));
+ }
+ else if (m_aTopWindowListeners.addInterface(rListener) == 1
+ && !m_bEventListener)
+ {
+ m_bEventListener = true;
+ ::Application::AddEventListener(m_aEventListenerLink);
+ }
+}
+
+// virtual
+void SAL_CALL VCLXToolkit::removeTopWindowListener(
+ css::uno::Reference< css::awt::XTopWindowListener > const & rListener)
+{
+ ::osl::MutexGuard aGuard(rBHelper.rMutex);
+ if (!(rBHelper.bDisposed || rBHelper.bInDispose)
+ && m_aTopWindowListeners.removeInterface(rListener) == 0
+ && m_aFocusListeners.getLength() == 0 && m_bEventListener)
+ {
+ ::Application::RemoveEventListener(m_aEventListenerLink);
+ m_bEventListener = false;
+ }
+}
+
+// virtual
+void SAL_CALL VCLXToolkit::addKeyHandler(
+ css::uno::Reference< css::awt::XKeyHandler > const & rHandler)
+{
+ OSL_ENSURE(rHandler.is(), "Null rHandler");
+ ::osl::ClearableMutexGuard aGuard(rBHelper.rMutex);
+ if (rBHelper.bDisposed || rBHelper.bInDispose)
+ {
+ aGuard.clear();
+ rHandler->disposing(
+ css::lang::EventObject(
+ getXWeak()));
+ }
+ else if (m_aKeyHandlers.addInterface(rHandler) == 1 && !m_bKeyListener)
+ {
+ m_bKeyListener = true;
+ ::Application::AddKeyListener(m_aKeyListenerLink);
+ }
+}
+
+// virtual
+void SAL_CALL VCLXToolkit::removeKeyHandler(
+ css::uno::Reference< css::awt::XKeyHandler > const & rHandler)
+{
+ ::osl::MutexGuard aGuard(rBHelper.rMutex);
+ if (!(rBHelper.bDisposed || rBHelper.bInDispose)
+ && m_aKeyHandlers.removeInterface(rHandler) == 0 && m_bKeyListener)
+ {
+ ::Application::RemoveKeyListener(m_aKeyListenerLink);
+ m_bKeyListener = false;
+ }
+}
+
+// virtual
+void SAL_CALL VCLXToolkit::addFocusListener(
+ css::uno::Reference< css::awt::XFocusListener > const & rListener)
+{
+ OSL_ENSURE(rListener.is(), "Null rListener");
+ ::osl::ClearableMutexGuard aGuard(rBHelper.rMutex);
+ if (rBHelper.bDisposed || rBHelper.bInDispose)
+ {
+ aGuard.clear();
+ rListener->disposing(
+ css::lang::EventObject(
+ getXWeak()));
+ }
+ else if (m_aFocusListeners.addInterface(rListener) == 1
+ && !m_bEventListener)
+ {
+ m_bEventListener = true;
+ ::Application::AddEventListener(m_aEventListenerLink);
+ }
+}
+
+// virtual
+void SAL_CALL VCLXToolkit::removeFocusListener(
+ css::uno::Reference< css::awt::XFocusListener > const & rListener)
+{
+ ::osl::MutexGuard aGuard(rBHelper.rMutex);
+ if (!(rBHelper.bDisposed || rBHelper.bInDispose)
+ && m_aFocusListeners.removeInterface(rListener) == 0
+ && m_aTopWindowListeners.getLength() == 0 && m_bEventListener)
+ {
+ ::Application::RemoveEventListener(m_aEventListenerLink);
+ m_bEventListener = false;
+ }
+}
+
+// virtual
+void SAL_CALL VCLXToolkit::fireFocusGained(
+ css::uno::Reference<
+ css::uno::XInterface > const &)
+{
+}
+
+// virtual
+void SAL_CALL VCLXToolkit::fireFocusLost(
+ css::uno::Reference<
+ css::uno::XInterface > const &)
+{
+}
+
+
+IMPL_LINK(VCLXToolkit, eventListenerHandler, ::VclSimpleEvent&, rEvent, void)
+{
+ switch (rEvent.GetId())
+ {
+ case VclEventId::WindowShow:
+ callTopWindowListeners(
+ &rEvent, &css::awt::XTopWindowListener::windowOpened);
+ break;
+ case VclEventId::WindowHide:
+ callTopWindowListeners(
+ &rEvent, &css::awt::XTopWindowListener::windowClosed);
+ break;
+ case VclEventId::WindowActivate:
+ callTopWindowListeners(
+ &rEvent, &css::awt::XTopWindowListener::windowActivated);
+ break;
+ case VclEventId::WindowDeactivate:
+ callTopWindowListeners(
+ &rEvent, &css::awt::XTopWindowListener::windowDeactivated);
+ break;
+ case VclEventId::WindowClose:
+ callTopWindowListeners(
+ &rEvent, &css::awt::XTopWindowListener::windowClosing);
+ break;
+ case VclEventId::WindowGetFocus:
+ callFocusListeners(&rEvent, true);
+ break;
+ case VclEventId::WindowLoseFocus:
+ callFocusListeners(&rEvent, false);
+ break;
+ case VclEventId::WindowMinimize:
+ callTopWindowListeners(
+ &rEvent, &css::awt::XTopWindowListener::windowMinimized);
+ break;
+ case VclEventId::WindowNormalize:
+ callTopWindowListeners(
+ &rEvent, &css::awt::XTopWindowListener::windowNormalized);
+ break;
+ default: break;
+ }
+}
+
+IMPL_LINK(VCLXToolkit, keyListenerHandler, ::VclWindowEvent&, rEvent, bool)
+{
+ switch (rEvent.GetId())
+ {
+ case VclEventId::WindowKeyInput:
+ return callKeyHandlers(&rEvent, true);
+ case VclEventId::WindowKeyUp:
+ return callKeyHandlers(&rEvent, false);
+ default: break;
+ }
+ return false;
+}
+
+void VCLXToolkit::callTopWindowListeners(
+ ::VclSimpleEvent const * pEvent,
+ void (SAL_CALL css::awt::XTopWindowListener::* pFn)(
+ css::lang::EventObject const &))
+{
+ vcl::Window * pWindow
+ = static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow();
+ if (!pWindow->IsTopWindow())
+ return;
+
+ std::vector< css::uno::Reference< css::awt::XTopWindowListener > >
+ aListeners(m_aTopWindowListeners.getElements());
+ if (aListeners.empty())
+ return;
+
+ css::lang::EventObject aAwtEvent(
+ static_cast< css::awt::XWindow * >(pWindow->GetWindowPeer()));
+ for (const css::uno::Reference<css::awt::XTopWindowListener> & xListener : aListeners)
+ {
+ try
+ {
+ (xListener.get()->*pFn)(aAwtEvent);
+ }
+ catch (const css::uno::RuntimeException &)
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit");
+ }
+ }
+}
+
+bool VCLXToolkit::callKeyHandlers(::VclSimpleEvent const * pEvent,
+ bool bPressed)
+{
+ std::vector< css::uno::Reference< css::awt::XKeyHandler > >
+ aHandlers(m_aKeyHandlers.getElements());
+
+ if (!aHandlers.empty())
+ {
+ vcl::Window * pWindow = static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow();
+
+ // See implementation in vclxwindow.cxx for mapping between VCL and UNO AWT event
+ ::KeyEvent * pKeyEvent = static_cast< ::KeyEvent * >(
+ static_cast< ::VclWindowEvent const * >(pEvent)->GetData());
+ css::awt::KeyEvent aAwtEvent(
+ static_cast< css::awt::XWindow * >(pWindow->GetWindowPeer()),
+ (pKeyEvent->GetKeyCode().IsShift()
+ ? css::awt::KeyModifier::SHIFT : 0)
+ | (pKeyEvent->GetKeyCode().IsMod1()
+ ? css::awt::KeyModifier::MOD1 : 0)
+ | (pKeyEvent->GetKeyCode().IsMod2()
+ ? css::awt::KeyModifier::MOD2 : 0)
+ | (pKeyEvent->GetKeyCode().IsMod3()
+ ? css::awt::KeyModifier::MOD3 : 0),
+ pKeyEvent->GetKeyCode().GetCode(), pKeyEvent->GetCharCode(),
+ sal::static_int_cast< sal_Int16 >(
+ pKeyEvent->GetKeyCode().GetFunction()));
+ for (const css::uno::Reference<css::awt::XKeyHandler> & xHandler : aHandlers)
+ {
+ try
+ {
+ if (bPressed ? xHandler->keyPressed(aAwtEvent)
+ : xHandler->keyReleased(aAwtEvent))
+ return true;
+ }
+ catch (const css::uno::RuntimeException &)
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit");
+ }
+ }
+ }
+ return false;
+}
+
+void VCLXToolkit::callFocusListeners(::VclSimpleEvent const * pEvent,
+ bool bGained)
+{
+ vcl::Window * pWindow
+ = static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow();
+ if (!pWindow->IsTopWindow())
+ return;
+
+ std::vector< css::uno::Reference< css::awt::XFocusListener > >
+ aListeners(m_aFocusListeners.getElements());
+ if (aListeners.empty())
+ return;
+
+ // Ignore the interior of compound controls when determining the
+ // window that gets the focus next (see implementation in
+ // vclxwindow.cxx for mapping between VCL and UNO AWT event):
+ css::uno::Reference< css::uno::XInterface > xNext;
+ vcl::Window * pFocus = ::Application::GetFocusWindow();
+ for (vcl::Window * p = pFocus; p != nullptr; p = p->GetParent())
+ if (!p->IsCompoundControl())
+ {
+ pFocus = p;
+ break;
+ }
+ if (pFocus != nullptr)
+ xNext = pFocus->GetComponentInterface();
+ css::awt::FocusEvent aAwtEvent(
+ static_cast< css::awt::XWindow * >(pWindow->GetWindowPeer()),
+ static_cast<sal_Int16>(pWindow->GetGetFocusFlags()),
+ xNext, false);
+ for (const css::uno::Reference<css::awt::XFocusListener> & xListener : aListeners)
+ {
+ try
+ {
+ bGained ? xListener->focusGained(aAwtEvent)
+ : xListener->focusLost(aAwtEvent);
+ }
+ catch (const css::uno::RuntimeException &)
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit");
+ }
+ }
+}
+
+// css::awt::XReschedule:
+
+void SAL_CALL VCLXToolkit::reschedule()
+{
+ SolarMutexGuard aSolarGuard;
+ Application::Reschedule(true);
+}
+
+// css::awt::XFontMappingUse:
+void SAL_CALL VCLXToolkit::startTrackingFontMappingUse()
+{
+ SolarMutexGuard aSolarGuard;
+ OutputDevice::StartTrackingFontMappingUse();
+}
+
+css::uno::Sequence<css::awt::XFontMappingUseItem>
+SAL_CALL VCLXToolkit::finishTrackingFontMappingUse()
+{
+ SolarMutexGuard aSolarGuard;
+ OutputDevice::FontMappingUseData data = OutputDevice::FinishTrackingFontMappingUse();
+ css::uno::Sequence<css::awt::XFontMappingUseItem> ret( data.size());
+ css::awt::XFontMappingUseItem* retData = ret.getArray();
+ for( size_t i = 0; i < data.size(); ++i )
+ {
+ retData[ i ].originalFont = data[ i ].mOriginalFont;
+ retData[ i ].usedFonts = comphelper::arrayToSequence<OUString,OUString>
+ (data[ i ].mUsedFonts.data(), data[ i ].mUsedFonts.size());
+ retData[ i ].count = data[ i ].mCount;
+ }
+ return ret;
+}
+
+// css::awt::XToolkitExperimental
+
+void SAL_CALL VCLXToolkit::processEventsToIdle()
+{
+ SolarMutexGuard aSolarGuard;
+ comphelper::ProfileZone aZone("processEvents");
+ Scheduler::ProcessEventsToIdle();
+}
+
+sal_Int64 SAL_CALL VCLXToolkit::getOpenGLBufferSwapCounter()
+{
+#if HAVE_FEATURE_OPENGL
+ return OpenGLWrapper::getBufferSwapCounter();
+#else
+ return 0;
+#endif
+}
+
+void SAL_CALL VCLXToolkit::setDeterministicScheduling(sal_Bool bDeterministicMode)
+{
+ SolarMutexGuard aSolarGuard;
+ Scheduler::SetDeterministicMode(bDeterministicMode);
+}
+
+void SAL_CALL VCLXToolkit::pause(sal_Int32 nMilliseconds)
+{
+ new Pause(nMilliseconds);
+}
+
+void SAL_CALL VCLXToolkit::startRecording()
+{
+ comphelper::TraceEvent::startRecording();
+}
+
+void SAL_CALL VCLXToolkit::stopRecording()
+{
+ comphelper::TraceEvent::stopRecording();
+}
+
+css::uno::Sequence< OUString > VCLXToolkit::getRecordingAndClear()
+{
+ return comphelper::ProfileZone::getRecordingAndClear();
+}
+
+void VCLXToolkit::waitUntilAllIdlesDispatched()
+{
+ IdleTask::waitUntilIdleDispatched();
+}
+
+// css:awt:XToolkitRobot
+
+void SAL_CALL VCLXToolkit::keyPress( const css::awt::KeyEvent & aKeyEvent )
+{
+ css::uno::Reference<css::awt::XWindow> xWindow ( aKeyEvent.Source, css::uno::UNO_QUERY_THROW );
+ VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
+ if( !pWindow )
+ throw css::uno::RuntimeException( "invalid event source" );
+
+ ::KeyEvent aVCLKeyEvent = VCLUnoHelper::createVCLKeyEvent( aKeyEvent );
+ ::Application::PostKeyEvent( VclEventId::WindowKeyInput, pWindow, &aVCLKeyEvent );
+}
+
+void SAL_CALL VCLXToolkit::keyRelease( const css::awt::KeyEvent & aKeyEvent )
+{
+ css::uno::Reference<css::awt::XWindow> xWindow ( aKeyEvent.Source, css::uno::UNO_QUERY_THROW );
+ VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
+ if( !pWindow )
+ throw css::uno::RuntimeException( "invalid event source" );
+
+ ::KeyEvent aVCLKeyEvent = VCLUnoHelper::createVCLKeyEvent( aKeyEvent );
+ ::Application::PostKeyEvent( VclEventId::WindowKeyUp, pWindow, &aVCLKeyEvent );
+}
+
+
+void SAL_CALL VCLXToolkit::mousePress( const css::awt::MouseEvent & aMouseEvent )
+{
+ css::uno::Reference<css::awt::XWindow> xWindow ( aMouseEvent.Source, css::uno::UNO_QUERY_THROW );
+ VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
+ if( !pWindow )
+ throw css::uno::RuntimeException( "invalid event source" );
+
+ ::MouseEvent aVCLMouseEvent = VCLUnoHelper::createVCLMouseEvent( aMouseEvent );
+ ::Application::PostMouseEvent( VclEventId::WindowMouseButtonDown, pWindow, &aVCLMouseEvent );
+}
+
+void SAL_CALL VCLXToolkit::mouseRelease( const css::awt::MouseEvent & aMouseEvent )
+{
+ css::uno::Reference<css::awt::XWindow> xWindow ( aMouseEvent.Source, css::uno::UNO_QUERY_THROW );
+ VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
+ if( !pWindow )
+ throw css::uno::RuntimeException( "invalid event source" );
+
+ ::MouseEvent aVCLMouseEvent = VCLUnoHelper::createVCLMouseEvent( aMouseEvent );
+ ::Application::PostMouseEvent( VclEventId::WindowMouseButtonUp, pWindow, &aVCLMouseEvent );
+}
+
+void SAL_CALL VCLXToolkit::mouseMove( const css::awt::MouseEvent & aMouseEvent )
+{
+ css::uno::Reference<css::awt::XWindow> xWindow ( aMouseEvent.Source, css::uno::UNO_QUERY_THROW );
+ VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
+ if( !pWindow )
+ throw css::uno::RuntimeException( "invalid event source" );
+
+ ::MouseEvent aVCLMouseEvent = VCLUnoHelper::createVCLMouseEvent( aMouseEvent );
+ ::Application::PostMouseEvent( VclEventId::WindowMouseMove, pWindow, &aVCLMouseEvent );
+}
+
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+stardiv_Toolkit_VCLXToolkit_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new VCLXToolkit());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/awt/vclxtopwindow.cxx b/toolkit/source/awt/vclxtopwindow.cxx
new file mode 100644
index 0000000000..c0ce4d891d
--- /dev/null
+++ b/toolkit/source/awt/vclxtopwindow.cxx
@@ -0,0 +1,229 @@
+/* -*- 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/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/SystemDependent.hpp>
+#include <com/sun/star/awt/SystemDependentXWindow.hpp>
+
+#if defined ( MACOSX )
+#include <premac.h>
+#include <Cocoa/Cocoa.h>
+#include <postmac.h>
+#endif
+
+#include <vcl/sysdata.hxx>
+#include <o3tl/safeint.hxx>
+
+#include <awt/vclxtopwindow.hxx>
+#include <toolkit/awt/vclxmenu.hxx>
+
+#include <vcl/wrkwin.hxx>
+#include <vcl/syswin.hxx>
+#include <vcl/menu.hxx>
+#include <vcl/svapp.hxx>
+
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::lang::IndexOutOfBoundsException;
+
+
+css::uno::Any VCLXTopWindow::getWindowHandle( const css::uno::Sequence< sal_Int8 >& /*ProcessId*/, sal_Int16 SystemType )
+{
+ SolarMutexGuard aGuard;
+
+ // TODO, check the process id
+ css::uno::Any aRet;
+ vcl::Window* pWindow = VCLXContainer::GetWindow();
+ if ( pWindow )
+ {
+ const SystemEnvData* pSysData = static_cast<SystemWindow *>(pWindow)->GetSystemData();
+ if( pSysData )
+ {
+#if defined (_WIN32)
+ if( SystemType == css::lang::SystemDependent::SYSTEM_WIN32 )
+ {
+ aRet <<= reinterpret_cast<sal_IntPtr>(pSysData->hWnd);
+ }
+#elif defined(MACOSX)
+ if( SystemType == css::lang::SystemDependent::SYSTEM_MAC )
+ {
+ aRet <<= reinterpret_cast<sal_IntPtr>(pSysData->mpNSView);
+ }
+#elif defined(ANDROID)
+ // Nothing
+ (void) SystemType;
+#elif defined(IOS)
+ // Nothing
+ (void) SystemType;
+#elif defined(UNX)
+ if( SystemType == css::lang::SystemDependent::SYSTEM_XWINDOW )
+ {
+ css::awt::SystemDependentXWindow aSD;
+ aSD.DisplayPointer = sal::static_int_cast< sal_Int64 >(reinterpret_cast< sal_IntPtr >(pSysData->pDisplay));
+ aSD.WindowHandle = pSysData->GetWindowHandle(pWindow->ImplGetFrame());
+ aRet <<= aSD;
+ }
+#endif
+ }
+ }
+ return aRet;
+}
+
+void VCLXTopWindow::addTopWindowListener( const css::uno::Reference< css::awt::XTopWindowListener >& rxListener )
+{
+ SolarMutexGuard aGuard;
+
+ if (!IsDisposed())
+ GetTopWindowListeners().addInterface( rxListener );
+}
+
+void VCLXTopWindow::removeTopWindowListener( const css::uno::Reference< css::awt::XTopWindowListener >& rxListener )
+{
+ SolarMutexGuard aGuard;
+
+ if (!IsDisposed())
+ GetTopWindowListeners().removeInterface( rxListener );
+}
+
+void VCLXTopWindow::toFront( )
+{
+ SolarMutexGuard aGuard;
+
+ vcl::Window* pWindow = VCLXContainer::GetWindow();
+ if (pWindow)
+ pWindow->ToTop( ToTopFlags::RestoreWhenMin );
+}
+
+void VCLXTopWindow::toBack( )
+{
+}
+
+void VCLXTopWindow::setMenuBar( const css::uno::Reference< css::awt::XMenuBar >& rxMenu )
+{
+ SolarMutexGuard aGuard;
+
+ vcl::Window* pWindow = VCLXContainer::GetWindow();
+ if ( pWindow )
+ {
+ SystemWindow* pSystemWindow = static_cast<SystemWindow*>( pWindow );
+ pSystemWindow->SetMenuBar( nullptr );
+ if ( rxMenu.is() )
+ {
+ VCLXMenu* pMenu = dynamic_cast<VCLXMenu*>( rxMenu.get() );
+ if ( pMenu && !pMenu->IsPopupMenu() )
+ pSystemWindow->SetMenuBar( static_cast<MenuBar*>( pMenu->GetMenu() ));
+ }
+ }
+}
+
+
+sal_Bool SAL_CALL VCLXTopWindow::getIsMaximized()
+{
+ SolarMutexGuard aGuard;
+
+ const WorkWindow* pWindow = VCLXContainer::GetAsDynamic<WorkWindow>();
+ if ( !pWindow )
+ return false;
+
+ return pWindow->IsMaximized();
+}
+
+
+void SAL_CALL VCLXTopWindow::setIsMaximized( sal_Bool _ismaximized )
+{
+ SolarMutexGuard aGuard;
+
+ WorkWindow* pWindow = VCLXContainer::GetAsDynamic<WorkWindow>();
+ if ( !pWindow )
+ return;
+
+ pWindow->Maximize( _ismaximized );
+}
+
+
+sal_Bool SAL_CALL VCLXTopWindow::getIsMinimized()
+{
+ SolarMutexGuard aGuard;
+
+ const WorkWindow* pWindow = VCLXContainer::GetAsDynamic<WorkWindow>();
+ if ( !pWindow )
+ return false;
+
+ return pWindow->IsMinimized();
+}
+
+
+void SAL_CALL VCLXTopWindow::setIsMinimized( sal_Bool _isMinimized )
+{
+ SolarMutexGuard aGuard;
+
+ WorkWindow* pWindow = VCLXContainer::GetAsDynamic<WorkWindow>();
+ if ( !pWindow )
+ return;
+
+ _isMinimized ? pWindow->Minimize() : pWindow->Restore();
+}
+
+
+::sal_Int32 SAL_CALL VCLXTopWindow::getDisplay()
+{
+ SolarMutexGuard aGuard;
+
+ const SystemWindow* pWindow = VCLXContainer::GetAsDynamic<SystemWindow>();
+ if ( !pWindow )
+ return 0;
+
+ return pWindow->GetScreenNumber();
+}
+
+
+void SAL_CALL VCLXTopWindow::setDisplay( ::sal_Int32 _display )
+{
+ SolarMutexGuard aGuard;
+
+ if ( ( _display < 0 ) || ( o3tl::make_unsigned(_display) >= Application::GetScreenCount() ) )
+ throw IndexOutOfBoundsException();
+
+ SystemWindow* pWindow = VCLXContainer::GetAsDynamic<SystemWindow>();
+ if ( !pWindow )
+ return;
+
+ pWindow->SetScreenNumber( _display );
+}
+
+
+
+
+void VCLXTopWindow::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ VCLXContainer::ImplGetPropertyIds( rIds );
+}
+
+VCLXTopWindow::VCLXTopWindow()
+{
+}
+
+VCLXTopWindow::~VCLXTopWindow()
+{
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/awt/vclxwindow.cxx b/toolkit/source/awt/vclxwindow.cxx
new file mode 100644
index 0000000000..2448eaf646
--- /dev/null
+++ b/toolkit/source/awt/vclxwindow.cxx
@@ -0,0 +1,2611 @@
+/* -*- 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 <stdarg.h>
+#include <memory>
+#include <com/sun/star/awt/WindowEvent.hpp>
+#include <com/sun/star/awt/KeyEvent.hpp>
+#include <com/sun/star/awt/MouseEvent.hpp>
+#include <com/sun/star/awt/MouseWheelBehavior.hpp>
+#include <com/sun/star/awt/Style.hpp>
+#include <com/sun/star/awt/DockingEvent.hpp>
+#include <com/sun/star/awt/EndDockingEvent.hpp>
+#include <com/sun/star/awt/EndPopupModeEvent.hpp>
+#include <com/sun/star/awt/XWindowListener2.hpp>
+#include <com/sun/star/style/VerticalAlignment.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/text/WritingMode2.hpp>
+#include <toolkit/awt/vclxwindow.hxx>
+#include <awt/vclxpointer.hxx>
+#include <toolkit/awt/vclxwindows.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <helper/property.hxx>
+#include <rtl/math.hxx>
+#include <sal/log.hxx>
+#include <utility>
+#include <vcl/toolkit/floatwin.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <tools/color.hxx>
+#include <tools/fract.hxx>
+#include <tools/debug.hxx>
+#include <vcl/event.hxx>
+#include <vcl/dockwin.hxx>
+#include <vcl/pdfextoutdevdata.hxx>
+#include <vcl/tabpage.hxx>
+#include <vcl/ctrl.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/commandevent.hxx>
+#include <comphelper/flagguard.hxx>
+#include <comphelper/interfacecontainer3.hxx>
+#include <comphelper/profilezone.hxx>
+#include "stylesettings.hxx"
+#include <tools/urlobj.hxx>
+
+#include <helper/accessibilityclient.hxx>
+#include <helper/unopropertyarrayhelper.hxx>
+
+using namespace ::com::sun::star;
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::UNO_QUERY;
+using ::com::sun::star::lang::EventObject;
+using ::com::sun::star::awt::XWindowListener2;
+using ::com::sun::star::awt::XDockableWindowListener;
+using ::com::sun::star::awt::XDevice;
+using ::com::sun::star::awt::XStyleSettings;
+using ::com::sun::star::lang::DisposedException;
+using ::com::sun::star::style::VerticalAlignment;
+using ::com::sun::star::style::VerticalAlignment_TOP;
+using ::com::sun::star::style::VerticalAlignment_MIDDLE;
+using ::com::sun::star::style::VerticalAlignment_BOTTOM;
+
+namespace WritingMode2 = ::com::sun::star::text::WritingMode2;
+
+
+//= VCLXWindowImpl
+
+class VCLXWindowImpl
+{
+private:
+ typedef ::std::vector< VCLXWindow::Callback > CallbackArray;
+
+private:
+ VCLXWindow& mrAntiImpl;
+ ::toolkit::AccessibilityClient maAccFactory;
+ bool mbDisposed;
+ bool mbDrawingOntoParent; // no bit mask, is passed around by reference
+ bool mbEnableVisible;
+ bool mbDirectVisible;
+
+ ::osl::Mutex maListenerContainerMutex;
+ ::comphelper::OInterfaceContainerHelper3<css::awt::XWindowListener2> maWindow2Listeners;
+ ::comphelper::OInterfaceContainerHelper3<XDockableWindowListener> maDockableWindowListeners;
+ EventListenerMultiplexer maEventListeners;
+ FocusListenerMultiplexer maFocusListeners;
+ WindowListenerMultiplexer maWindowListeners;
+ KeyListenerMultiplexer maKeyListeners;
+ MouseListenerMultiplexer maMouseListeners;
+ MouseMotionListenerMultiplexer maMouseMotionListeners;
+ PaintListenerMultiplexer maPaintListeners;
+ VclContainerListenerMultiplexer maContainerListeners;
+ TopWindowListenerMultiplexer maTopWindowListeners;
+
+ CallbackArray maCallbackEvents;
+ ImplSVEvent * mnCallbackEventId;
+
+public:
+ bool mbDisposing : 1;
+ bool mbDesignMode : 1;
+ bool mbSynthesizingVCLEvent : 1;
+ bool mbWithDefaultProps : 1;
+
+ sal_uLong mnListenerLockLevel;
+ sal_Int16 mnWritingMode;
+ sal_Int16 mnContextWritingMode;
+
+ std::unique_ptr<UnoPropertyArrayHelper>
+ mpPropHelper;
+
+ css::uno::Reference< css::accessibility::XAccessibleContext >
+ mxAccessibleContext;
+ css::uno::Reference< css::awt::XGraphics >
+ mxViewGraphics;
+ rtl::Reference< toolkit::WindowStyleSettings >
+ mxWindowStyleSettings;
+
+public:
+ bool& getDrawingOntoParent_ref() { return mbDrawingOntoParent; }
+
+public:
+ /** ctor
+ @param _pAntiImpl
+ the <type>VCLXWindow</type> instance which the object belongs to. Must
+ live longer then the object just being constructed.
+ */
+ VCLXWindowImpl( VCLXWindow& _rAntiImpl, bool _bWithDefaultProps );
+
+ VCLXWindowImpl( const VCLXWindowImpl& ) = delete;
+ const VCLXWindowImpl& operator=(const VCLXWindowImpl&) = delete;
+
+ /** synchronously mbEnableVisible
+ */
+ void setEnableVisible( bool bEnableVisible ) { mbEnableVisible = bEnableVisible; }
+ bool isEnableVisible() const { return mbEnableVisible; }
+ /** synchronously mbDirectVisible;
+ */
+ void setDirectVisible( bool bDirectVisible ) { mbDirectVisible = bDirectVisible; }
+ bool isDirectVisible() const { return mbDirectVisible; }
+
+ /** impl-version of VCLXWindow::ImplExecuteAsyncWithoutSolarLock
+ */
+ void callBackAsync( const VCLXWindow::Callback& i_callback );
+
+ /** notifies the object that its VCLXWindow is being disposed
+ */
+ void disposing();
+
+ ::toolkit::AccessibilityClient& getAccessibleFactory()
+ {
+ return maAccFactory;
+ }
+
+ Reference< XStyleSettings > getStyleSettings();
+
+ /** returns the container of registered XWindowListener2 listeners
+ */
+ ::comphelper::OInterfaceContainerHelper3<css::awt::XWindowListener2>& getWindow2Listeners() { return maWindow2Listeners; }
+ ::comphelper::OInterfaceContainerHelper3<XDockableWindowListener>& getDockableWindowListeners() { return maDockableWindowListeners; }
+ EventListenerMultiplexer& getEventListeners() { return maEventListeners; }
+ FocusListenerMultiplexer& getFocusListeners() { return maFocusListeners; }
+ WindowListenerMultiplexer& getWindowListeners() { return maWindowListeners; }
+ KeyListenerMultiplexer& getKeyListeners() { return maKeyListeners; }
+ MouseListenerMultiplexer& getMouseListeners() { return maMouseListeners; }
+ MouseMotionListenerMultiplexer& getMouseMotionListeners() { return maMouseMotionListeners; }
+ PaintListenerMultiplexer& getPaintListeners() { return maPaintListeners; }
+ VclContainerListenerMultiplexer& getContainerListeners() { return maContainerListeners; }
+ TopWindowListenerMultiplexer& getTopWindowListeners() { return maTopWindowListeners; }
+
+private:
+ DECL_LINK( OnProcessCallbacks, void*, void );
+};
+
+
+VCLXWindowImpl::VCLXWindowImpl( VCLXWindow& _rAntiImpl, bool _bWithDefaultProps )
+ :mrAntiImpl( _rAntiImpl )
+ ,mbDisposed( false )
+ ,mbDrawingOntoParent( false )
+ ,mbEnableVisible(true)
+ ,mbDirectVisible(true)
+ ,maWindow2Listeners( maListenerContainerMutex )
+ ,maDockableWindowListeners( maListenerContainerMutex )
+ ,maEventListeners( _rAntiImpl )
+ ,maFocusListeners( _rAntiImpl )
+ ,maWindowListeners( _rAntiImpl )
+ ,maKeyListeners( _rAntiImpl )
+ ,maMouseListeners( _rAntiImpl )
+ ,maMouseMotionListeners( _rAntiImpl )
+ ,maPaintListeners( _rAntiImpl )
+ ,maContainerListeners( _rAntiImpl )
+ ,maTopWindowListeners( _rAntiImpl )
+ ,mnCallbackEventId( nullptr )
+ ,mbDisposing( false )
+ ,mbDesignMode( false )
+ ,mbSynthesizingVCLEvent( false )
+ ,mbWithDefaultProps( _bWithDefaultProps )
+ ,mnListenerLockLevel( 0 )
+ ,mnWritingMode( WritingMode2::CONTEXT )
+ ,mnContextWritingMode( WritingMode2::CONTEXT )
+{
+}
+
+void VCLXWindowImpl::disposing()
+{
+ SolarMutexGuard aGuard;
+
+ assert(!mbDisposed);
+
+ mbDisposed = true;
+
+ if ( mnCallbackEventId )
+ {
+ Application::RemoveUserEvent( mnCallbackEventId );
+ mnCallbackEventId = nullptr;
+ // we acquired our VCLXWindow once before posting the event, release this one ref now
+ mrAntiImpl.release();
+ }
+ maCallbackEvents.clear();
+
+ css::lang::EventObject aEvent;
+ aEvent.Source = mrAntiImpl;
+
+ maDockableWindowListeners.disposeAndClear( aEvent );
+ maEventListeners.disposeAndClear( aEvent );
+ maFocusListeners.disposeAndClear( aEvent );
+ maWindowListeners.disposeAndClear( aEvent );
+ maKeyListeners.disposeAndClear( aEvent );
+ maMouseListeners.disposeAndClear( aEvent );
+ maMouseMotionListeners.disposeAndClear( aEvent );
+ maPaintListeners.disposeAndClear( aEvent );
+ maContainerListeners.disposeAndClear( aEvent );
+ maTopWindowListeners.disposeAndClear( aEvent );
+ maWindow2Listeners.disposeAndClear( aEvent );
+
+ if ( mxWindowStyleSettings )
+ mxWindowStyleSettings->dispose();
+ mxWindowStyleSettings.clear();
+}
+
+
+void VCLXWindowImpl::callBackAsync( const VCLXWindow::Callback& i_callback )
+{
+ DBG_TESTSOLARMUTEX();
+ maCallbackEvents.push_back( i_callback );
+ if ( !mnCallbackEventId )
+ {
+ // ensure our VCLXWindow is not destroyed while the event is underway
+ mrAntiImpl.acquire();
+ mnCallbackEventId = Application::PostUserEvent( LINK( this, VCLXWindowImpl, OnProcessCallbacks ) );
+ }
+}
+
+
+IMPL_LINK_NOARG(VCLXWindowImpl, OnProcessCallbacks, void*, void)
+{
+ const Reference< uno::XInterface > xKeepAlive( mrAntiImpl );
+
+ SAL_INFO("toolkit.controls", "OnProcessCallbacks grabbing solarmutex");
+
+ // work on a copy of the callback array
+ CallbackArray aCallbacksCopy;
+ {
+ SolarMutexGuard aGuard;
+ aCallbacksCopy.swap(maCallbackEvents);
+
+ // we acquired our VCLXWindow once before posting the event, release this one ref now
+ mrAntiImpl.release();
+
+ assert( mnCallbackEventId && "should not be possible to call us if the event was removed");
+
+ mnCallbackEventId = nullptr;
+ }
+
+ {
+ SAL_INFO("toolkit.controls", "OnProcessCallbacks relinquished solarmutex");
+ SolarMutexReleaser aReleaseSolar;
+ for (const auto& rCallback : aCallbacksCopy)
+ {
+ rCallback();
+ }
+ }
+}
+
+Reference< XStyleSettings > VCLXWindowImpl::getStyleSettings()
+{
+ SolarMutexGuard aGuard;
+ if ( mbDisposed )
+ throw DisposedException( OUString(), mrAntiImpl );
+ if ( !mxWindowStyleSettings.is() )
+ mxWindowStyleSettings = new ::toolkit::WindowStyleSettings( maListenerContainerMutex, mrAntiImpl );
+ return mxWindowStyleSettings;
+}
+
+
+// Uses an out-parameter instead of return value, due to the object reference
+
+static void ImplInitWindowEvent( css::awt::WindowEvent& rEvent, vcl::Window const * pWindow )
+{
+ Point aPos = pWindow->GetPosPixel();
+ Size aSz = pWindow->GetSizePixel();
+
+ rEvent.X = aPos.X();
+ rEvent.Y = aPos.Y();
+
+ rEvent.Width = aSz.Width();
+ rEvent.Height = aSz.Height();
+
+ pWindow->GetBorder( rEvent.LeftInset, rEvent.TopInset, rEvent.RightInset, rEvent.BottomInset );
+}
+
+VCLXWindow::VCLXWindow( bool _bWithDefaultProps )
+{
+ mpImpl.reset( new VCLXWindowImpl( *this, _bWithDefaultProps ) );
+}
+
+VCLXWindow::~VCLXWindow()
+{
+ assert(mpImpl->mbDisposing && "forgot to call dispose()");
+}
+
+
+void VCLXWindow::ImplExecuteAsyncWithoutSolarLock( const Callback& i_callback )
+{
+ if (mpImpl->mbDisposing)
+ return;
+ mpImpl->callBackAsync( i_callback );
+}
+
+
+::toolkit::IAccessibleFactory& VCLXWindow::getAccessibleFactory()
+{
+ return mpImpl->getAccessibleFactory().getFactory();
+}
+
+void VCLXWindow::SetWindow( const VclPtr<vcl::Window> &pWindow )
+{
+ assert(!mpImpl->mbDisposing || !pWindow);
+
+ if ( GetWindow() )
+ {
+ GetWindow()->RemoveEventListener( LINK( this, VCLXWindow, WindowEventListener ) );
+// GetWindow()->DbgAssertNoEventListeners();
+ }
+
+ SetOutputDevice( pWindow ? pWindow->GetOutDev() : nullptr );
+
+ if ( GetWindow() )
+ {
+ GetWindow()->AddEventListener( LINK( this, VCLXWindow, WindowEventListener ) );
+ bool bDirectVisible = pWindow && pWindow->IsVisible();
+ mpImpl->setDirectVisible( bDirectVisible );
+ }
+}
+
+void VCLXWindow::suspendVclEventListening( )
+{
+ ++mpImpl->mnListenerLockLevel;
+}
+
+void VCLXWindow::resumeVclEventListening( )
+{
+ DBG_ASSERT( mpImpl->mnListenerLockLevel, "VCLXWindow::resumeVclEventListening: not suspended!" );
+ --mpImpl->mnListenerLockLevel;
+}
+
+void VCLXWindow::notifyWindowRemoved( vcl::Window const & _rWindow )
+{
+ if ( mpImpl->getContainerListeners().getLength() )
+ {
+ awt::VclContainerEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.Child = static_cast< XWindow* >( _rWindow.GetWindowPeer() );
+ mpImpl->getContainerListeners().windowRemoved( aEvent );
+ }
+}
+
+IMPL_LINK( VCLXWindow, WindowEventListener, VclWindowEvent&, rEvent, void )
+{
+ if ( mpImpl->mbDisposing || mpImpl->mnListenerLockLevel )
+ return;
+
+ DBG_ASSERT( rEvent.GetWindow() && GetWindow(), "Window???" );
+ ProcessWindowEvent( rEvent );
+}
+
+namespace
+{
+ struct CallWindow2Listener
+ {
+ CallWindow2Listener( ::comphelper::OInterfaceContainerHelper3<css::awt::XWindowListener2>& i_rWindow2Listeners, const bool i_bEnabled, EventObject i_Event )
+ :m_rWindow2Listeners( i_rWindow2Listeners )
+ ,m_bEnabled( i_bEnabled )
+ ,m_aEvent(std::move( i_Event ))
+ {
+ }
+
+ void operator()()
+ {
+ m_rWindow2Listeners.notifyEach( m_bEnabled ? &XWindowListener2::windowEnabled : &XWindowListener2::windowDisabled, m_aEvent );
+ }
+
+ ::comphelper::OInterfaceContainerHelper3<css::awt::XWindowListener2>& m_rWindow2Listeners;
+ const bool m_bEnabled;
+ const EventObject m_aEvent;
+ };
+}
+
+void VCLXWindow::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ if (mpImpl->mbDisposing)
+ return;
+ css::uno::Reference< css::uno::XInterface > xThis( getXWeak() );
+
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::WindowEnabled:
+ case VclEventId::WindowDisabled:
+ {
+ Callback aCallback = CallWindow2Listener(
+ mpImpl->getWindow2Listeners(),
+ ( VclEventId::WindowEnabled == rVclWindowEvent.GetId() ),
+ EventObject( *this )
+ );
+ ImplExecuteAsyncWithoutSolarLock( aCallback );
+ }
+ break;
+
+ case VclEventId::WindowPaint:
+ {
+ if ( mpImpl->getPaintListeners().getLength() )
+ {
+ css::awt::PaintEvent aEvent;
+ aEvent.Source = getXWeak();
+ aEvent.UpdateRect = AWTRectangle( *static_cast<tools::Rectangle*>(rVclWindowEvent.GetData()) );
+ aEvent.Count = 0;
+ mpImpl->getPaintListeners().windowPaint( aEvent );
+ }
+ }
+ break;
+ case VclEventId::WindowMove:
+ {
+ if ( mpImpl->getWindowListeners().getLength() )
+ {
+ css::awt::WindowEvent aEvent;
+ aEvent.Source = getXWeak();
+ ImplInitWindowEvent( aEvent, rVclWindowEvent.GetWindow() );
+ mpImpl->getWindowListeners().windowMoved( aEvent );
+ }
+ }
+ break;
+ case VclEventId::WindowResize:
+ {
+ if ( mpImpl->getWindowListeners().getLength() )
+ {
+ css::awt::WindowEvent aEvent;
+ aEvent.Source = getXWeak();
+ ImplInitWindowEvent( aEvent, rVclWindowEvent.GetWindow() );
+ mpImpl->getWindowListeners().windowResized( aEvent );
+ }
+ }
+ break;
+ case VclEventId::WindowShow:
+ {
+ if ( mpImpl->getWindowListeners().getLength() )
+ {
+ css::awt::WindowEvent aEvent;
+ aEvent.Source = getXWeak();
+ ImplInitWindowEvent( aEvent, rVclWindowEvent.GetWindow() );
+ mpImpl->getWindowListeners().windowShown( aEvent );
+ }
+
+ // For TopWindows this means opened...
+ if ( mpImpl->getTopWindowListeners().getLength() )
+ {
+ css::lang::EventObject aEvent;
+ aEvent.Source = getXWeak();
+ mpImpl->getTopWindowListeners().windowOpened( aEvent );
+ }
+ }
+ break;
+ case VclEventId::WindowHide:
+ {
+ if ( mpImpl->getWindowListeners().getLength() )
+ {
+ css::awt::WindowEvent aEvent;
+ aEvent.Source = getXWeak();
+ ImplInitWindowEvent( aEvent, rVclWindowEvent.GetWindow() );
+ mpImpl->getWindowListeners().windowHidden( aEvent );
+ }
+
+ // For TopWindows this means closed...
+ if ( mpImpl->getTopWindowListeners().getLength() )
+ {
+ css::lang::EventObject aEvent;
+ aEvent.Source = getXWeak();
+ mpImpl->getTopWindowListeners().windowClosed( aEvent );
+ }
+ }
+ break;
+ case VclEventId::WindowActivate:
+ case VclEventId::WindowDeactivate:
+ {
+ if (!mpImpl->getTopWindowListeners().getLength())
+ return;
+
+ // Suppress events which are unlikely to be interesting to our listeners.
+ vcl::Window* pWin = static_cast<vcl::Window*>(rVclWindowEvent.GetData());
+ bool bSuppress = false;
+
+ while (pWin)
+ {
+ // Either the event came from the same window, from its
+ // child, or from a child of its border window (e.g.
+ // menubar or notebookbar).
+ if (pWin->GetWindow(GetWindowType::Client) == GetWindow())
+ return;
+
+ if (pWin->IsMenuFloatingWindow())
+ bSuppress = true;
+
+ if (pWin->GetType() == WindowType::FLOATINGWINDOW &&
+ static_cast<FloatingWindow*>(pWin)->IsInPopupMode())
+ bSuppress = true;
+
+ // Otherwise, don't suppress if the event came from a different frame.
+ if (!bSuppress && pWin->GetWindow(GetWindowType::Frame) == pWin)
+ break;
+
+ pWin = pWin->GetWindow(GetWindowType::RealParent);
+ }
+
+ css::lang::EventObject aEvent;
+ aEvent.Source = getXWeak();
+ if (rVclWindowEvent.GetId() == VclEventId::WindowActivate)
+ mpImpl->getTopWindowListeners().windowActivated( aEvent );
+ else
+ mpImpl->getTopWindowListeners().windowDeactivated( aEvent );
+ }
+ break;
+ case VclEventId::WindowClose:
+ {
+ if ( mpImpl->getDockableWindowListeners().getLength() )
+ {
+ css::lang::EventObject aEvent;
+ aEvent.Source = getXWeak();
+ mpImpl->getDockableWindowListeners().notifyEach( &XDockableWindowListener::closed, aEvent );
+ }
+ if ( mpImpl->getTopWindowListeners().getLength() )
+ {
+ css::lang::EventObject aEvent;
+ aEvent.Source = getXWeak();
+ mpImpl->getTopWindowListeners().windowClosing( aEvent );
+ }
+ }
+ break;
+ case VclEventId::ControlGetFocus:
+ case VclEventId::WindowGetFocus:
+ {
+ if ( ( rVclWindowEvent.GetWindow()->IsCompoundControl()
+ && rVclWindowEvent.GetId() == VclEventId::ControlGetFocus
+ )
+ || ( !rVclWindowEvent.GetWindow()->IsCompoundControl()
+ && rVclWindowEvent.GetId() == VclEventId::WindowGetFocus
+ )
+ )
+ {
+ if ( mpImpl->getFocusListeners().getLength() )
+ {
+ css::awt::FocusEvent aEvent;
+ aEvent.Source = getXWeak();
+ aEvent.FocusFlags = static_cast<sal_Int16>(rVclWindowEvent.GetWindow()->GetGetFocusFlags());
+ aEvent.Temporary = false;
+ mpImpl->getFocusListeners().focusGained( aEvent );
+ }
+ }
+ }
+ break;
+ case VclEventId::ControlLoseFocus:
+ case VclEventId::WindowLoseFocus:
+ {
+ if ( ( rVclWindowEvent.GetWindow()->IsCompoundControl()
+ && rVclWindowEvent.GetId() == VclEventId::ControlLoseFocus
+ )
+ || ( !rVclWindowEvent.GetWindow()->IsCompoundControl()
+ && rVclWindowEvent.GetId() == VclEventId::WindowLoseFocus
+ )
+ )
+ {
+ if ( mpImpl->getFocusListeners().getLength() )
+ {
+ css::awt::FocusEvent aEvent;
+ aEvent.Source = getXWeak();
+ aEvent.FocusFlags = static_cast<sal_Int16>(rVclWindowEvent.GetWindow()->GetGetFocusFlags());
+ aEvent.Temporary = false;
+
+ vcl::Window* pNext = Application::GetFocusWindow();
+ if ( pNext )
+ {
+ // Don't care about internals if this control is compound
+ vcl::Window* pNextC = pNext;
+ while ( pNextC && !pNextC->IsCompoundControl() )
+ pNextC = pNextC->GetParent();
+ if ( pNextC )
+ pNext = pNextC;
+
+ pNext->GetComponentInterface();
+ aEvent.NextFocus = cppu::getXWeak(pNext->GetWindowPeer());
+ }
+ mpImpl->getFocusListeners().focusLost( aEvent );
+ }
+ }
+ }
+ break;
+ case VclEventId::WindowMinimize:
+ {
+ if ( mpImpl->getTopWindowListeners().getLength() )
+ {
+ css::lang::EventObject aEvent;
+ aEvent.Source = getXWeak();
+ mpImpl->getTopWindowListeners().windowMinimized( aEvent );
+ }
+ }
+ break;
+ case VclEventId::WindowNormalize:
+ {
+ if ( mpImpl->getTopWindowListeners().getLength() )
+ {
+ css::lang::EventObject aEvent;
+ aEvent.Source = getXWeak();
+ mpImpl->getTopWindowListeners().windowNormalized( aEvent );
+ }
+ }
+ break;
+ case VclEventId::WindowKeyInput:
+ {
+ if ( mpImpl->getKeyListeners().getLength() )
+ {
+ css::awt::KeyEvent aEvent( VCLUnoHelper::createKeyEvent(
+ *static_cast<KeyEvent*>(rVclWindowEvent.GetData()), *this
+ ) );
+ mpImpl->getKeyListeners().keyPressed( aEvent );
+ }
+ }
+ break;
+ case VclEventId::WindowKeyUp:
+ {
+ if ( mpImpl->getKeyListeners().getLength() )
+ {
+ css::awt::KeyEvent aEvent( VCLUnoHelper::createKeyEvent(
+ *static_cast<KeyEvent*>(rVclWindowEvent.GetData()), *this
+ ) );
+ mpImpl->getKeyListeners().keyReleased( aEvent );
+ }
+ }
+ break;
+ case VclEventId::WindowCommand:
+ {
+ CommandEvent* pCmdEvt = static_cast<CommandEvent*>(rVclWindowEvent.GetData());
+ if ( mpImpl->getMouseListeners().getLength() && ( pCmdEvt->GetCommand() == CommandEventId::ContextMenu ) )
+ {
+ // CommandEventId::ContextMenu: send as mousePressed with PopupTrigger = true ...
+ Point aWhere = static_cast< CommandEvent* >( rVclWindowEvent.GetData() )->GetMousePosPixel();
+ if ( !pCmdEvt->IsMouseEvent() )
+ { // for keyboard events, we set the coordinates to -1,-1. This is a slight HACK, but the current API
+ // handles a context menu command as special case of a mouse event, which is simply wrong.
+ // Without extending the API, we would not have another chance to notify listeners of a
+ // keyboard-triggered context menu request
+ aWhere = Point( -1, -1 );
+ }
+
+ MouseEvent aMEvt( aWhere, 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT, 0 );
+ awt::MouseEvent aEvent( VCLUnoHelper::createMouseEvent( aMEvt, *this ) );
+ aEvent.PopupTrigger = true;
+
+ Callback aCallback = [ this, aEvent ]()
+ { this->mpImpl->getMouseListeners().mousePressed( aEvent ); };
+
+ ImplExecuteAsyncWithoutSolarLock( aCallback );
+ }
+ }
+ break;
+ case VclEventId::WindowMouseMove:
+ {
+ MouseEvent* pMouseEvt = static_cast<MouseEvent*>(rVclWindowEvent.GetData());
+ if ( mpImpl->getMouseListeners().getLength() && ( pMouseEvt->IsEnterWindow() || pMouseEvt->IsLeaveWindow() ) )
+ {
+ awt::MouseEvent aEvent( VCLUnoHelper::createMouseEvent( *pMouseEvt, *this ) );
+ bool const isEnter(pMouseEvt->IsEnterWindow());
+ Callback aCallback = [ this, isEnter, aEvent ]()
+ { MouseListenerMultiplexer& rMouseListeners = this->mpImpl->getMouseListeners();
+ isEnter
+ ? rMouseListeners.mouseEntered(aEvent)
+ : rMouseListeners.mouseExited(aEvent); };
+
+ ImplExecuteAsyncWithoutSolarLock( aCallback );
+ }
+
+ if ( mpImpl->getMouseMotionListeners().getLength() && !pMouseEvt->IsEnterWindow() && !pMouseEvt->IsLeaveWindow() )
+ {
+ awt::MouseEvent aEvent( VCLUnoHelper::createMouseEvent( *pMouseEvt, *this ) );
+ aEvent.ClickCount = 0;
+ if ( pMouseEvt->GetMode() & MouseEventModifiers::SIMPLEMOVE )
+ mpImpl->getMouseMotionListeners().mouseMoved( aEvent );
+ else
+ mpImpl->getMouseMotionListeners().mouseDragged( aEvent );
+ }
+ }
+ break;
+ case VclEventId::WindowMouseButtonDown:
+ {
+ if ( mpImpl->getMouseListeners().getLength() )
+ {
+ awt::MouseEvent aEvent( VCLUnoHelper::createMouseEvent( *static_cast<MouseEvent*>(rVclWindowEvent.GetData()), *this ) );
+ Callback aCallback = [ this, aEvent ]()
+ { this->mpImpl->getMouseListeners().mousePressed( aEvent ); };
+ ImplExecuteAsyncWithoutSolarLock( aCallback );
+ }
+ }
+ break;
+ case VclEventId::WindowMouseButtonUp:
+ {
+ if ( mpImpl->getMouseListeners().getLength() )
+ {
+ awt::MouseEvent aEvent( VCLUnoHelper::createMouseEvent( *static_cast<MouseEvent*>(rVclWindowEvent.GetData()), *this ) );
+
+ Callback aCallback = [ this, aEvent ]()
+ { this->mpImpl->getMouseListeners().mouseReleased( aEvent ); };
+ ImplExecuteAsyncWithoutSolarLock( aCallback );
+ }
+ }
+ break;
+ case VclEventId::WindowStartDocking:
+ {
+ if ( mpImpl->getDockableWindowListeners().getLength() )
+ {
+ DockingData *pData = static_cast<DockingData*>(rVclWindowEvent.GetData());
+
+ if( pData )
+ {
+ css::awt::DockingEvent aEvent;
+ aEvent.Source = getXWeak();
+ aEvent.TrackingRectangle = AWTRectangle( pData->maTrackRect );
+ aEvent.MousePos.X = pData->maMousePos.X();
+ aEvent.MousePos.Y = pData->maMousePos.Y();
+ aEvent.bLiveMode = false;
+ aEvent.bInteractive = true;
+
+ mpImpl->getDockableWindowListeners().notifyEach( &XDockableWindowListener::startDocking, aEvent );
+ }
+ }
+ }
+ break;
+ case VclEventId::WindowDocking:
+ {
+ if ( mpImpl->getDockableWindowListeners().getLength() )
+ {
+ DockingData *pData = static_cast<DockingData*>(rVclWindowEvent.GetData());
+
+ if( pData )
+ {
+ css::awt::DockingEvent aEvent;
+ aEvent.Source = getXWeak();
+ aEvent.TrackingRectangle = AWTRectangle( pData->maTrackRect );
+ aEvent.MousePos.X = pData->maMousePos.X();
+ aEvent.MousePos.Y = pData->maMousePos.Y();
+ aEvent.bLiveMode = false;
+ aEvent.bInteractive = true;
+
+ Reference< XDockableWindowListener > xFirstListener;
+ ::comphelper::OInterfaceIteratorHelper3 aIter( mpImpl->getDockableWindowListeners() );
+ while ( aIter.hasMoreElements() && !xFirstListener.is() )
+ {
+ xFirstListener = aIter.next();
+ }
+
+ css::awt::DockingData aDockingData =
+ xFirstListener->docking( aEvent );
+ pData->maTrackRect = VCLRectangle( aDockingData.TrackingRectangle );
+ pData->mbFloating = aDockingData.bFloating;
+ }
+ }
+ }
+ break;
+ case VclEventId::WindowEndDocking:
+ {
+ if ( mpImpl->getDockableWindowListeners().getLength() )
+ {
+ EndDockingData *pData = static_cast<EndDockingData*>(rVclWindowEvent.GetData());
+
+ if( pData )
+ {
+ css::awt::EndDockingEvent aEvent;
+ aEvent.Source = getXWeak();
+ aEvent.WindowRectangle = AWTRectangle( pData->maWindowRect );
+ aEvent.bFloating = pData->mbFloating;
+ aEvent.bCancelled = pData->mbCancelled;
+ mpImpl->getDockableWindowListeners().notifyEach( &XDockableWindowListener::endDocking, aEvent );
+ }
+ }
+ }
+ break;
+ case VclEventId::WindowPrepareToggleFloating:
+ {
+ if ( mpImpl->getDockableWindowListeners().getLength() )
+ {
+ sal_Bool *p_bFloating = static_cast<sal_Bool*>(rVclWindowEvent.GetData());
+
+ css::lang::EventObject aEvent;
+ aEvent.Source = getXWeak();
+
+ Reference< XDockableWindowListener > xFirstListener;
+ ::comphelper::OInterfaceIteratorHelper3 aIter( mpImpl->getDockableWindowListeners() );
+ while ( aIter.hasMoreElements() && !xFirstListener.is() )
+ {
+ xFirstListener = aIter.next();
+ }
+
+ *p_bFloating = xFirstListener->prepareToggleFloatingMode( aEvent );
+ }
+ }
+ break;
+ case VclEventId::WindowToggleFloating:
+ {
+ if ( mpImpl->getDockableWindowListeners().getLength() )
+ {
+ css::lang::EventObject aEvent;
+ aEvent.Source = getXWeak();
+ mpImpl->getDockableWindowListeners().notifyEach( &XDockableWindowListener::toggleFloatingMode, aEvent );
+ }
+ }
+ break;
+ case VclEventId::WindowEndPopupMode:
+ {
+ if ( mpImpl->getDockableWindowListeners().getLength() )
+ {
+ EndPopupModeData *pData = static_cast<EndPopupModeData*>(rVclWindowEvent.GetData());
+
+ if( pData )
+ {
+ css::awt::EndPopupModeEvent aEvent;
+ aEvent.Source = getXWeak();
+ aEvent.FloatingPosition.X = pData->maFloatingPos.X();
+ aEvent.FloatingPosition.Y = pData->maFloatingPos.Y();
+ aEvent.bTearoff = pData->mbTearoff;
+ mpImpl->getDockableWindowListeners().notifyEach( &XDockableWindowListener::endPopupMode, aEvent );
+ }
+ }
+ }
+ break;
+ default: break;
+ }
+}
+
+uno::Reference< accessibility::XAccessibleContext > VCLXWindow::CreateAccessibleContext()
+{
+ SolarMutexGuard aGuard;
+ if (mpImpl->mbDisposing)
+ return nullptr;
+ return getAccessibleFactory().createAccessibleContext( this );
+}
+
+void VCLXWindow::SetSynthesizingVCLEvent( bool _b )
+{
+ mpImpl->mbSynthesizingVCLEvent = _b;
+}
+
+bool VCLXWindow::IsSynthesizingVCLEvent() const
+{
+ return mpImpl->mbSynthesizingVCLEvent;
+}
+
+Size VCLXWindow::ImplCalcWindowSize( const Size& rOutSz ) const
+{
+ Size aSz = rOutSz;
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ sal_Int32 nLeft, nTop, nRight, nBottom;
+ pWindow->GetBorder( nLeft, nTop, nRight, nBottom );
+ aSz.AdjustWidth(nLeft+nRight );
+ aSz.AdjustHeight(nTop+nBottom );
+ }
+ return aSz;
+}
+
+
+// css::lang::Component
+void VCLXWindow::dispose( )
+{
+ SolarMutexGuard aGuard;
+
+ if ( mpImpl->mbDisposing )
+ return;
+
+ mpImpl->mbDisposing = true;
+
+ mpImpl->mxViewGraphics = nullptr;
+
+ mpImpl->disposing();
+
+ if ( VclPtr<vcl::Window> pWindow = GetWindow() )
+ {
+ pWindow->RemoveEventListener( LINK( this, VCLXWindow, WindowEventListener ) );
+ pWindow->SetWindowPeer( nullptr, nullptr );
+ pWindow->SetAccessible( nullptr );
+
+ SetOutputDevice( nullptr );
+ pWindow.disposeAndClear();
+ }
+
+ // #i14103# dispose the accessible context after the window has been destroyed,
+ // otherwise the old value in the child event fired in VCLXAccessibleComponent::ProcessWindowEvent()
+ // for VclEventId::WindowChildDestroyed contains a reference to an already disposed accessible object
+ try
+ {
+ css::uno::Reference< css::lang::XComponent > xComponent( mpImpl->mxAccessibleContext, css::uno::UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+ }
+ catch ( const css::uno::Exception& )
+ {
+ OSL_FAIL( "VCLXWindow::dispose: could not dispose the accessible context!" );
+ }
+ mpImpl->mxAccessibleContext.clear();
+}
+
+void VCLXWindow::addEventListener( const css::uno::Reference< css::lang::XEventListener >& rxListener )
+{
+ SolarMutexGuard aGuard;
+ if (mpImpl->mbDisposing) // called during dispose by accessibility stuff
+ return;
+ mpImpl->getEventListeners().addInterface( rxListener );
+}
+
+void VCLXWindow::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& rxListener )
+{
+ SolarMutexGuard aGuard;
+ if (mpImpl->mbDisposing)
+ return;
+ mpImpl->getEventListeners().removeInterface( rxListener );
+}
+
+
+// css::awt::XWindow
+void VCLXWindow::setPosSize( sal_Int32 X, sal_Int32 Y, sal_Int32 Width, sal_Int32 Height, sal_Int16 Flags )
+{
+ SolarMutexGuard aGuard;
+ comphelper::ProfileZone aZone("setPosSize");
+
+ if ( GetWindow() )
+ {
+ if( vcl::Window::GetDockingManager()->IsDockable( GetWindow() ) )
+ vcl::Window::GetDockingManager()->SetPosSizePixel( GetWindow() , X, Y, Width, Height, static_cast<PosSizeFlags>(Flags) );
+ else
+ GetWindow()->setPosSizePixel( X, Y, Width, Height, static_cast<PosSizeFlags>(Flags) );
+ }
+}
+
+css::awt::Rectangle VCLXWindow::getPosSize( )
+{
+ SolarMutexGuard aGuard;
+
+ css::awt::Rectangle aBounds;
+ if ( GetWindow() )
+ {
+ if( vcl::Window::GetDockingManager()->IsDockable( GetWindow() ) )
+ aBounds = AWTRectangle( vcl::Window::GetDockingManager()->GetPosSizePixel( GetWindow() ) );
+ else
+ aBounds = AWTRectangle( tools::Rectangle( GetWindow()->GetPosPixel(), GetWindow()->GetSizePixel() ) );
+ }
+
+ return aBounds;
+}
+
+void VCLXWindow::setVisible( sal_Bool bVisible )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ mpImpl->setDirectVisible( bVisible );
+ pWindow->Show( bVisible && mpImpl->isEnableVisible() );
+ }
+}
+
+void VCLXWindow::setEnable( sal_Bool bEnable )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ pWindow->Enable( bEnable, false ); // #95824# without children!
+ pWindow->EnableInput( bEnable );
+ }
+}
+
+void VCLXWindow::setFocus( )
+{
+ SolarMutexGuard aGuard;
+
+ if ( GetWindow() )
+ GetWindow()->GrabFocus();
+}
+
+void VCLXWindow::addWindowListener( const css::uno::Reference< css::awt::XWindowListener >& rxListener )
+{
+ SolarMutexGuard aGuard;
+ if (mpImpl->mbDisposing)
+ return;
+
+ mpImpl->getWindowListeners().addInterface( rxListener );
+
+ Reference< XWindowListener2 > xListener2( rxListener, UNO_QUERY );
+ if ( xListener2.is() )
+ mpImpl->getWindow2Listeners().addInterface( xListener2 );
+
+ // #100119# Get all resize events, even if height or width 0, or invisible
+ if ( GetWindow() )
+ GetWindow()->EnableAllResize();
+}
+
+void VCLXWindow::removeWindowListener( const css::uno::Reference< css::awt::XWindowListener >& rxListener )
+{
+ SolarMutexGuard aGuard;
+
+ if (mpImpl->mbDisposing)
+ return;
+
+ Reference< XWindowListener2 > xListener2( rxListener, UNO_QUERY );
+ if ( xListener2.is() )
+ mpImpl->getWindow2Listeners().removeInterface( xListener2 );
+
+ mpImpl->getWindowListeners().removeInterface( rxListener );
+}
+
+void VCLXWindow::addFocusListener( const css::uno::Reference< css::awt::XFocusListener >& rxListener )
+{
+ SolarMutexGuard aGuard;
+ if (mpImpl->mbDisposing)
+ return;
+ mpImpl->getFocusListeners().addInterface( rxListener );
+}
+
+void VCLXWindow::removeFocusListener( const css::uno::Reference< css::awt::XFocusListener >& rxListener )
+{
+ SolarMutexGuard aGuard;
+ if (mpImpl->mbDisposing)
+ return;
+ mpImpl->getFocusListeners().removeInterface( rxListener );
+}
+
+void VCLXWindow::addKeyListener( const css::uno::Reference< css::awt::XKeyListener >& rxListener )
+{
+ SolarMutexGuard aGuard;
+ if (mpImpl->mbDisposing)
+ return;
+ mpImpl->getKeyListeners().addInterface( rxListener );
+}
+
+void VCLXWindow::removeKeyListener( const css::uno::Reference< css::awt::XKeyListener >& rxListener )
+{
+ SolarMutexGuard aGuard;
+ if (mpImpl->mbDisposing)
+ return;
+ mpImpl->getKeyListeners().removeInterface( rxListener );
+}
+
+void VCLXWindow::addMouseListener( const css::uno::Reference< css::awt::XMouseListener >& rxListener )
+{
+ SolarMutexGuard aGuard;
+ if (mpImpl->mbDisposing)
+ return;
+ mpImpl->getMouseListeners().addInterface( rxListener );
+}
+
+void VCLXWindow::removeMouseListener( const css::uno::Reference< css::awt::XMouseListener >& rxListener )
+{
+ SolarMutexGuard aGuard;
+ if (mpImpl->mbDisposing)
+ return;
+ mpImpl->getMouseListeners().removeInterface( rxListener );
+}
+
+void VCLXWindow::addMouseMotionListener( const css::uno::Reference< css::awt::XMouseMotionListener >& rxListener )
+{
+ SolarMutexGuard aGuard;
+ if (mpImpl->mbDisposing)
+ return;
+ mpImpl->getMouseMotionListeners().addInterface( rxListener );
+}
+
+void VCLXWindow::removeMouseMotionListener( const css::uno::Reference< css::awt::XMouseMotionListener >& rxListener )
+{
+ SolarMutexGuard aGuard;
+ if (mpImpl->mbDisposing)
+ return;
+ mpImpl->getMouseMotionListeners().removeInterface( rxListener );
+}
+
+void VCLXWindow::addPaintListener( const css::uno::Reference< css::awt::XPaintListener >& rxListener )
+{
+ SolarMutexGuard aGuard;
+ if (mpImpl->mbDisposing)
+ return;
+ mpImpl->getPaintListeners().addInterface( rxListener );
+}
+
+void VCLXWindow::removePaintListener( const css::uno::Reference< css::awt::XPaintListener >& rxListener )
+{
+ SolarMutexGuard aGuard;
+ if (mpImpl->mbDisposing)
+ return;
+ mpImpl->getPaintListeners().removeInterface( rxListener );
+}
+
+// css::awt::XWindowPeer
+css::uno::Reference< css::awt::XToolkit > VCLXWindow::getToolkit( )
+{
+ // no guard. nothing to guard here.
+ // 82463 - 12/21/00 - fs
+ return Application::GetVCLToolkit();
+}
+
+void VCLXWindow::setPointer( const css::uno::Reference< css::awt::XPointer >& rxPointer )
+{
+ SolarMutexGuard aGuard;
+
+ VCLXPointer* pPointer = dynamic_cast<VCLXPointer*>( rxPointer.get() );
+ if ( pPointer && GetWindow() )
+ GetWindow()->SetPointer( pPointer->GetPointer() );
+}
+
+void VCLXWindow::setBackground( sal_Int32 nColor )
+{
+ SolarMutexGuard aGuard;
+
+ if ( !GetWindow() )
+ return;
+
+ Color aColor(ColorTransparency, nColor);
+ GetWindow()->SetBackground( aColor );
+ GetWindow()->SetControlBackground( aColor );
+
+ WindowType eWinType = GetWindow()->GetType();
+ if ( ( eWinType == WindowType::WINDOW ) ||
+ ( eWinType == WindowType::WORKWINDOW ) ||
+ ( eWinType == WindowType::FLOATINGWINDOW ) )
+ {
+ GetWindow()->Invalidate();
+ }
+}
+
+void VCLXWindow::invalidate( sal_Int16 nInvalidateFlags )
+{
+ SolarMutexGuard aGuard;
+
+ if ( GetWindow() )
+ GetWindow()->Invalidate( static_cast<InvalidateFlags>(nInvalidateFlags) );
+}
+
+void VCLXWindow::invalidateRect( const css::awt::Rectangle& rRect, sal_Int16 nInvalidateFlags )
+{
+ SolarMutexGuard aGuard;
+
+ if ( GetWindow() )
+ GetWindow()->Invalidate( VCLRectangle(rRect), static_cast<InvalidateFlags>(nInvalidateFlags) );
+}
+
+
+// css::awt::XVclWindowPeer
+sal_Bool VCLXWindow::isChild( const css::uno::Reference< css::awt::XWindowPeer >& rxPeer )
+{
+ SolarMutexGuard aGuard;
+
+ bool bIsChild = false;
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ VclPtr<vcl::Window> pPeerWindow = VCLUnoHelper::GetWindow( rxPeer );
+ bIsChild = pPeerWindow && pWindow->IsChild( pPeerWindow );
+ }
+
+ return bIsChild;
+}
+
+void VCLXWindow::setDesignMode( sal_Bool bOn )
+{
+ SolarMutexGuard aGuard;
+
+ mpImpl->mbDesignMode = bOn;
+}
+
+sal_Bool VCLXWindow::isDesignMode( )
+{
+ SolarMutexGuard aGuard;
+ return mpImpl->mbDesignMode;
+}
+
+void VCLXWindow::enableClipSiblings( sal_Bool bClip )
+{
+ SolarMutexGuard aGuard;
+
+ if ( GetWindow() )
+ GetWindow()->EnableClipSiblings( bClip );
+}
+
+void VCLXWindow::setForeground( sal_Int32 nColor )
+{
+ SolarMutexGuard aGuard;
+
+ if ( GetWindow() )
+ {
+ GetWindow()->SetControlForeground( Color(ColorTransparency, nColor) );
+ }
+}
+
+void VCLXWindow::setControlFont( const css::awt::FontDescriptor& rFont )
+{
+ SolarMutexGuard aGuard;
+
+ if ( GetWindow() )
+ GetWindow()->SetControlFont( VCLUnoHelper::CreateFont( rFont, GetWindow()->GetControlFont() ) );
+}
+
+void VCLXWindow::getStyles( sal_Int16 nType, css::awt::FontDescriptor& Font, sal_Int32& ForegroundColor, sal_Int32& BackgroundColor )
+{
+ SolarMutexGuard aGuard;
+
+ if ( !GetWindow() )
+ return;
+
+ const StyleSettings& rStyleSettings = GetWindow()->GetSettings().GetStyleSettings();
+
+ switch ( nType )
+ {
+ case css::awt::Style::FRAME:
+ {
+ Font = VCLUnoHelper::CreateFontDescriptor( rStyleSettings.GetAppFont() );
+ ForegroundColor = sal_Int32(rStyleSettings.GetWindowTextColor());
+ BackgroundColor = sal_Int32(rStyleSettings.GetWindowColor());
+ }
+ break;
+ case css::awt::Style::DIALOG:
+ {
+ Font = VCLUnoHelper::CreateFontDescriptor( rStyleSettings.GetAppFont() );
+ ForegroundColor = sal_Int32(rStyleSettings.GetDialogTextColor());
+ BackgroundColor = sal_Int32(rStyleSettings.GetDialogColor());
+ }
+ break;
+ default: OSL_FAIL( "VCLWindow::getStyles() - unknown Type" );
+ }
+}
+
+namespace toolkit
+{
+ static void setColorSettings( vcl::Window* _pWindow, const css::uno::Any& _rValue,
+ void (StyleSettings::*pSetter)( const Color& ), const Color& (StyleSettings::*pGetter)( ) const )
+ {
+ sal_Int32 nColor = 0;
+ if ( !( _rValue >>= nColor ) )
+ nColor = sal_Int32((Application::GetSettings().GetStyleSettings().*pGetter)());
+
+ AllSettings aSettings = _pWindow->GetSettings();
+ StyleSettings aStyleSettings = aSettings.GetStyleSettings();
+
+ (aStyleSettings.*pSetter)( Color( ColorTransparency, nColor ) );
+
+ aSettings.SetStyleSettings( aStyleSettings );
+ _pWindow->SetSettings( aSettings, true );
+ }
+}
+
+// Terminated by BASEPROPERTY_NOTFOUND (or 0)
+void VCLXWindow::PushPropertyIds( std::vector< sal_uInt16 > &rIds,
+ int nFirstId, ...)
+{
+ va_list pVarArgs;
+ va_start( pVarArgs, nFirstId );
+
+ for ( int nId = nFirstId; nId != BASEPROPERTY_NOTFOUND;
+ nId = va_arg( pVarArgs, int ) )
+ rIds.push_back( static_cast<sal_uInt16>(nId) );
+
+ va_end( pVarArgs );
+}
+
+void VCLXWindow::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds, bool bWithDefaults )
+{
+ // These are common across ~all VCLXWindow derived classes
+ if( bWithDefaults )
+ PushPropertyIds( rIds,
+ BASEPROPERTY_ALIGN,
+ BASEPROPERTY_BACKGROUNDCOLOR,
+ BASEPROPERTY_BORDER,
+ BASEPROPERTY_BORDERCOLOR,
+ BASEPROPERTY_DEFAULTCONTROL,
+ BASEPROPERTY_ENABLED,
+ BASEPROPERTY_FONTDESCRIPTOR,
+ BASEPROPERTY_HELPTEXT,
+ BASEPROPERTY_HELPURL,
+ BASEPROPERTY_TEXT,
+ BASEPROPERTY_PRINTABLE,
+ BASEPROPERTY_ENABLEVISIBLE, // for visibility
+ BASEPROPERTY_TABSTOP,
+ 0);
+
+ // lovely hack from:
+ // void UnoControlModel::ImplRegisterProperty( sal_uInt16 nPropId )
+ if( std::find(rIds.begin(), rIds.end(), BASEPROPERTY_FONTDESCRIPTOR) != rIds.end() )
+ {
+ // 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...
+
+ rIds.push_back( BASEPROPERTY_TEXTCOLOR );
+ rIds.push_back( BASEPROPERTY_TEXTLINECOLOR );
+ rIds.push_back( BASEPROPERTY_FONTRELIEF );
+ rIds.push_back( BASEPROPERTY_FONTEMPHASISMARK );
+ }
+}
+
+void VCLXWindow::GetPropertyIds( std::vector< sal_uInt16 >& _out_rIds )
+{
+ return ImplGetPropertyIds( _out_rIds, mpImpl->mbWithDefaultProps );
+}
+
+ListenerMultiplexerBase<css::awt::XVclContainerListener>& VCLXWindow::GetContainerListeners()
+{
+ return mpImpl->getContainerListeners();
+}
+
+ListenerMultiplexerBase<css::awt::XTopWindowListener>& VCLXWindow::GetTopWindowListeners()
+{
+ return mpImpl->getTopWindowListeners();
+}
+
+namespace
+{
+ void lcl_updateWritingMode( vcl::Window& _rWindow, const sal_Int16 _nWritingMode, const sal_Int16 _nContextWritingMode )
+ {
+ bool bEnableRTL = false;
+ switch ( _nWritingMode )
+ {
+ case WritingMode2::LR_TB: bEnableRTL = false; break;
+ case WritingMode2::RL_TB: bEnableRTL = true; break;
+ case WritingMode2::CONTEXT:
+ {
+ // consult our ContextWritingMode. If it has an explicit RTL/LTR value, then use
+ // it. If it doesn't (but is CONTEXT itself), then just ask the parent window of our
+ // own window for its RTL mode
+ switch ( _nContextWritingMode )
+ {
+ case WritingMode2::LR_TB: bEnableRTL = false; break;
+ case WritingMode2::RL_TB: bEnableRTL = true; break;
+ case WritingMode2::CONTEXT:
+ {
+ const vcl::Window* pParent = _rWindow.GetParent();
+ OSL_ENSURE( pParent, "lcl_updateWritingMode: cannot determine context's writing mode!" );
+ if ( pParent )
+ bEnableRTL = pParent->IsRTLEnabled();
+ }
+ break;
+ }
+ }
+ break;
+ default:
+ OSL_FAIL( "lcl_updateWritingMode: unsupported WritingMode!" );
+ } // switch ( nWritingMode )
+
+ _rWindow.EnableRTL( bEnableRTL );
+ }
+}
+
+void VCLXWindow::setProperty( const OUString& PropertyName, const css::uno::Any& Value )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( !pWindow )
+ return;
+
+ bool bVoid = Value.getValueType().getTypeClass() == css::uno::TypeClass_VOID;
+
+ WindowType eWinType = pWindow->GetType();
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_REFERENCE_DEVICE:
+ {
+ Control* pControl = dynamic_cast< Control* >( pWindow.get() );
+ OSL_ENSURE( pControl, "VCLXWindow::setProperty( RefDevice ): need a Control for this!" );
+ if ( !pControl )
+ break;
+ Reference< XDevice > xDevice( Value, UNO_QUERY );
+ OutputDevice* pDevice = VCLUnoHelper::GetOutputDevice( xDevice );
+ pControl->SetReferenceDevice( pDevice );
+ }
+ break;
+
+ case BASEPROPERTY_CONTEXT_WRITING_MODE:
+ {
+ OSL_VERIFY( Value >>= mpImpl->mnContextWritingMode );
+ if ( mpImpl->mnWritingMode == WritingMode2::CONTEXT )
+ lcl_updateWritingMode( *pWindow, mpImpl->mnWritingMode, mpImpl->mnContextWritingMode );
+ }
+ break;
+
+ case BASEPROPERTY_WRITING_MODE:
+ {
+ bool bProperType = ( Value >>= mpImpl->mnWritingMode );
+ OSL_ENSURE( bProperType, "VCLXWindow::setProperty( 'WritingMode' ): illegal value type!" );
+ if ( bProperType )
+ lcl_updateWritingMode( *pWindow, mpImpl->mnWritingMode, mpImpl->mnContextWritingMode );
+ }
+ break;
+
+ case BASEPROPERTY_MOUSE_WHEEL_BEHAVIOUR:
+ {
+ sal_uInt16 nWheelBehavior( css::awt::MouseWheelBehavior::SCROLL_FOCUS_ONLY );
+ OSL_VERIFY( Value >>= nWheelBehavior );
+
+ AllSettings aSettings = pWindow->GetSettings();
+ MouseSettings aMouseSettings = aSettings.GetMouseSettings();
+
+ MouseWheelBehaviour nVclBehavior( MouseWheelBehaviour::FocusOnly );
+ switch ( nWheelBehavior )
+ {
+ case css::awt::MouseWheelBehavior::SCROLL_DISABLED: nVclBehavior = MouseWheelBehaviour::Disable; break;
+ case css::awt::MouseWheelBehavior::SCROLL_FOCUS_ONLY: nVclBehavior = MouseWheelBehaviour::FocusOnly; break;
+ case css::awt::MouseWheelBehavior::SCROLL_ALWAYS: nVclBehavior = MouseWheelBehaviour::ALWAYS; break;
+ default:
+ OSL_FAIL( "VCLXWindow::setProperty( 'MouseWheelBehavior' ): illegal property value!" );
+ }
+
+ aMouseSettings.SetWheelBehavior( nVclBehavior );
+ aSettings.SetMouseSettings( aMouseSettings );
+ pWindow->SetSettings( aSettings, true );
+ }
+ break;
+
+ case BASEPROPERTY_NATIVE_WIDGET_LOOK:
+ {
+ bool bEnable( true );
+ OSL_VERIFY( Value >>= bEnable );
+ pWindow->EnableNativeWidget( bEnable );
+ }
+ break;
+
+ case BASEPROPERTY_PLUGINPARENT:
+ {
+ // set parent handle
+ SetSystemParent_Impl( Value );
+ }
+ break;
+
+ case BASEPROPERTY_ENABLED:
+ {
+ bool b = bool();
+ if ( Value >>= b )
+ setEnable( b );
+ }
+ break;
+ case BASEPROPERTY_ENABLEVISIBLE:
+ {
+ bool b = false;
+ if ( Value >>= b )
+ {
+ if( b != mpImpl->isEnableVisible() )
+ {
+ mpImpl->setEnableVisible( b );
+ pWindow->Show( b && mpImpl->isDirectVisible() );
+ }
+ }
+ }
+ break;
+ case BASEPROPERTY_TEXT:
+ case BASEPROPERTY_LABEL:
+ case BASEPROPERTY_TITLE:
+ {
+ OUString aText;
+ if ( Value >>= aText )
+ {
+ switch (eWinType)
+ {
+ case WindowType::OKBUTTON:
+ case WindowType::CANCELBUTTON:
+ case WindowType::HELPBUTTON:
+ // Standard Button: overwrite only if not empty.
+ if (!aText.isEmpty())
+ pWindow->SetText( aText );
+ break;
+
+ default:
+ pWindow->SetText( aText );
+ break;
+ }
+ }
+ }
+ break;
+ case BASEPROPERTY_ACCESSIBLENAME:
+ {
+ OUString aText;
+ if ( Value >>= aText )
+ pWindow->SetAccessibleName( aText );
+ }
+ break;
+ case BASEPROPERTY_HELPURL:
+ {
+ OUString aURL;
+ if ( Value >>= aURL )
+ {
+ INetURLObject aHelpURL( aURL );
+ if ( aHelpURL.GetProtocol() == INetProtocol::Hid )
+ pWindow->SetHelpId( aHelpURL.GetURLPath() );
+ else
+ pWindow->SetHelpId( aURL );
+ }
+ }
+ break;
+ case BASEPROPERTY_HELPTEXT:
+ {
+ OUString aHelpText;
+ if ( Value >>= aHelpText )
+ {
+ pWindow->SetQuickHelpText( aHelpText );
+ }
+ }
+ break;
+ case BASEPROPERTY_FONTDESCRIPTOR:
+ {
+ if ( bVoid )
+ pWindow->SetControlFont( vcl::Font() );
+ else
+ {
+ css::awt::FontDescriptor aFont;
+ if ( Value >>= aFont )
+ pWindow->SetControlFont( VCLUnoHelper::CreateFont( aFont, pWindow->GetControlFont() ) );
+ }
+ }
+ break;
+ case BASEPROPERTY_FONTRELIEF:
+ {
+ sal_Int16 n = sal_Int16();
+ if ( Value >>= n )
+ {
+ vcl::Font aFont = pWindow->GetControlFont();
+ aFont.SetRelief( static_cast<FontRelief>(n) );
+ pWindow->SetControlFont( aFont );
+ }
+ }
+ break;
+ case BASEPROPERTY_FONTEMPHASISMARK:
+ {
+ sal_Int16 n = sal_Int16();
+ if ( Value >>= n )
+ {
+ vcl::Font aFont = pWindow->GetControlFont();
+ aFont.SetEmphasisMark( static_cast<FontEmphasisMark>(n) );
+ pWindow->SetControlFont( aFont );
+ }
+ }
+ break;
+ case BASEPROPERTY_BACKGROUNDCOLOR:
+ if ( bVoid )
+ {
+ switch ( eWinType )
+ {
+ // set dialog color for default
+ case WindowType::DIALOG:
+ case WindowType::MESSBOX:
+ case WindowType::INFOBOX:
+ case WindowType::WARNINGBOX:
+ case WindowType::ERRORBOX:
+ case WindowType::QUERYBOX:
+ case WindowType::TABPAGE:
+ {
+ Color aColor = pWindow->GetSettings().GetStyleSettings().GetDialogColor();
+ pWindow->SetBackground( aColor );
+ pWindow->SetControlBackground( aColor );
+ break;
+ }
+
+ case WindowType::FIXEDTEXT:
+ case WindowType::CHECKBOX:
+ case WindowType::RADIOBUTTON:
+ case WindowType::GROUPBOX:
+ case WindowType::FIXEDLINE:
+ {
+ // support transparency only for special controls
+ pWindow->SetBackground();
+ pWindow->SetControlBackground();
+ pWindow->SetPaintTransparent( true );
+ break;
+ }
+
+ default:
+ {
+ // default code which enables transparency for
+ // compound controls. It's not real transparency
+ // as most of these controls repaint their client
+ // area completely new.
+ if ( pWindow->IsCompoundControl() )
+ pWindow->SetBackground();
+ pWindow->SetControlBackground();
+ break;
+ }
+ }
+ }
+ else
+ {
+ Color aColor;
+ if ( Value >>= aColor )
+ {
+ pWindow->SetControlBackground( aColor );
+ pWindow->SetBackground( aColor );
+ switch ( eWinType )
+ {
+ // reset paint transparent mode
+ case WindowType::FIXEDTEXT:
+ case WindowType::CHECKBOX:
+ case WindowType::RADIOBUTTON:
+ case WindowType::GROUPBOX:
+ case WindowType::FIXEDLINE:
+ pWindow->SetPaintTransparent( false );
+ break;
+ default:
+ break;
+ }
+ pWindow->Invalidate(); // Invalidate if control does not respond to it
+ }
+ }
+ break;
+ case BASEPROPERTY_TEXTCOLOR:
+ if ( bVoid )
+ {
+ pWindow->SetControlForeground();
+ }
+ else
+ {
+ Color nColor ;
+ if ( Value >>= nColor )
+ {
+ pWindow->SetTextColor( nColor );
+ pWindow->SetControlForeground( nColor );
+ }
+ }
+ break;
+ case BASEPROPERTY_TEXTLINECOLOR:
+ if ( bVoid )
+ {
+ pWindow->SetTextLineColor();
+ }
+ else
+ {
+ Color nColor;
+ if ( Value >>= nColor )
+ pWindow->SetTextLineColor( nColor );
+ }
+ break;
+ case BASEPROPERTY_FILLCOLOR:
+ if ( bVoid )
+ pWindow->GetOutDev()->SetFillColor();
+ else
+ {
+ Color nColor;
+ if ( Value >>= nColor )
+ pWindow->GetOutDev()->SetFillColor( nColor );
+ }
+ break;
+ case BASEPROPERTY_LINECOLOR:
+ if ( bVoid )
+ pWindow->GetOutDev()->SetLineColor();
+ else
+ {
+ Color nColor;
+ if ( Value >>= nColor )
+ pWindow->GetOutDev()->SetLineColor( nColor );
+ }
+ break;
+ case BASEPROPERTY_HIGHLIGHT_COLOR:
+ {
+ Color nColor = 0;
+ if ( bVoid )
+ {
+ nColor = Application::GetSettings().GetStyleSettings().GetHighlightColor();
+ }
+ else
+ {
+ if (!(Value >>= nColor))
+ break;
+ }
+
+ AllSettings aSettings(pWindow->GetSettings());
+ StyleSettings aStyle(aSettings.GetStyleSettings());
+ aStyle.SetHighlightColor(nColor);
+ aSettings.SetStyleSettings(aStyle);
+ pWindow->SetSettings(aSettings);
+ }
+ break;
+ case BASEPROPERTY_HIGHLIGHT_TEXT_COLOR:
+ {
+ Color nColor = 0;
+ if (bVoid)
+ {
+ nColor = Application::GetSettings().GetStyleSettings().GetHighlightTextColor();
+ }
+ else
+ {
+ if (!(Value >>= nColor))
+ break;
+ }
+
+ AllSettings aSettings(pWindow->GetSettings());
+ StyleSettings aStyle(aSettings.GetStyleSettings());
+ aStyle.SetHighlightTextColor(nColor);
+ aSettings.SetStyleSettings(aStyle);
+ pWindow->SetSettings(aSettings);
+ }
+ break;
+ case BASEPROPERTY_BORDER:
+ {
+ WinBits nStyle = pWindow->GetStyle();
+ sal_uInt16 nTmp = 0;
+ Value >>= nTmp;
+ // clear any dodgy bits passed in, can come from dodgy extensions
+ nTmp &= o3tl::typed_flags<WindowBorderStyle>::mask;
+ WindowBorderStyle nBorder = static_cast<WindowBorderStyle>(nTmp);
+ if ( !bool(nBorder) )
+ {
+ pWindow->SetStyle( nStyle & ~WB_BORDER );
+ }
+ else
+ {
+ pWindow->SetStyle( nStyle | WB_BORDER );
+ pWindow->SetBorderStyle( nBorder );
+ }
+ }
+ break;
+ case BASEPROPERTY_TABSTOP:
+ {
+ WinBits nStyle = pWindow->GetStyle() & ~WB_TABSTOP;
+ if ( !bVoid )
+ {
+ bool bTab = false;
+ Value >>= bTab;
+ if ( bTab )
+ nStyle |= WB_TABSTOP;
+ else
+ nStyle |= WB_NOTABSTOP;
+ }
+ pWindow->SetStyle( nStyle );
+ }
+ break;
+ case BASEPROPERTY_VERTICALALIGN:
+ {
+ VerticalAlignment eAlign = css::style::VerticalAlignment::VerticalAlignment_MAKE_FIXED_SIZE;
+ WinBits nStyle = pWindow->GetStyle();
+ nStyle &= ~(WB_TOP|WB_VCENTER|WB_BOTTOM);
+ if ( !bVoid )
+ Value >>= eAlign;
+ switch ( eAlign )
+ {
+ case VerticalAlignment_TOP:
+ nStyle |= WB_TOP;
+ break;
+ case VerticalAlignment_MIDDLE:
+ nStyle |= WB_VCENTER;
+ break;
+ case VerticalAlignment_BOTTOM:
+ nStyle |= WB_BOTTOM;
+ break;
+ default: ; // for warning free code, MAKE_FIXED_SIZE
+ }
+ pWindow->SetStyle( nStyle );
+ }
+ break;
+ case BASEPROPERTY_ALIGN:
+ {
+ sal_Int16 nAlign = PROPERTY_ALIGN_LEFT;
+ switch ( eWinType )
+ {
+ case WindowType::COMBOBOX:
+ case WindowType::PUSHBUTTON:
+ case WindowType::OKBUTTON:
+ case WindowType::CANCELBUTTON:
+ case WindowType::HELPBUTTON:
+ nAlign = PROPERTY_ALIGN_CENTER;
+ [[fallthrough]];
+ case WindowType::FIXEDTEXT:
+ case WindowType::EDIT:
+ case WindowType::MULTILINEEDIT:
+ case WindowType::CHECKBOX:
+ case WindowType::RADIOBUTTON:
+ case WindowType::LISTBOX:
+ {
+ WinBits nStyle = pWindow->GetStyle();
+ nStyle &= ~(WB_LEFT|WB_CENTER|WB_RIGHT);
+ if ( !bVoid )
+ Value >>= nAlign;
+ if ( nAlign == PROPERTY_ALIGN_LEFT )
+ nStyle |= WB_LEFT;
+ else if ( nAlign == PROPERTY_ALIGN_CENTER )
+ nStyle |= WB_CENTER;
+ else
+ nStyle |= WB_RIGHT;
+ pWindow->SetStyle( nStyle );
+ }
+ break;
+ default: break;
+ }
+ }
+ break;
+ case BASEPROPERTY_MULTILINE:
+ {
+ if ( ( eWinType == WindowType::FIXEDTEXT )
+ || ( eWinType == WindowType::CHECKBOX )
+ || ( eWinType == WindowType::RADIOBUTTON )
+ || ( eWinType == WindowType::PUSHBUTTON )
+ || ( eWinType == WindowType::OKBUTTON )
+ || ( eWinType == WindowType::CANCELBUTTON )
+ || ( eWinType == WindowType::HELPBUTTON )
+ )
+ {
+ WinBits nStyle = pWindow->GetStyle();
+ bool bMulti = false;
+ Value >>= bMulti;
+ if ( bMulti )
+ nStyle |= WB_WORDBREAK;
+ else
+ nStyle &= ~WB_WORDBREAK;
+ pWindow->SetStyle( nStyle );
+ }
+ }
+ break;
+ case BASEPROPERTY_ORIENTATION:
+ {
+ if ( eWinType == WindowType::FIXEDLINE)
+ {
+ sal_Int32 nOrientation = 0;
+ if ( Value >>= nOrientation )
+ {
+ WinBits nStyle = pWindow->GetStyle();
+ nStyle &= ~(WB_HORZ|WB_VERT);
+ if ( nOrientation == 0 )
+ nStyle |= WB_HORZ;
+ else
+ nStyle |= WB_VERT;
+
+ pWindow->SetStyle( nStyle );
+ }
+ }
+ }
+ break;
+ case BASEPROPERTY_AUTOMNEMONICS:
+ {
+ bool bAutoMnemonics = false;
+ Value >>= bAutoMnemonics;
+ AllSettings aSettings = pWindow->GetSettings();
+ StyleSettings aStyleSettings = aSettings.GetStyleSettings();
+ if ( aStyleSettings.GetAutoMnemonic() != bAutoMnemonics )
+ {
+ aStyleSettings.SetAutoMnemonic( bAutoMnemonics );
+ aSettings.SetStyleSettings( aStyleSettings );
+ pWindow->SetSettings( aSettings );
+ }
+ }
+ break;
+ case BASEPROPERTY_MOUSETRANSPARENT:
+ {
+ bool bMouseTransparent = false;
+ Value >>= bMouseTransparent;
+ pWindow->SetMouseTransparent( bMouseTransparent );
+ }
+ break;
+ case BASEPROPERTY_PAINTTRANSPARENT:
+ {
+ bool bPaintTransparent = false;
+ Value >>= bPaintTransparent;
+ pWindow->SetPaintTransparent( bPaintTransparent );
+// pWindow->SetBackground();
+ }
+ break;
+
+ case BASEPROPERTY_REPEAT:
+ {
+ bool bRepeat( false );
+ Value >>= bRepeat;
+
+ WinBits nStyle = pWindow->GetStyle();
+ if ( bRepeat )
+ nStyle |= WB_REPEAT;
+ else
+ nStyle &= ~WB_REPEAT;
+ pWindow->SetStyle( nStyle );
+ }
+ break;
+
+ case BASEPROPERTY_REPEAT_DELAY:
+ {
+ sal_Int32 nRepeatDelay = 0;
+ if ( Value >>= nRepeatDelay )
+ {
+ AllSettings aSettings = pWindow->GetSettings();
+ MouseSettings aMouseSettings = aSettings.GetMouseSettings();
+
+ aMouseSettings.SetButtonRepeat( nRepeatDelay );
+ aSettings.SetMouseSettings( aMouseSettings );
+
+ pWindow->SetSettings( aSettings, true );
+ }
+ }
+ break;
+
+ case BASEPROPERTY_SYMBOL_COLOR:
+ ::toolkit::setColorSettings( pWindow, Value, &StyleSettings::SetButtonTextColor, &StyleSettings::GetButtonTextColor );
+ break;
+
+ case BASEPROPERTY_BORDERCOLOR:
+ ::toolkit::setColorSettings( pWindow, Value, &StyleSettings::SetMonoColor, &StyleSettings::GetMonoColor);
+ break;
+ }
+}
+
+css::uno::Any VCLXWindow::getProperty( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Any aProp;
+ if ( GetWindow() )
+ {
+ if (PropertyName == "ParentIs100thmm")
+ {
+ bool bParentIs100thmm = false;
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if (pWindow)
+ {
+ pWindow = pWindow->GetParent();
+ if(pWindow && MapUnit::Map100thMM == pWindow->GetMapMode().GetMapUnit())
+ {
+ bParentIs100thmm = true;
+ }
+ }
+ aProp <<= bParentIs100thmm;
+ return aProp;
+ }
+ WindowType eWinType = GetWindow()->GetType();
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_REFERENCE_DEVICE:
+ {
+ VclPtr<Control> pControl = GetAsDynamic<Control >();
+ OSL_ENSURE( pControl, "VCLXWindow::setProperty( RefDevice ): need a Control for this!" );
+ if ( !pControl )
+ break;
+
+ rtl::Reference<VCLXDevice> pDevice = new VCLXDevice;
+ pDevice->SetOutputDevice( pControl->GetReferenceDevice() );
+ aProp <<= Reference< XDevice >( pDevice );
+ }
+ break;
+
+ case BASEPROPERTY_CONTEXT_WRITING_MODE:
+ aProp <<= mpImpl->mnContextWritingMode;
+ break;
+
+ case BASEPROPERTY_WRITING_MODE:
+ aProp <<= mpImpl->mnWritingMode;
+ break;
+
+ case BASEPROPERTY_MOUSE_WHEEL_BEHAVIOUR:
+ {
+ MouseWheelBehaviour nVclBehavior = GetWindow()->GetSettings().GetMouseSettings().GetWheelBehavior();
+ sal_uInt16 nBehavior = css::awt::MouseWheelBehavior::SCROLL_FOCUS_ONLY;
+ switch ( nVclBehavior )
+ {
+ case MouseWheelBehaviour::Disable: nBehavior = css::awt::MouseWheelBehavior::SCROLL_DISABLED; break;
+ case MouseWheelBehaviour::FocusOnly: nBehavior = css::awt::MouseWheelBehavior::SCROLL_FOCUS_ONLY; break;
+ case MouseWheelBehaviour::ALWAYS: nBehavior = css::awt::MouseWheelBehavior::SCROLL_ALWAYS; break;
+ default:
+ OSL_FAIL( "VCLXWindow::getProperty( 'MouseWheelBehavior' ): illegal VCL value!" );
+ }
+ aProp <<= nBehavior;
+ }
+ break;
+
+ case BASEPROPERTY_NATIVE_WIDGET_LOOK:
+ aProp <<= GetWindow()->IsNativeWidgetEnabled();
+ break;
+
+ case BASEPROPERTY_ENABLED:
+ aProp <<= GetWindow()->IsEnabled();
+ break;
+
+ case BASEPROPERTY_ENABLEVISIBLE:
+ aProp <<= mpImpl->isEnableVisible();
+ break;
+
+ case BASEPROPERTY_HIGHCONTRASTMODE:
+ aProp <<= GetWindow()->GetSettings().GetStyleSettings().GetHighContrastMode();
+ break;
+
+ case BASEPROPERTY_TEXT:
+ case BASEPROPERTY_LABEL:
+ case BASEPROPERTY_TITLE:
+ {
+ OUString aText = GetWindow()->GetText();
+ aProp <<= aText;
+ }
+ break;
+ case BASEPROPERTY_ACCESSIBLENAME:
+ {
+ OUString aText = GetWindow()->GetAccessibleName();
+ aProp <<= aText;
+ }
+ break;
+ case BASEPROPERTY_HELPTEXT:
+ {
+ OUString aText = GetWindow()->GetQuickHelpText();
+ aProp <<= aText;
+ }
+ break;
+ case BASEPROPERTY_HELPURL:
+ aProp <<= GetWindow()->GetHelpId();
+ break;
+ case BASEPROPERTY_FONTDESCRIPTOR:
+ {
+ vcl::Font aFont = GetWindow()->GetControlFont();
+ css::awt::FontDescriptor aFD = VCLUnoHelper::CreateFontDescriptor( aFont );
+ aProp <<= aFD;
+ }
+ break;
+ case BASEPROPERTY_BACKGROUNDCOLOR:
+ aProp <<= GetWindow()->GetControlBackground();
+ break;
+ case BASEPROPERTY_DISPLAYBACKGROUNDCOLOR:
+ aProp <<= GetWindow()->GetBackgroundColor();
+ break;
+ case BASEPROPERTY_FONTRELIEF:
+ aProp <<= static_cast<sal_Int16>(GetWindow()->GetControlFont().GetRelief());
+ break;
+ case BASEPROPERTY_FONTEMPHASISMARK:
+ aProp <<= static_cast<sal_Int16>(GetWindow()->GetControlFont().GetEmphasisMark());
+ break;
+ case BASEPROPERTY_TEXTCOLOR:
+ aProp <<= GetWindow()->GetControlForeground();
+ break;
+ case BASEPROPERTY_TEXTLINECOLOR:
+ aProp <<= GetWindow()->GetTextLineColor();
+ break;
+ case BASEPROPERTY_FILLCOLOR:
+ aProp <<= GetWindow()->GetOutDev()->GetFillColor();
+ break;
+ case BASEPROPERTY_LINECOLOR:
+ aProp <<= GetWindow()->GetOutDev()->GetLineColor();
+ break;
+ case BASEPROPERTY_HIGHLIGHT_COLOR:
+ aProp <<= GetWindow()->GetSettings().GetStyleSettings().GetHighlightColor();
+ break;
+ case BASEPROPERTY_HIGHLIGHT_TEXT_COLOR:
+ aProp <<= GetWindow()->GetSettings().GetStyleSettings().GetHighlightTextColor();
+ break;
+ case BASEPROPERTY_BORDER:
+ {
+ WindowBorderStyle nBorder = WindowBorderStyle::NONE;
+ if ( GetWindow()->GetStyle() & WB_BORDER )
+ nBorder = GetWindow()->GetBorderStyle();
+ aProp <<= static_cast<sal_uInt16>(nBorder);
+ }
+ break;
+ case BASEPROPERTY_TABSTOP:
+ aProp <<= ( GetWindow()->GetStyle() & WB_TABSTOP ) != 0;
+ break;
+ case BASEPROPERTY_VERTICALALIGN:
+ {
+ WinBits nStyle = GetWindow()->GetStyle();
+ if ( nStyle & WB_TOP )
+ aProp <<= VerticalAlignment_TOP;
+ else if ( nStyle & WB_VCENTER )
+ aProp <<= VerticalAlignment_MIDDLE;
+ else if ( nStyle & WB_BOTTOM )
+ aProp <<= VerticalAlignment_BOTTOM;
+ }
+ break;
+ case BASEPROPERTY_ALIGN:
+ {
+ switch ( eWinType )
+ {
+ case WindowType::FIXEDTEXT:
+ case WindowType::EDIT:
+ case WindowType::MULTILINEEDIT:
+ case WindowType::CHECKBOX:
+ case WindowType::RADIOBUTTON:
+ case WindowType::LISTBOX:
+ case WindowType::COMBOBOX:
+ case WindowType::PUSHBUTTON:
+ case WindowType::OKBUTTON:
+ case WindowType::CANCELBUTTON:
+ case WindowType::HELPBUTTON:
+ {
+ WinBits nStyle = GetWindow()->GetStyle();
+ if ( nStyle & WB_LEFT )
+ aProp <<= sal_Int16(PROPERTY_ALIGN_LEFT);
+ else if ( nStyle & WB_CENTER )
+ aProp <<= sal_Int16(PROPERTY_ALIGN_CENTER);
+ else if ( nStyle & WB_RIGHT )
+ aProp <<= sal_Int16(PROPERTY_ALIGN_RIGHT);
+ }
+ break;
+ default: break;
+ }
+ }
+ break;
+ case BASEPROPERTY_MULTILINE:
+ {
+ if ( ( eWinType == WindowType::FIXEDTEXT )
+ || ( eWinType == WindowType::CHECKBOX )
+ || ( eWinType == WindowType::RADIOBUTTON )
+ || ( eWinType == WindowType::PUSHBUTTON )
+ || ( eWinType == WindowType::OKBUTTON )
+ || ( eWinType == WindowType::CANCELBUTTON )
+ || ( eWinType == WindowType::HELPBUTTON )
+ )
+ aProp <<= ( GetWindow()->GetStyle() & WB_WORDBREAK ) != 0;
+ }
+ break;
+ case BASEPROPERTY_AUTOMNEMONICS:
+ {
+ bool bAutoMnemonics = GetWindow()->GetSettings().GetStyleSettings().GetAutoMnemonic();
+ aProp <<= bAutoMnemonics;
+ }
+ break;
+ case BASEPROPERTY_MOUSETRANSPARENT:
+ {
+ bool bMouseTransparent = GetWindow()->IsMouseTransparent();
+ aProp <<= bMouseTransparent;
+ }
+ break;
+ case BASEPROPERTY_PAINTTRANSPARENT:
+ {
+ bool bPaintTransparent = GetWindow()->IsPaintTransparent();
+ aProp <<= bPaintTransparent;
+ }
+ break;
+
+ case BASEPROPERTY_REPEAT:
+ aProp <<= ( 0 != ( GetWindow()->GetStyle() & WB_REPEAT ) );
+ break;
+
+ case BASEPROPERTY_REPEAT_DELAY:
+ {
+ sal_Int32 nButtonRepeat = GetWindow()->GetSettings().GetMouseSettings().GetButtonRepeat();
+ aProp <<= nButtonRepeat;
+ }
+ break;
+
+ case BASEPROPERTY_SYMBOL_COLOR:
+ aProp <<= GetWindow()->GetSettings().GetStyleSettings().GetButtonTextColor();
+ break;
+
+ case BASEPROPERTY_BORDERCOLOR:
+ aProp <<= GetWindow()->GetSettings().GetStyleSettings().GetMonoColor();
+ break;
+ }
+ }
+ return aProp;
+}
+
+
+// css::awt::XLayoutConstrains
+css::awt::Size VCLXWindow::getMinimumSize( )
+{
+ SolarMutexGuard aGuard;
+
+ // Use this method only for those components which can be created through
+ // css::awt::Toolkit , but do not have an interface
+
+ Size aSz;
+ if ( GetWindow() )
+ {
+ WindowType nWinType = GetWindow()->GetType();
+ switch ( nWinType )
+ {
+ case WindowType::CONTROL:
+ aSz.setWidth( GetWindow()->GetTextWidth( GetWindow()->GetText() )+2*12 );
+ aSz.setHeight( GetWindow()->GetTextHeight()+2*6 );
+ break;
+
+ case WindowType::PATTERNBOX:
+ case WindowType::NUMERICBOX:
+ case WindowType::METRICBOX:
+ case WindowType::CURRENCYBOX:
+ case WindowType::DATEBOX:
+ case WindowType::TIMEBOX:
+ case WindowType::LONGCURRENCYBOX:
+ aSz.setWidth( GetWindow()->GetTextWidth( GetWindow()->GetText() )+2*2 );
+ aSz.setHeight( GetWindow()->GetTextHeight()+2*2 );
+ break;
+ case WindowType::SCROLLBARBOX:
+ return VCLXScrollBar::implGetMinimumSize( GetWindow() );
+ default:
+ aSz = GetWindow()->get_preferred_size();
+ }
+ }
+
+ return css::awt::Size( aSz.Width(), aSz.Height() );
+}
+
+css::awt::Size VCLXWindow::getPreferredSize( )
+{
+ return getMinimumSize();
+}
+
+css::awt::Size VCLXWindow::calcAdjustedSize( const css::awt::Size& rNewSize )
+{
+ SolarMutexGuard aGuard;
+
+ css::awt::Size aNewSize( rNewSize );
+ css::awt::Size aMinSize = getMinimumSize();
+
+ if ( aNewSize.Width < aMinSize.Width )
+ aNewSize.Width = aMinSize.Width;
+ if ( aNewSize.Height < aMinSize.Height )
+ aNewSize.Height = aMinSize.Height;
+
+ return aNewSize;
+}
+
+
+// css::awt::XView
+sal_Bool VCLXWindow::setGraphics( const css::uno::Reference< css::awt::XGraphics >& rxDevice )
+{
+ SolarMutexGuard aGuard;
+
+ if ( VCLUnoHelper::GetOutputDevice( rxDevice ) )
+ mpImpl->mxViewGraphics = rxDevice;
+ else
+ mpImpl->mxViewGraphics = nullptr;
+
+ return mpImpl->mxViewGraphics.is();
+}
+
+css::uno::Reference< css::awt::XGraphics > VCLXWindow::getGraphics( )
+{
+ SolarMutexGuard aGuard;
+
+ return mpImpl->mxViewGraphics;
+}
+
+css::awt::Size VCLXWindow::getSize( )
+{
+ SolarMutexGuard aGuard;
+
+ Size aSz;
+ if ( GetWindow() )
+ aSz = GetWindow()->GetSizePixel();
+ return css::awt::Size( aSz.Width(), aSz.Height() );
+}
+
+void VCLXWindow::draw( sal_Int32 nX, sal_Int32 nY )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( !pWindow )
+ return;
+
+ if ( !(isDesignMode() || mpImpl->isEnableVisible()) )
+ return;
+
+ OutputDevice* pDev = VCLUnoHelper::GetOutputDevice( mpImpl->mxViewGraphics );
+ if (!pDev)
+ pDev = pWindow->GetParent()->GetOutDev();
+ TabPage* pTabPage = dynamic_cast< TabPage* >( pWindow.get() );
+ if ( pTabPage )
+ {
+ Point aPos( nX, nY );
+ aPos = pDev->PixelToLogic( aPos );
+ pTabPage->Draw( pDev, aPos, SystemTextColorFlags::NONE );
+ return;
+ }
+
+ Point aPos( nX, nY );
+
+ if ( pWindow->GetParent() && !pWindow->IsSystemWindow() && ( pWindow->GetParent()->GetOutDev() == pDev ) )
+ {
+ // #i40647# don't draw here if this is a recursive call
+ // sometimes this is called recursively, because the Update call on the parent
+ // (strangely) triggers another paint. Prevent a stack overflow here
+ // Yes, this is only fixing symptoms for the moment...
+ // #i40647# / 2005-01-18 / frank.schoenheit@sun.com
+ if ( !mpImpl->getDrawingOntoParent_ref() )
+ {
+ ::comphelper::FlagGuard aDrawingflagGuard( mpImpl->getDrawingOntoParent_ref() );
+
+ bool bWasVisible = pWindow->IsVisible();
+ Point aOldPos( pWindow->GetPosPixel() );
+
+ if ( bWasVisible && aOldPos == aPos )
+ {
+ pWindow->PaintImmediately();
+ return;
+ }
+
+ pWindow->SetPosPixel( aPos );
+
+ // Update parent first to avoid painting the parent upon the update
+ // of this window, as it may otherwise cause the parent
+ // to hide this window again
+ if( pWindow->GetParent() )
+ pWindow->GetParent()->PaintImmediately();
+
+ pWindow->Show();
+ pWindow->PaintImmediately();
+ pWindow->SetParentUpdateMode( false );
+ pWindow->Hide();
+ pWindow->SetParentUpdateMode( true );
+
+ pWindow->SetPosPixel( aOldPos );
+ if ( bWasVisible )
+ pWindow->Show();
+ }
+ }
+ else if ( pDev )
+ {
+ Point aP = pDev->PixelToLogic( aPos );
+
+ vcl::PDFExtOutDevData* pPDFExport = dynamic_cast<vcl::PDFExtOutDevData*>(pDev->GetExtOutDevData());
+ bool bDrawSimple = ( pDev->GetOutDevType() == OUTDEV_PRINTER )
+ || ( pDev->GetOutDevViewType() == OutDevViewType::PrintPreview )
+ || ( pPDFExport != nullptr );
+ if ( bDrawSimple )
+ {
+ pWindow->Draw( pDev, aP, SystemTextColorFlags::NoControls );
+ }
+ else
+ {
+ bool bOldNW =pWindow->IsNativeWidgetEnabled();
+ if( bOldNW )
+ pWindow->EnableNativeWidget(false);
+ pWindow->PaintToDevice( pDev, aP );
+ if( bOldNW )
+ pWindow->EnableNativeWidget();
+ }
+ }
+}
+
+void VCLXWindow::setZoom( float fZoomX, float /*fZoomY*/ )
+{
+ SolarMutexGuard aGuard;
+
+ if ( GetWindow() )
+ {
+ // Fraction::Fraction takes a double, but we have a float only.
+ // The implicit conversion from float to double can result in a precision loss, i.e. 1.2 is converted to
+ // 1.200000000047something. To prevent this, we convert explicitly to double, and round it.
+ double nZoom( fZoomX );
+ Fraction aZoom(::rtl::math::round(nZoom, 4));
+ aZoom.ReduceInaccurate(10); // to avoid runovers and BigInt mapping
+ GetWindow()->SetZoom(aZoom);
+ }
+}
+
+// css::lang::XEventListener
+void SAL_CALL VCLXWindow::disposing( const css::lang::EventObject& _rSource )
+{
+ SolarMutexGuard aGuard;
+
+ if (mpImpl->mbDisposing)
+ return;
+
+ // check if it comes from our AccessibleContext
+ uno::Reference< uno::XInterface > aAC( mpImpl->mxAccessibleContext, uno::UNO_QUERY );
+ uno::Reference< uno::XInterface > xSource( _rSource.Source, uno::UNO_QUERY );
+
+ if ( aAC.get() == xSource.get() )
+ { // yep, it does
+ mpImpl->mxAccessibleContext.clear();
+ }
+}
+
+// css::accessibility::XAccessible
+css::uno::Reference< css::accessibility::XAccessibleContext > VCLXWindow::getAccessibleContext( )
+{
+ SolarMutexGuard aGuard;
+
+ // already disposed
+ if (mpImpl->mbDisposing)
+ return uno::Reference< accessibility::XAccessibleContext >();
+
+ if ( !mpImpl->mxAccessibleContext.is() && GetWindow() )
+ {
+ mpImpl->mxAccessibleContext = CreateAccessibleContext();
+
+ // add as event listener to this component
+ // in case somebody disposes it, we do not want to have a (though weak) reference to a dead
+ // object
+ uno::Reference< lang::XComponent > xComp( mpImpl->mxAccessibleContext, uno::UNO_QUERY );
+ if ( xComp.is() )
+ xComp->addEventListener( this );
+ }
+
+ return mpImpl->mxAccessibleContext;
+}
+
+// css::awt::XDockable
+void SAL_CALL VCLXWindow::addDockableWindowListener( const css::uno::Reference< css::awt::XDockableWindowListener >& xListener )
+{
+ SolarMutexGuard aGuard;
+
+ if (!mpImpl->mbDisposing && xListener.is() )
+ mpImpl->getDockableWindowListeners().addInterface( xListener );
+
+}
+
+void SAL_CALL VCLXWindow::removeDockableWindowListener( const css::uno::Reference< css::awt::XDockableWindowListener >& xListener )
+{
+ SolarMutexGuard aGuard;
+
+ if (!mpImpl->mbDisposing)
+ mpImpl->getDockableWindowListeners().removeInterface( xListener );
+}
+
+void SAL_CALL VCLXWindow::enableDocking( sal_Bool bEnable )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ pWindow->EnableDocking( bEnable );
+}
+
+sal_Bool SAL_CALL VCLXWindow::isFloating( )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if( pWindow )
+ return vcl::Window::GetDockingManager()->IsFloating( pWindow );
+ else
+ return false;
+}
+
+void SAL_CALL VCLXWindow::setFloatingMode( sal_Bool bFloating )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if( pWindow )
+ vcl::Window::GetDockingManager()->SetFloatingMode( pWindow, bFloating );
+}
+
+sal_Bool SAL_CALL VCLXWindow::isLocked( )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if( pWindow )
+ return vcl::Window::GetDockingManager()->IsLocked( pWindow );
+ else
+ return false;
+}
+
+void SAL_CALL VCLXWindow::lock( )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if( pWindow && !vcl::Window::GetDockingManager()->IsFloating( pWindow ) )
+ vcl::Window::GetDockingManager()->Lock( pWindow );
+}
+
+void SAL_CALL VCLXWindow::unlock( )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if( pWindow && !vcl::Window::GetDockingManager()->IsFloating( pWindow ) )
+ vcl::Window::GetDockingManager()->Unlock( pWindow );
+}
+
+void SAL_CALL VCLXWindow::startPopupMode( const css::awt::Rectangle& )
+{
+ // deprecated
+}
+
+sal_Bool SAL_CALL VCLXWindow::isInPopupMode( )
+{
+ // deprecated
+ return false;
+}
+
+
+// css::awt::XWindow2
+
+void SAL_CALL VCLXWindow::setOutputSize( const css::awt::Size& aSize )
+{
+ SolarMutexGuard aGuard;
+ if( VclPtr<vcl::Window> pWindow = GetWindow() )
+ pWindow->SetOutputSizePixel( VCLSize( aSize ) );
+}
+
+css::awt::Size SAL_CALL VCLXWindow::getOutputSize( )
+{
+ SolarMutexGuard aGuard;
+ if( VclPtr<vcl::Window> pWindow = GetWindow() )
+ return AWTSize( pWindow->GetOutputSizePixel() );
+ else
+ return css::awt::Size();
+}
+
+sal_Bool SAL_CALL VCLXWindow::isVisible( )
+{
+ SolarMutexGuard aGuard;
+ if( GetWindow() )
+ return GetWindow()->IsVisible();
+ else
+ return false;
+}
+
+sal_Bool SAL_CALL VCLXWindow::isActive( )
+{
+ SolarMutexGuard aGuard;
+ if( GetWindow() )
+ return GetWindow()->IsActive();
+ else
+ return false;
+
+}
+
+sal_Bool SAL_CALL VCLXWindow::isEnabled( )
+{
+ SolarMutexGuard aGuard;
+ if( GetWindow() )
+ return GetWindow()->IsEnabled();
+ else
+ return false;
+}
+
+sal_Bool SAL_CALL VCLXWindow::hasFocus( )
+{
+ SolarMutexGuard aGuard;
+ if( GetWindow() )
+ return GetWindow()->HasFocus();
+ else
+ return false;
+}
+
+// css::beans::XPropertySetInfo
+
+UnoPropertyArrayHelper *
+VCLXWindow::GetPropHelper()
+{
+ SolarMutexGuard aGuard;
+ if ( mpImpl->mpPropHelper == nullptr )
+ {
+ std::vector< sal_uInt16 > aIDs;
+ GetPropertyIds( aIDs );
+ mpImpl->mpPropHelper.reset( new UnoPropertyArrayHelper( aIDs ) );
+ }
+ return mpImpl->mpPropHelper.get();
+}
+
+css::uno::Sequence< css::beans::Property > SAL_CALL
+VCLXWindow::getProperties()
+{
+ return GetPropHelper()->getProperties();
+}
+css::beans::Property SAL_CALL
+VCLXWindow::getPropertyByName( const OUString& rName )
+{
+ return GetPropHelper()->getPropertyByName( rName );
+}
+
+sal_Bool SAL_CALL
+VCLXWindow::hasPropertyByName( const OUString& rName )
+{
+ return GetPropHelper()->hasPropertyByName( rName );
+}
+
+Reference< XStyleSettings > SAL_CALL VCLXWindow::getStyleSettings()
+{
+ return mpImpl->getStyleSettings();
+}
+
+bool VCLXWindow::IsDisposed() const
+{
+ return mpImpl->mbDisposing;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/awt/vclxwindow1.cxx b/toolkit/source/awt/vclxwindow1.cxx
new file mode 100644
index 0000000000..edc78f7d92
--- /dev/null
+++ b/toolkit/source/awt/vclxwindow1.cxx
@@ -0,0 +1,90 @@
+/* -*- 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 <toolkit/awt/vclxwindow.hxx>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <vcl/wrkwin.hxx>
+#include <vcl/window.hxx>
+
+#ifdef _WIN32
+#include <prewin.h>
+#include <postwin.h>
+#elif defined(MACOSX)
+#include <premac.h>
+#include <Cocoa/Cocoa.h>
+#include <postmac.h>
+#endif
+#include <vcl/sysdata.hxx>
+
+/// helper method to set a window handle into a SystemParentData struct
+void VCLXWindow::SetSystemParent_Impl(const css::uno::Any& rHandle)
+{
+ // does only work for WorkWindows
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if (pWindow->GetType() != WindowType::WORKWINDOW)
+ {
+ throw css::uno::RuntimeException("not a work window");
+ }
+
+ // use sal_Int64 here to accommodate all int types
+ // uno::Any shift operator will upcast if necessary
+ sal_Int64 nHandle = 0;
+ bool bXEmbed = false;
+ bool bThrow = false;
+ if (!(rHandle >>= nHandle))
+ {
+ css::uno::Sequence<css::beans::NamedValue> aProps;
+ if (rHandle >>= aProps)
+ {
+ for (const css::beans::NamedValue& rProp : std::as_const(aProps))
+ {
+ if (rProp.Name == "WINDOW")
+ rProp.Value >>= nHandle;
+ else if (rProp.Name == "XEMBED")
+ rProp.Value >>= bXEmbed;
+ }
+ }
+ else
+ bThrow = true;
+ }
+ if (bThrow)
+ {
+ throw css::uno::RuntimeException("incorrect window handle type");
+ }
+ // create system parent data
+ SystemParentData aSysParentData;
+ aSysParentData.nSize = sizeof(SystemParentData);
+#if defined(_WIN32)
+ aSysParentData.hWnd = reinterpret_cast<HWND>(nHandle);
+#elif defined(MACOSX)
+ aSysParentData.pView = reinterpret_cast<NSView*>(nHandle);
+#elif defined(ANDROID)
+ // Nothing
+#elif defined(IOS)
+ // Nothing
+#elif defined(UNX)
+ aSysParentData.aWindow = nHandle;
+ aSysParentData.bXEmbedSupport = bXEmbed;
+#endif
+
+ // set system parent
+ static_cast<WorkWindow*>(pWindow.get())->SetPluginParent(&aSysParentData);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/awt/vclxwindows.cxx b/toolkit/source/awt/vclxwindows.cxx
new file mode 100644
index 0000000000..d6ba5e48a6
--- /dev/null
+++ b/toolkit/source/awt/vclxwindows.cxx
@@ -0,0 +1,7877 @@
+/* -*- 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 <toolkit/awt/vclxwindows.hxx>
+#include <toolkit/helper/accessiblefactory.hxx>
+#include <com/sun/star/awt/LineEndFormat.hpp>
+#include <com/sun/star/awt/ScrollBarOrientation.hpp>
+#include <com/sun/star/graphic/GraphicProvider.hpp>
+#include <com/sun/star/graphic/XGraphicProvider.hpp>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <helper/property.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <com/sun/star/awt/VisualEffect.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/resource/XStringResourceResolver.hpp>
+#include <com/sun/star/awt/ImageScaleMode.hpp>
+#include <com/sun/star/awt/XItemList.hpp>
+#include <com/sun/star/awt/TextAlign.hpp>
+#include <comphelper/namedvaluecollection.hxx>
+#include <comphelper/processfactory.hxx>
+#include <sal/log.hxx>
+
+#include <awt/vclxwindows.hxx>
+#include <controls/filectrl.hxx>
+#include <controls/svmedit.hxx>
+#include <vcl/toolkit/button.hxx>
+#include <vcl/toolkit/fmtfield.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/toolkit/lstbox.hxx>
+#include <vcl/toolkit/combobox.hxx>
+#include <vcl/toolkit/field.hxx>
+#include <vcl/toolkit/fixedhyper.hxx>
+#include <vcl/toolkit/imgctrl.hxx>
+#include <vcl/toolkit/dialog.hxx>
+#include <vcl/toolkit/prgsbar.hxx>
+#include <vcl/toolkit/scrbar.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/tabpage.hxx>
+#include <vcl/tabctrl.hxx>
+#include <vcl/settings.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <tools/debug.hxx>
+
+#include <helper/imagealign.hxx>
+#include <helper/msgbox.hxx>
+#include <helper/tkresmgr.hxx>
+#include "vclxwindows_internal.hxx"
+#include <svl/numformat.hxx>
+
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::RuntimeException;
+using ::com::sun::star::lang::EventObject;
+using ::com::sun::star::awt::ItemListEvent;
+using ::com::sun::star::awt::XItemList;
+using ::com::sun::star::graphic::XGraphic;
+using ::com::sun::star::graphic::XGraphicProvider;
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::awt::VisualEffect;
+namespace ImageScaleMode = ::com::sun::star::awt::ImageScaleMode;
+
+static double ImplCalcLongValue( double nValue, sal_uInt16 nDigits )
+{
+ double n = nValue;
+ for ( sal_uInt16 d = 0; d < nDigits; d++ )
+ n *= 10;
+ return n;
+}
+
+static double ImplCalcDoubleValue( double nValue, sal_uInt16 nDigits )
+{
+ double n = nValue;
+ for ( sal_uInt16 d = 0; d < nDigits; d++ )
+ n /= 10;
+ return n;
+}
+
+namespace toolkit
+{
+ /** sets the "face color" for button like controls (scroll bar, spin button)
+ */
+ void setButtonLikeFaceColor( vcl::Window* _pWindow, const css::uno::Any& _rColorValue )
+ {
+ AllSettings aSettings = _pWindow->GetSettings();
+ StyleSettings aStyleSettings = aSettings.GetStyleSettings();
+
+ if ( !_rColorValue.hasValue() )
+ {
+ const StyleSettings& aAppStyle = Application::GetSettings().GetStyleSettings();
+ aStyleSettings.SetFaceColor( aAppStyle.GetFaceColor( ) );
+ aStyleSettings.SetCheckedColor( aAppStyle.GetCheckedColor( ) );
+ aStyleSettings.SetLightBorderColor( aAppStyle.GetLightBorderColor() );
+ aStyleSettings.SetLightColor( aAppStyle.GetLightColor() );
+ aStyleSettings.SetShadowColor( aAppStyle.GetShadowColor() );
+ aStyleSettings.SetDarkShadowColor( aAppStyle.GetDarkShadowColor() );
+ }
+ else
+ {
+ Color nBackgroundColor;
+ _rColorValue >>= nBackgroundColor;
+ aStyleSettings.SetFaceColor( nBackgroundColor );
+
+ // for the real background (everything except the buttons and the thumb),
+ // use an average between the desired color and "white"
+ Color aWhite( COL_WHITE );
+ Color aCheckedBackground( nBackgroundColor );
+ aCheckedBackground.SetRed( ( aCheckedBackground.GetRed() + aWhite.GetRed() ) / 2 );
+ aCheckedBackground.SetGreen( ( aCheckedBackground.GetGreen() + aWhite.GetGreen() ) / 2 );
+ aCheckedBackground.SetBlue( ( aCheckedBackground.GetBlue() + aWhite.GetBlue() ) / 2 );
+ aStyleSettings.SetCheckedColor( aCheckedBackground );
+
+ sal_Int32 nBackgroundLuminance = nBackgroundColor.GetLuminance();
+ sal_Int32 nWhiteLuminance = COL_WHITE.GetLuminance();
+
+ Color aLightShadow( nBackgroundColor );
+ aLightShadow.IncreaseLuminance( static_cast<sal_uInt8>( ( nWhiteLuminance - nBackgroundLuminance ) * 2 / 3 ) );
+ aStyleSettings.SetLightBorderColor( aLightShadow );
+
+ Color aLight( nBackgroundColor );
+ aLight.IncreaseLuminance( static_cast<sal_uInt8>( ( nWhiteLuminance - nBackgroundLuminance ) * 1 / 3 ) );
+ aStyleSettings.SetLightColor( aLight );
+
+ Color aShadow( nBackgroundColor );
+ aShadow.DecreaseLuminance( static_cast<sal_uInt8>( nBackgroundLuminance * 1 / 3 ) );
+ aStyleSettings.SetShadowColor( aShadow );
+
+ Color aDarkShadow( nBackgroundColor );
+ aDarkShadow.DecreaseLuminance( static_cast<sal_uInt8>( nBackgroundLuminance * 2 / 3 ) );
+ aStyleSettings.SetDarkShadowColor( aDarkShadow );
+ }
+
+ aSettings.SetStyleSettings( aStyleSettings );
+ _pWindow->SetSettings( aSettings, true );
+ }
+
+ Any getButtonLikeFaceColor( const vcl::Window* _pWindow )
+ {
+ Color nBackgroundColor = _pWindow->GetSettings().GetStyleSettings().GetFaceColor();
+ return Any( sal_Int32(nBackgroundColor) );
+ }
+
+ static void adjustBooleanWindowStyle( const Any& _rValue, vcl::Window* _pWindow, WinBits _nBits, bool _bInverseSemantics )
+ {
+ WinBits nStyle = _pWindow->GetStyle();
+ bool bValue( false );
+ OSL_VERIFY( _rValue >>= bValue );
+ if ( bValue != _bInverseSemantics )
+ nStyle |= _nBits;
+ else
+ nStyle &= ~_nBits;
+ _pWindow->SetStyle( nStyle );
+ }
+
+ static void setVisualEffect( const Any& _rValue, vcl::Window* _pWindow )
+ {
+ AllSettings aSettings = _pWindow->GetSettings();
+ StyleSettings aStyleSettings = aSettings.GetStyleSettings();
+
+ sal_Int16 nStyle = LOOK3D;
+ OSL_VERIFY( _rValue >>= nStyle );
+ switch ( nStyle )
+ {
+ case FLAT:
+ aStyleSettings.SetOptions( aStyleSettings.GetOptions() | StyleSettingsOptions::Mono );
+ break;
+ case LOOK3D:
+ default:
+ aStyleSettings.SetOptions( aStyleSettings.GetOptions() & ~StyleSettingsOptions::Mono );
+ }
+ aSettings.SetStyleSettings( aStyleSettings );
+ _pWindow->SetSettings( aSettings );
+ }
+
+ static Any getVisualEffect( vcl::Window const * _pWindow )
+ {
+ Any aEffect;
+
+ StyleSettings aStyleSettings = _pWindow->GetSettings().GetStyleSettings();
+ if ( aStyleSettings.GetOptions() & StyleSettingsOptions::Mono )
+ aEffect <<= sal_Int16(FLAT);
+ else
+ aEffect <<= sal_Int16(LOOK3D);
+ return aEffect;
+ }
+}
+
+
+
+
+void VCLXGraphicControl::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ VCLXWindow::ImplGetPropertyIds( rIds );
+}
+
+void VCLXGraphicControl::ImplSetNewImage()
+{
+ OSL_PRECOND( GetWindow(), "VCLXGraphicControl::ImplSetNewImage: window is required to be not-NULL!" );
+ VclPtr< Button > pButton = GetAsDynamic< Button >();
+ pButton->SetModeImage( GetImage() );
+}
+
+void VCLXGraphicControl::setPosSize( sal_Int32 X, sal_Int32 Y, sal_Int32 Width, sal_Int32 Height, sal_Int16 Flags )
+{
+ SolarMutexGuard aGuard;
+
+ if ( GetWindow() )
+ {
+ Size aOldSize = GetWindow()->GetSizePixel();
+ VCLXWindow::setPosSize( X, Y, Width, Height, Flags );
+ if ( ( aOldSize.Width() != Width ) || ( aOldSize.Height() != Height ) )
+ ImplSetNewImage();
+ }
+}
+
+void VCLXGraphicControl::setProperty( const OUString& PropertyName, const css::uno::Any& Value)
+{
+ SolarMutexGuard aGuard;
+
+ if ( !GetWindow() )
+ return;
+
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_GRAPHIC:
+ {
+ Reference< XGraphic > xGraphic;
+ OSL_VERIFY( Value >>= xGraphic );
+ maImage = Image( xGraphic );
+ ImplSetNewImage();
+ }
+ break;
+
+ case BASEPROPERTY_IMAGEALIGN:
+ {
+ WindowType eType = GetWindow()->GetType();
+ if ( ( eType == WindowType::PUSHBUTTON )
+ || ( eType == WindowType::RADIOBUTTON )
+ || ( eType == WindowType::CHECKBOX )
+ )
+ {
+ sal_Int16 nAlignment = sal_Int16();
+ if ( Value >>= nAlignment )
+ GetAs< Button >()->SetImageAlign( static_cast< ImageAlign >( nAlignment ) );
+ }
+ }
+ break;
+ case BASEPROPERTY_IMAGEPOSITION:
+ {
+ WindowType eType = GetWindow()->GetType();
+ if ( ( eType == WindowType::PUSHBUTTON )
+ || ( eType == WindowType::RADIOBUTTON )
+ || ( eType == WindowType::CHECKBOX )
+ )
+ {
+ sal_Int16 nImagePosition = 2;
+ OSL_VERIFY( Value >>= nImagePosition );
+ GetAs<Button>()->SetImageAlign( ::toolkit::translateImagePosition( nImagePosition ) );
+ }
+ }
+ break;
+ default:
+ VCLXWindow::setProperty( PropertyName, Value );
+ break;
+ }
+}
+
+css::uno::Any VCLXGraphicControl::getProperty( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Any aProp;
+ if ( !GetWindow() )
+ return aProp;
+
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_GRAPHIC:
+ aProp <<= Graphic(maImage.GetBitmapEx()).GetXGraphic();
+ break;
+ case BASEPROPERTY_IMAGEALIGN:
+ {
+ WindowType eType = GetWindow()->GetType();
+ if ( ( eType == WindowType::PUSHBUTTON )
+ || ( eType == WindowType::RADIOBUTTON )
+ || ( eType == WindowType::CHECKBOX )
+ )
+ {
+ aProp <<= ::toolkit::getCompatibleImageAlign(
+ GetAs<Button>()->GetImageAlign() );
+ }
+ }
+ break;
+ case BASEPROPERTY_IMAGEPOSITION:
+ {
+ WindowType eType = GetWindow()->GetType();
+ if ( ( eType == WindowType::PUSHBUTTON )
+ || ( eType == WindowType::RADIOBUTTON )
+ || ( eType == WindowType::CHECKBOX )
+ )
+ {
+ aProp <<= ::toolkit::translateImagePosition(
+ GetAs< Button >()->GetImageAlign() );
+ }
+ }
+ break;
+ default:
+ {
+ aProp = VCLXWindow::getProperty( PropertyName );
+ }
+ break;
+ }
+ return aProp;
+}
+
+
+
+
+void VCLXButton::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ BASEPROPERTY_BACKGROUNDCOLOR,
+ BASEPROPERTY_DEFAULTBUTTON,
+ BASEPROPERTY_DEFAULTCONTROL,
+ BASEPROPERTY_ENABLED,
+ BASEPROPERTY_ENABLEVISIBLE,
+ BASEPROPERTY_FONTDESCRIPTOR,
+ BASEPROPERTY_GRAPHIC,
+ BASEPROPERTY_HELPTEXT,
+ BASEPROPERTY_HELPURL,
+ BASEPROPERTY_IMAGEALIGN,
+ BASEPROPERTY_IMAGEPOSITION,
+ BASEPROPERTY_IMAGEURL,
+ BASEPROPERTY_LABEL,
+ BASEPROPERTY_PRINTABLE,
+ BASEPROPERTY_PUSHBUTTONTYPE,
+ BASEPROPERTY_REPEAT,
+ BASEPROPERTY_REPEAT_DELAY,
+ BASEPROPERTY_STATE,
+ BASEPROPERTY_TABSTOP,
+ BASEPROPERTY_TOGGLE,
+ BASEPROPERTY_FOCUSONCLICK,
+ BASEPROPERTY_MULTILINE,
+ BASEPROPERTY_ALIGN,
+ BASEPROPERTY_VERTICALALIGN,
+ BASEPROPERTY_WRITING_MODE,
+ BASEPROPERTY_CONTEXT_WRITING_MODE,
+ BASEPROPERTY_REFERENCE_DEVICE,
+ 0);
+ VCLXGraphicControl::ImplGetPropertyIds( rIds );
+}
+
+VCLXButton::VCLXButton()
+ :maActionListeners( *this )
+ ,maItemListeners( *this )
+{
+}
+
+VCLXButton::~VCLXButton()
+{
+}
+
+css::uno::Reference< css::accessibility::XAccessibleContext > VCLXButton::CreateAccessibleContext()
+{
+ return getAccessibleFactory().createAccessibleContext( this );
+}
+
+void VCLXButton::dispose()
+{
+ SolarMutexGuard aGuard;
+
+ css::lang::EventObject aObj;
+ aObj.Source = getXWeak();
+ maActionListeners.disposeAndClear( aObj );
+ maItemListeners.disposeAndClear( aObj );
+ VCLXGraphicControl::dispose();
+}
+
+void VCLXButton::addActionListener( const css::uno::Reference< css::awt::XActionListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maActionListeners.addInterface( l );
+}
+
+void VCLXButton::removeActionListener( const css::uno::Reference< css::awt::XActionListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maActionListeners.removeInterface( l );
+}
+
+void VCLXButton::addItemListener( const css::uno::Reference< css::awt::XItemListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maItemListeners.addInterface( l );
+}
+
+void VCLXButton::removeItemListener( const css::uno::Reference< css::awt::XItemListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maItemListeners.removeInterface( l );
+}
+
+void VCLXButton::setLabel( const OUString& rLabel )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ pWindow->SetText( rLabel );
+}
+
+void VCLXButton::setActionCommand( const OUString& rCommand )
+{
+ SolarMutexGuard aGuard;
+
+ maActionCommand = rCommand;
+}
+
+css::awt::Size VCLXButton::getMinimumSize( )
+{
+ SolarMutexGuard aGuard;
+
+ Size aSz;
+ VclPtr< PushButton > pButton = GetAs< PushButton >();
+ if ( pButton )
+ aSz = pButton->CalcMinimumSize();
+ return AWTSize(aSz);
+}
+
+css::awt::Size VCLXButton::getPreferredSize( )
+{
+ css::awt::Size aSz = getMinimumSize();
+ aSz.Width += 16;
+ aSz.Height += 10;
+ return aSz;
+}
+
+css::awt::Size VCLXButton::calcAdjustedSize( const css::awt::Size& rNewSize )
+{
+ SolarMutexGuard aGuard;
+
+ Size aSz = VCLSize(rNewSize);
+ VclPtr< PushButton > pButton = GetAs< PushButton >();
+ if ( pButton )
+ {
+ Size aMinSz = pButton->CalcMinimumSize();
+ // no text, thus image
+ if ( pButton->GetText().isEmpty() )
+ {
+ if ( aSz.Width() < aMinSz.Width() )
+ aSz.setWidth( aMinSz.Width() );
+ if ( aSz.Height() < aMinSz.Height() )
+ aSz.setHeight( aMinSz.Height() );
+ }
+ else
+ {
+ if ( ( aSz.Width() > aMinSz.Width() ) && ( aSz.Height() < aMinSz.Height() ) )
+ aSz.setHeight( aMinSz.Height() );
+ else
+ aSz = aMinSz;
+ }
+ }
+ return AWTSize(aSz);
+}
+
+void VCLXButton::setProperty( const OUString& PropertyName, const css::uno::Any& Value)
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< Button > pButton = GetAs< Button >();
+ if ( !pButton )
+ return;
+
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_FOCUSONCLICK:
+ ::toolkit::adjustBooleanWindowStyle( Value, pButton, WB_NOPOINTERFOCUS, true );
+ break;
+
+ case BASEPROPERTY_TOGGLE:
+ ::toolkit::adjustBooleanWindowStyle( Value, pButton, WB_TOGGLE, false );
+ break;
+
+ case BASEPROPERTY_DEFAULTBUTTON:
+ {
+ WinBits nStyle = pButton->GetStyle() | WB_DEFBUTTON;
+ bool b = bool();
+ if ( ( Value >>= b ) && !b )
+ nStyle &= ~WB_DEFBUTTON;
+ pButton->SetStyle( nStyle );
+ }
+ break;
+ case BASEPROPERTY_STATE:
+ {
+ if ( GetWindow()->GetType() == WindowType::PUSHBUTTON )
+ {
+ sal_Int16 n = sal_Int16();
+ if ( Value >>= n )
+ static_cast<PushButton*>(pButton.get())->SetState( static_cast<TriState>(n) );
+ }
+ }
+ break;
+ default:
+ {
+ VCLXGraphicControl::setProperty( PropertyName, Value );
+ }
+ }
+}
+
+css::uno::Any VCLXButton::getProperty( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Any aProp;
+ VclPtr< Button > pButton = GetAs< Button >();
+ if ( pButton )
+ {
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_FOCUSONCLICK:
+ aProp <<= ( ( pButton->GetStyle() & WB_NOPOINTERFOCUS ) == 0 );
+ break;
+
+ case BASEPROPERTY_TOGGLE:
+ aProp <<= ( ( pButton->GetStyle() & WB_TOGGLE ) != 0 );
+ break;
+
+ case BASEPROPERTY_DEFAULTBUTTON:
+ {
+ aProp <<= ( pButton->GetStyle() & WB_DEFBUTTON ) != 0;
+ }
+ break;
+ case BASEPROPERTY_STATE:
+ {
+ if ( GetWindow()->GetType() == WindowType::PUSHBUTTON )
+ {
+ aProp <<= static_cast<sal_Int16>(static_cast<PushButton*>(pButton.get())->GetState());
+ }
+ }
+ break;
+ default:
+ {
+ aProp = VCLXGraphicControl::getProperty( PropertyName );
+ }
+ }
+ }
+ return aProp;
+}
+
+void VCLXButton::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::ButtonClick:
+ {
+ css::uno::Reference< css::awt::XWindow > xKeepAlive( this );
+ // since we call listeners below, there is a potential that we will be destroyed
+ // during the listener call. To prevent the resulting crashes, we keep us
+ // alive as long as we're here
+
+ if ( maActionListeners.getLength() )
+ {
+ css::awt::ActionEvent aEvent;
+ aEvent.Source = getXWeak();
+ aEvent.ActionCommand = maActionCommand;
+
+ Callback aCallback = [ this, aEvent ]()
+ { this->maActionListeners.actionPerformed( aEvent ); };
+
+ ImplExecuteAsyncWithoutSolarLock( aCallback );
+ }
+ }
+ break;
+
+ case VclEventId::PushbuttonToggle:
+ {
+ PushButton& rButton = dynamic_cast< PushButton& >( *rVclWindowEvent.GetWindow() );
+
+ css::uno::Reference< css::awt::XWindow > xKeepAlive( this );
+ if ( maItemListeners.getLength() )
+ {
+ css::awt::ItemEvent aEvent;
+ aEvent.Source = getXWeak();
+ aEvent.Selected = ( rButton.GetState() == TRISTATE_TRUE ) ? 1 : 0;
+ maItemListeners.itemStateChanged( aEvent );
+ }
+ }
+ break;
+
+ default:
+ VCLXGraphicControl::ProcessWindowEvent( rVclWindowEvent );
+ break;
+ }
+}
+
+
+
+
+void VCLXImageControl::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ BASEPROPERTY_BACKGROUNDCOLOR,
+ BASEPROPERTY_BORDER,
+ BASEPROPERTY_BORDERCOLOR,
+ BASEPROPERTY_DEFAULTCONTROL,
+ BASEPROPERTY_ENABLED,
+ BASEPROPERTY_ENABLEVISIBLE,
+ BASEPROPERTY_GRAPHIC,
+ BASEPROPERTY_HELPTEXT,
+ BASEPROPERTY_HELPURL,
+ BASEPROPERTY_IMAGEURL,
+ BASEPROPERTY_PRINTABLE,
+ BASEPROPERTY_SCALEIMAGE,
+ BASEPROPERTY_IMAGE_SCALE_MODE,
+ BASEPROPERTY_TABSTOP,
+ BASEPROPERTY_WRITING_MODE,
+ BASEPROPERTY_CONTEXT_WRITING_MODE,
+ 0);
+ VCLXGraphicControl::ImplGetPropertyIds( rIds );
+}
+
+VCLXImageControl::VCLXImageControl()
+{
+}
+
+VCLXImageControl::~VCLXImageControl()
+{
+}
+
+void VCLXImageControl::ImplSetNewImage()
+{
+ OSL_PRECOND( GetWindow(), "VCLXImageControl::ImplSetNewImage: window is required to be not-NULL!" );
+ VclPtr<ImageControl> pControl = GetAs< ImageControl >();
+ pControl->SetImage( GetImage() );
+}
+
+css::awt::Size VCLXImageControl::getMinimumSize( )
+{
+ SolarMutexGuard aGuard;
+
+ Size aSz = GetImage().GetSizePixel();
+ aSz = ImplCalcWindowSize( aSz );
+
+ return AWTSize(aSz);
+}
+
+css::awt::Size VCLXImageControl::getPreferredSize( )
+{
+ return getMinimumSize();
+}
+
+css::awt::Size VCLXImageControl::calcAdjustedSize( const css::awt::Size& rNewSize )
+{
+ SolarMutexGuard aGuard;
+
+ css::awt::Size aSz = rNewSize;
+ css::awt::Size aMinSz = getMinimumSize();
+ if ( aSz.Width < aMinSz.Width )
+ aSz.Width = aMinSz.Width;
+ if ( aSz.Height < aMinSz.Height )
+ aSz.Height = aMinSz.Height;
+ return aSz;
+}
+
+void VCLXImageControl::setProperty( const OUString& PropertyName, const css::uno::Any& Value)
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ImageControl > pImageControl = GetAs< ImageControl >();
+
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_IMAGE_SCALE_MODE:
+ {
+ sal_Int16 nScaleMode( ImageScaleMode::ANISOTROPIC );
+ if ( pImageControl && ( Value >>= nScaleMode ) )
+ {
+ pImageControl->SetScaleMode( nScaleMode );
+ }
+ }
+ break;
+
+ case BASEPROPERTY_SCALEIMAGE:
+ {
+ // this is for compatibility only, nowadays, the ImageScaleMode property should be used
+ bool bScaleImage = false;
+ if ( pImageControl && ( Value >>= bScaleImage ) )
+ {
+ pImageControl->SetScaleMode( bScaleImage ? ImageScaleMode::ANISOTROPIC : ImageScaleMode::NONE );
+ }
+ }
+ break;
+
+ default:
+ VCLXGraphicControl::setProperty( PropertyName, Value );
+ break;
+ }
+}
+
+css::uno::Any VCLXImageControl::getProperty( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Any aProp;
+ VclPtr< ImageControl > pImageControl = GetAs< ImageControl >();
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_IMAGE_SCALE_MODE:
+ aProp <<= ( pImageControl ? pImageControl->GetScaleMode() : ImageScaleMode::ANISOTROPIC );
+ break;
+
+ case BASEPROPERTY_SCALEIMAGE:
+ aProp <<= ( pImageControl && pImageControl->GetScaleMode() != ImageScaleMode::NONE );
+ break;
+
+ default:
+ aProp = VCLXGraphicControl::getProperty( PropertyName );
+ break;
+ }
+ return aProp;
+}
+
+
+
+
+void VCLXCheckBox::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ BASEPROPERTY_DEFAULTCONTROL,
+ BASEPROPERTY_ENABLED,
+ BASEPROPERTY_ENABLEVISIBLE,
+ BASEPROPERTY_FONTDESCRIPTOR,
+ BASEPROPERTY_GRAPHIC,
+ BASEPROPERTY_HELPTEXT,
+ BASEPROPERTY_HELPURL,
+ BASEPROPERTY_IMAGEPOSITION,
+ BASEPROPERTY_IMAGEURL,
+ BASEPROPERTY_LABEL,
+ BASEPROPERTY_PRINTABLE,
+ BASEPROPERTY_STATE,
+ BASEPROPERTY_TABSTOP,
+ BASEPROPERTY_TRISTATE,
+ BASEPROPERTY_VISUALEFFECT,
+ BASEPROPERTY_MULTILINE,
+ BASEPROPERTY_BACKGROUNDCOLOR,
+ BASEPROPERTY_ALIGN,
+ BASEPROPERTY_VERTICALALIGN,
+ BASEPROPERTY_WRITING_MODE,
+ BASEPROPERTY_CONTEXT_WRITING_MODE,
+ BASEPROPERTY_REFERENCE_DEVICE,
+ 0);
+ VCLXGraphicControl::ImplGetPropertyIds( rIds );
+}
+
+VCLXCheckBox::VCLXCheckBox() : maActionListeners( *this ), maItemListeners( *this )
+{
+}
+
+css::uno::Reference< css::accessibility::XAccessibleContext > VCLXCheckBox::CreateAccessibleContext()
+{
+ return getAccessibleFactory().createAccessibleContext( this );
+}
+
+void VCLXCheckBox::dispose()
+{
+ SolarMutexGuard aGuard;
+
+ css::lang::EventObject aObj;
+ aObj.Source = getXWeak();
+ maItemListeners.disposeAndClear( aObj );
+ VCLXGraphicControl::dispose();
+}
+
+void VCLXCheckBox::addItemListener( const css::uno::Reference< css::awt::XItemListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maItemListeners.addInterface( l );
+}
+
+void VCLXCheckBox::removeItemListener( const css::uno::Reference< css::awt::XItemListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maItemListeners.removeInterface( l );
+}
+
+void VCLXCheckBox::addActionListener( const css::uno::Reference< css::awt::XActionListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maActionListeners.addInterface( l );
+}
+
+void VCLXCheckBox::removeActionListener( const css::uno::Reference< css::awt::XActionListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maActionListeners.removeInterface( l );
+}
+
+void VCLXCheckBox::setActionCommand( const OUString& rCommand )
+{
+ SolarMutexGuard aGuard;
+ maActionCommand = rCommand;
+}
+
+void VCLXCheckBox::setLabel( const OUString& rLabel )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ pWindow->SetText( rLabel );
+}
+
+void VCLXCheckBox::setState( sal_Int16 n )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< CheckBox> pCheckBox = GetAs< CheckBox >();
+ if ( !pCheckBox)
+ return;
+
+ TriState eState;
+ switch ( n )
+ {
+ case 0: eState = TRISTATE_FALSE; break;
+ case 1: eState = TRISTATE_TRUE; break;
+ case 2: eState = TRISTATE_INDET; break;
+ default: eState = TRISTATE_FALSE;
+ }
+ pCheckBox->SetState( eState );
+
+ // #105198# call C++ click listeners (needed for accessibility)
+ // pCheckBox->GetClickHdl().Call( pCheckBox );
+
+ // #107218# Call same virtual methods and listeners like VCL would do after user interaction
+ SetSynthesizingVCLEvent( true );
+ pCheckBox->Toggle();
+ pCheckBox->Click();
+ SetSynthesizingVCLEvent( false );
+}
+
+sal_Int16 VCLXCheckBox::getState()
+{
+ SolarMutexGuard aGuard;
+
+ sal_Int16 nState = -1;
+ VclPtr< CheckBox > pCheckBox = GetAs< CheckBox >();
+ if ( pCheckBox )
+ {
+ switch ( pCheckBox->GetState() )
+ {
+ case TRISTATE_FALSE: nState = 0; break;
+ case TRISTATE_TRUE: nState = 1; break;
+ case TRISTATE_INDET: nState = 2; break;
+ default: OSL_FAIL( "VCLXCheckBox::getState(): unknown TriState!" );
+ }
+ }
+
+ return nState;
+}
+
+void VCLXCheckBox::enableTriState( sal_Bool b )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< CheckBox > pCheckBox = GetAs< CheckBox >();
+ if ( pCheckBox)
+ pCheckBox->EnableTriState( b );
+}
+
+css::awt::Size VCLXCheckBox::getMinimumSize()
+{
+ SolarMutexGuard aGuard;
+
+ Size aSz;
+ VclPtr< CheckBox > pCheckBox = GetAs< CheckBox >();
+ if ( pCheckBox )
+ aSz = pCheckBox->CalcMinimumSize();
+ return AWTSize(aSz);
+}
+
+css::awt::Size VCLXCheckBox::getPreferredSize()
+{
+ return getMinimumSize();
+}
+
+css::awt::Size VCLXCheckBox::calcAdjustedSize( const css::awt::Size& rNewSize )
+{
+ SolarMutexGuard aGuard;
+
+ Size aSz = VCLSize(rNewSize);
+ VclPtr< CheckBox > pCheckBox = GetAs< CheckBox >();
+ if ( pCheckBox )
+ {
+ Size aMinSz = pCheckBox->CalcMinimumSize(rNewSize.Width);
+ if ( ( aSz.Width() > aMinSz.Width() ) && ( aSz.Height() < aMinSz.Height() ) )
+ aSz.setHeight( aMinSz.Height() );
+ else
+ aSz = aMinSz;
+ }
+ return AWTSize(aSz);
+}
+
+void VCLXCheckBox::setProperty( const OUString& PropertyName, const css::uno::Any& Value)
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< CheckBox > pCheckBox = GetAs< CheckBox >();
+ if ( !pCheckBox )
+ return;
+
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_VISUALEFFECT:
+ ::toolkit::setVisualEffect( Value, pCheckBox );
+ break;
+
+ case BASEPROPERTY_TRISTATE:
+ {
+ bool b = bool();
+ if ( Value >>= b )
+ pCheckBox->EnableTriState( b );
+ }
+ break;
+ case BASEPROPERTY_STATE:
+ {
+ sal_Int16 n = sal_Int16();
+ if ( Value >>= n )
+ setState( n );
+ }
+ break;
+ default:
+ {
+ VCLXGraphicControl::setProperty( PropertyName, Value );
+ }
+ }
+}
+
+css::uno::Any VCLXCheckBox::getProperty( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Any aProp;
+ VclPtr< CheckBox > pCheckBox = GetAs< CheckBox >();
+ if ( pCheckBox )
+ {
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_VISUALEFFECT:
+ aProp = ::toolkit::getVisualEffect( pCheckBox );
+ break;
+ case BASEPROPERTY_TRISTATE:
+ aProp <<= pCheckBox->IsTriStateEnabled();
+ break;
+ case BASEPROPERTY_STATE:
+ aProp <<= static_cast<sal_Int16>(pCheckBox->GetState());
+ break;
+ default:
+ {
+ aProp = VCLXGraphicControl::getProperty( PropertyName );
+ }
+ }
+ }
+ return aProp;
+}
+
+void VCLXCheckBox::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::CheckboxToggle:
+ {
+ css::uno::Reference< css::awt::XWindow > xKeepAlive( this );
+ // since we call listeners below, there is a potential that we will be destroyed
+ // in during the listener call. To prevent the resulting crashes, we keep us
+ // alive as long as we're here
+
+ VclPtr< CheckBox > pCheckBox = GetAs< CheckBox >();
+ if ( pCheckBox )
+ {
+ if ( maItemListeners.getLength() )
+ {
+ css::awt::ItemEvent aEvent;
+ aEvent.Source = getXWeak();
+ aEvent.Highlighted = 0;
+ aEvent.Selected = pCheckBox->GetState();
+ maItemListeners.itemStateChanged( aEvent );
+ }
+ if ( !IsSynthesizingVCLEvent() && maActionListeners.getLength() )
+ {
+ css::awt::ActionEvent aEvent;
+ aEvent.Source = getXWeak();
+ aEvent.ActionCommand = maActionCommand;
+ maActionListeners.actionPerformed( aEvent );
+ }
+ }
+ }
+ break;
+
+ default:
+ VCLXGraphicControl::ProcessWindowEvent( rVclWindowEvent );
+ break;
+ }
+}
+
+
+
+void VCLXRadioButton::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ BASEPROPERTY_DEFAULTCONTROL,
+ BASEPROPERTY_ENABLED,
+ BASEPROPERTY_ENABLEVISIBLE,
+ BASEPROPERTY_FONTDESCRIPTOR,
+ BASEPROPERTY_GRAPHIC,
+ BASEPROPERTY_HELPTEXT,
+ BASEPROPERTY_HELPURL,
+ BASEPROPERTY_IMAGEPOSITION,
+ BASEPROPERTY_IMAGEURL,
+ BASEPROPERTY_LABEL,
+ BASEPROPERTY_PRINTABLE,
+ BASEPROPERTY_STATE,
+ BASEPROPERTY_TABSTOP,
+ BASEPROPERTY_VISUALEFFECT,
+ BASEPROPERTY_MULTILINE,
+ BASEPROPERTY_BACKGROUNDCOLOR,
+ BASEPROPERTY_ALIGN,
+ BASEPROPERTY_VERTICALALIGN,
+ BASEPROPERTY_WRITING_MODE,
+ BASEPROPERTY_CONTEXT_WRITING_MODE,
+ BASEPROPERTY_REFERENCE_DEVICE,
+ BASEPROPERTY_GROUPNAME,
+ 0);
+ VCLXGraphicControl::ImplGetPropertyIds( rIds );
+}
+
+
+VCLXRadioButton::VCLXRadioButton() : maItemListeners( *this ), maActionListeners( *this )
+{
+}
+
+css::uno::Reference< css::accessibility::XAccessibleContext > VCLXRadioButton::CreateAccessibleContext()
+{
+ return getAccessibleFactory().createAccessibleContext( this );
+}
+
+void VCLXRadioButton::dispose()
+{
+ SolarMutexGuard aGuard;
+
+ css::lang::EventObject aObj;
+ aObj.Source = getXWeak();
+ maItemListeners.disposeAndClear( aObj );
+ VCLXGraphicControl::dispose();
+}
+
+void VCLXRadioButton::setProperty( const OUString& PropertyName, const css::uno::Any& Value)
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< RadioButton > pButton = GetAs< RadioButton >();
+ if ( !pButton )
+ return;
+
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_VISUALEFFECT:
+ ::toolkit::setVisualEffect( Value, pButton );
+ break;
+
+ case BASEPROPERTY_STATE:
+ {
+ sal_Int16 n = sal_Int16();
+ if ( Value >>= n )
+ {
+ bool b = n != 0;
+ if ( pButton->IsRadioCheckEnabled() )
+ pButton->Check( b );
+ else
+ pButton->SetState( b );
+ }
+ }
+ break;
+ case BASEPROPERTY_AUTOTOGGLE:
+ {
+ bool b = bool();
+ if ( Value >>= b )
+ pButton->EnableRadioCheck( b );
+ }
+ break;
+ default:
+ {
+ VCLXGraphicControl::setProperty( PropertyName, Value );
+ }
+ }
+}
+
+css::uno::Any VCLXRadioButton::getProperty( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Any aProp;
+ VclPtr< RadioButton > pButton = GetAs< RadioButton >();
+ if ( pButton )
+ {
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_VISUALEFFECT:
+ aProp = ::toolkit::getVisualEffect( pButton );
+ break;
+ case BASEPROPERTY_STATE:
+ aProp <<= static_cast<sal_Int16>( pButton->IsChecked() ? 1 : 0 );
+ break;
+ case BASEPROPERTY_AUTOTOGGLE:
+ aProp <<= pButton->IsRadioCheckEnabled();
+ break;
+ default:
+ {
+ aProp = VCLXGraphicControl::getProperty( PropertyName );
+ }
+ }
+ }
+ return aProp;
+}
+
+void VCLXRadioButton::addItemListener( const css::uno::Reference< css::awt::XItemListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maItemListeners.addInterface( l );
+}
+
+void VCLXRadioButton::removeItemListener( const css::uno::Reference< css::awt::XItemListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maItemListeners.removeInterface( l );
+}
+
+void VCLXRadioButton::addActionListener( const css::uno::Reference< css::awt::XActionListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maActionListeners.addInterface( l );
+}
+
+void VCLXRadioButton::removeActionListener( const css::uno::Reference< css::awt::XActionListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maActionListeners.removeInterface( l );
+}
+
+void VCLXRadioButton::setLabel( const OUString& rLabel )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ pWindow->SetText( rLabel );
+}
+
+void VCLXRadioButton::setActionCommand( const OUString& rCommand )
+{
+ SolarMutexGuard aGuard;
+ maActionCommand = rCommand;
+}
+
+void VCLXRadioButton::setState( sal_Bool b )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< RadioButton > pRadioButton = GetAs< RadioButton >();
+ if ( pRadioButton)
+ {
+ pRadioButton->Check( b );
+ // #102717# item listeners are called, but not C++ click listeners in StarOffice code => call click hdl
+ // But this is needed in old code because Accessibility API uses it.
+ // pRadioButton->GetClickHdl().Call( pRadioButton );
+
+ // #107218# Call same virtual methods and listeners like VCL would do after user interaction
+ SetSynthesizingVCLEvent( true );
+ pRadioButton->Click();
+ SetSynthesizingVCLEvent( false );
+ }
+}
+
+sal_Bool VCLXRadioButton::getState()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< RadioButton > pRadioButton = GetAs< RadioButton >();
+ return pRadioButton && pRadioButton->IsChecked();
+}
+
+css::awt::Size VCLXRadioButton::getMinimumSize( )
+{
+ SolarMutexGuard aGuard;
+
+ Size aSz;
+ VclPtr< RadioButton > pRadioButton = GetAs< RadioButton >();
+ if ( pRadioButton )
+ aSz = pRadioButton->CalcMinimumSize();
+ return AWTSize(aSz);
+}
+
+css::awt::Size VCLXRadioButton::getPreferredSize( )
+{
+ return getMinimumSize();
+}
+
+css::awt::Size VCLXRadioButton::calcAdjustedSize( const css::awt::Size& rNewSize )
+{
+ SolarMutexGuard aGuard;
+
+ Size aSz = VCLSize(rNewSize);
+ VclPtr< RadioButton > pRadioButton = GetAs< RadioButton >();
+ if ( pRadioButton )
+ {
+ Size aMinSz = pRadioButton->CalcMinimumSize(rNewSize.Width);
+ if ( ( aSz.Width() > aMinSz.Width() ) && ( aSz.Height() < aMinSz.Height() ) )
+ aSz.setHeight( aMinSz.Height() );
+ else
+ aSz = aMinSz;
+ }
+ return AWTSize(aSz);
+}
+
+void VCLXRadioButton::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ css::uno::Reference< css::awt::XWindow > xKeepAlive( this );
+ // since we call listeners below, there is a potential that we will be destroyed
+ // in during the listener call. To prevent the resulting crashes, we keep us
+ // alive as long as we're here
+
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::ButtonClick:
+ if ( !IsSynthesizingVCLEvent() && maActionListeners.getLength() )
+ {
+ css::awt::ActionEvent aEvent;
+ aEvent.Source = getXWeak();
+ aEvent.ActionCommand = maActionCommand;
+ maActionListeners.actionPerformed( aEvent );
+ }
+ ImplClickedOrToggled( false );
+ break;
+
+ case VclEventId::RadiobuttonToggle:
+ ImplClickedOrToggled( true );
+ break;
+
+ default:
+ VCLXGraphicControl::ProcessWindowEvent( rVclWindowEvent );
+ break;
+ }
+}
+
+void VCLXRadioButton::ImplClickedOrToggled( bool bToggled )
+{
+ // In the forms, RadioChecked is not enabled, call itemStateChanged only for click
+ // In the dialog editor, RadioChecked is enabled, call itemStateChanged only for bToggled
+ VclPtr< RadioButton > pRadioButton = GetAs< RadioButton >();
+ if ( pRadioButton && ( pRadioButton->IsRadioCheckEnabled() == bToggled ) && ( bToggled || pRadioButton->IsStateChanged() ) && maItemListeners.getLength() )
+ {
+ css::awt::ItemEvent aEvent;
+ aEvent.Source = getXWeak();
+ aEvent.Highlighted = 0;
+ aEvent.Selected = pRadioButton->IsChecked() ? 1 : 0;
+ maItemListeners.itemStateChanged( aEvent );
+ }
+}
+
+
+
+void VCLXSpinField::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ BASEPROPERTY_MOUSE_WHEEL_BEHAVIOUR,
+ 0 );
+ VCLXEdit::ImplGetPropertyIds( rIds );
+}
+
+VCLXSpinField::VCLXSpinField() : maSpinListeners( *this )
+{
+}
+
+void VCLXSpinField::addSpinListener( const css::uno::Reference< css::awt::XSpinListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maSpinListeners.addInterface( l );
+}
+
+void VCLXSpinField::removeSpinListener( const css::uno::Reference< css::awt::XSpinListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maSpinListeners.removeInterface( l );
+}
+
+void VCLXSpinField::up()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< SpinField > pSpinField = GetAs< SpinField >();
+ if ( pSpinField )
+ pSpinField->Up();
+}
+
+void VCLXSpinField::down()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< SpinField > pSpinField = GetAs< SpinField >();
+ if ( pSpinField )
+ pSpinField->Down();
+}
+
+void VCLXSpinField::first()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< SpinField > pSpinField = GetAs< SpinField >();
+ if ( pSpinField )
+ pSpinField->First();
+}
+
+void VCLXSpinField::last()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< SpinField > pSpinField = GetAs< SpinField >();
+ if ( pSpinField )
+ pSpinField->Last();
+}
+
+void VCLXSpinField::enableRepeat( sal_Bool bRepeat )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ WinBits nStyle = pWindow->GetStyle();
+ if ( bRepeat )
+ nStyle |= WB_REPEAT;
+ else
+ nStyle &= ~WB_REPEAT;
+ pWindow->SetStyle( nStyle );
+ }
+}
+
+void VCLXSpinField::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::SpinfieldUp:
+ case VclEventId::SpinfieldDown:
+ case VclEventId::SpinfieldFirst:
+ case VclEventId::SpinfieldLast:
+ {
+ css::uno::Reference< css::awt::XWindow > xKeepAlive( this );
+ // since we call listeners below, there is a potential that we will be destroyed
+ // in during the listener call. To prevent the resulting crashes, we keep us
+ // alive as long as we're here
+
+ if ( maSpinListeners.getLength() )
+ {
+ css::awt::SpinEvent aEvent;
+ aEvent.Source = getXWeak();
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::SpinfieldUp: maSpinListeners.up( aEvent );
+ break;
+ case VclEventId::SpinfieldDown: maSpinListeners.down( aEvent );
+ break;
+ case VclEventId::SpinfieldFirst: maSpinListeners.first( aEvent );
+ break;
+ case VclEventId::SpinfieldLast: maSpinListeners.last( aEvent );
+ break;
+ default: break;
+ }
+
+ }
+ }
+ break;
+
+ default:
+ VCLXEdit::ProcessWindowEvent( rVclWindowEvent );
+ break;
+ }
+}
+
+
+
+void VCLXListBox::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ BASEPROPERTY_BACKGROUNDCOLOR,
+ BASEPROPERTY_BORDER,
+ BASEPROPERTY_BORDERCOLOR,
+ BASEPROPERTY_DEFAULTCONTROL,
+ BASEPROPERTY_DROPDOWN,
+ BASEPROPERTY_ENABLED,
+ BASEPROPERTY_ENABLEVISIBLE,
+ BASEPROPERTY_FONTDESCRIPTOR,
+ BASEPROPERTY_HELPTEXT,
+ BASEPROPERTY_HELPURL,
+ BASEPROPERTY_LINECOUNT,
+ BASEPROPERTY_MULTISELECTION,
+ BASEPROPERTY_MULTISELECTION_SIMPLEMODE,
+ BASEPROPERTY_ITEM_SEPARATOR_POS,
+ BASEPROPERTY_PRINTABLE,
+ BASEPROPERTY_SELECTEDITEMS,
+ BASEPROPERTY_STRINGITEMLIST,
+ BASEPROPERTY_TYPEDITEMLIST,
+ BASEPROPERTY_TABSTOP,
+ BASEPROPERTY_READONLY,
+ BASEPROPERTY_ALIGN,
+ BASEPROPERTY_WRITING_MODE,
+ BASEPROPERTY_CONTEXT_WRITING_MODE,
+ BASEPROPERTY_REFERENCE_DEVICE,
+ BASEPROPERTY_MOUSE_WHEEL_BEHAVIOUR,
+ BASEPROPERTY_HIGHLIGHT_COLOR,
+ BASEPROPERTY_HIGHLIGHT_TEXT_COLOR,
+ 0);
+ VCLXWindow::ImplGetPropertyIds( rIds );
+}
+
+
+VCLXListBox::VCLXListBox()
+ : maActionListeners( *this ),
+ maItemListeners( *this )
+{
+}
+
+void VCLXListBox::dispose()
+{
+ SolarMutexGuard aGuard;
+
+ css::lang::EventObject aObj;
+ aObj.Source = getXWeak();
+ maItemListeners.disposeAndClear( aObj );
+ maActionListeners.disposeAndClear( aObj );
+ VCLXWindow::dispose();
+}
+
+void VCLXListBox::addItemListener( const css::uno::Reference< css::awt::XItemListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maItemListeners.addInterface( l );
+}
+
+void VCLXListBox::removeItemListener( const css::uno::Reference< css::awt::XItemListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maItemListeners.removeInterface( l );
+}
+
+void VCLXListBox::addActionListener( const css::uno::Reference< css::awt::XActionListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maActionListeners.addInterface( l );
+}
+
+void VCLXListBox::removeActionListener( const css::uno::Reference< css::awt::XActionListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maActionListeners.removeInterface( l );
+}
+
+void VCLXListBox::addItem( const OUString& aItem, sal_Int16 nPos )
+{
+ SolarMutexGuard aGuard;
+ VclPtr< ListBox > pBox = GetAs< ListBox >();
+ if ( pBox )
+ pBox->InsertEntry( aItem, nPos );
+}
+
+void VCLXListBox::addItems( const css::uno::Sequence< OUString>& aItems, sal_Int16 nPos )
+{
+ SolarMutexGuard aGuard;
+ VclPtr< ListBox > pBox = GetAs< ListBox >();
+ if ( !pBox )
+ return;
+
+ sal_uInt16 nP = nPos;
+ for ( auto const & item : aItems )
+ {
+ if ( nP == 0xFFFF )
+ {
+ OSL_FAIL( "VCLXListBox::addItems: too many entries!" );
+ // skip remaining entries, list cannot hold them, anyway
+ break;
+ }
+
+ pBox->InsertEntry( item, nP++ );
+ }
+}
+
+void VCLXListBox::removeItems( sal_Int16 nPos, sal_Int16 nCount )
+{
+ SolarMutexGuard aGuard;
+ VclPtr< ListBox > pBox = GetAs< ListBox >();
+ if ( pBox )
+ {
+ for ( sal_Int16 n = nCount; n; )
+ pBox->RemoveEntry( nPos + (--n) );
+ }
+}
+
+sal_Int16 VCLXListBox::getItemCount()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ListBox > pBox = GetAs< ListBox >();
+ return pBox ? pBox->GetEntryCount() : 0;
+}
+
+OUString VCLXListBox::getItem( sal_Int16 nPos )
+{
+ SolarMutexGuard aGuard;
+
+ OUString aItem;
+ VclPtr< ListBox > pBox = GetAs< ListBox >();
+ if ( pBox )
+ aItem = pBox->GetEntry( nPos );
+ return aItem;
+}
+
+css::uno::Sequence< OUString> VCLXListBox::getItems()
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Sequence< OUString> aSeq;
+ VclPtr< ListBox > pBox = GetAs< ListBox >();
+ if ( pBox )
+ {
+ auto n = pBox->GetEntryCount();
+ aSeq = css::uno::Sequence< OUString>( n );
+ while (n)
+ {
+ --n;
+ aSeq.getArray()[n] = pBox->GetEntry( n );
+ }
+ }
+ return aSeq;
+}
+
+sal_Int16 VCLXListBox::getSelectedItemPos()
+{
+ SolarMutexGuard aGuard;
+ VclPtr< ListBox > pBox = GetAs< ListBox >();
+ return pBox ? pBox->GetSelectedEntryPos() : 0;
+}
+
+css::uno::Sequence<sal_Int16> VCLXListBox::getSelectedItemsPos()
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Sequence<sal_Int16> aSeq;
+ VclPtr< ListBox > pBox = GetAs< ListBox >();
+ if ( pBox )
+ {
+ const sal_Int32 nSelEntries = pBox->GetSelectedEntryCount();
+ aSeq = css::uno::Sequence<sal_Int16>( nSelEntries );
+ for ( sal_Int32 n = 0; n < nSelEntries; ++n )
+ aSeq.getArray()[n] = pBox->GetSelectedEntryPos( n );
+ }
+ return aSeq;
+}
+
+OUString VCLXListBox::getSelectedItem()
+{
+ SolarMutexGuard aGuard;
+
+ OUString aItem;
+ VclPtr< ListBox > pBox = GetAs< ListBox >();
+ if ( pBox )
+ aItem = pBox->GetSelectedEntry();
+ return aItem;
+}
+
+css::uno::Sequence< OUString> VCLXListBox::getSelectedItems()
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Sequence< OUString> aSeq;
+ VclPtr< ListBox > pBox = GetAs< ListBox >();
+ if ( pBox )
+ {
+ const sal_Int32 nSelEntries = pBox->GetSelectedEntryCount();
+ aSeq = css::uno::Sequence< OUString>( nSelEntries );
+ for ( sal_Int32 n = 0; n < nSelEntries; ++n )
+ aSeq.getArray()[n] = pBox->GetSelectedEntry( n );
+ }
+ return aSeq;
+}
+
+void VCLXListBox::selectItemPos( sal_Int16 nPos, sal_Bool bSelect )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ListBox > pBox = GetAs< ListBox >();
+ if ( pBox && ( pBox->IsEntryPosSelected( nPos ) != bool(bSelect) ) )
+ {
+ pBox->SelectEntryPos( nPos, bSelect );
+
+ // VCL doesn't call select handler after API call.
+ // ImplCallItemListeners();
+
+ // #107218# Call same listeners like VCL would do after user interaction
+ SetSynthesizingVCLEvent( true );
+ pBox->Select();
+ SetSynthesizingVCLEvent( false );
+ }
+}
+
+void VCLXListBox::selectItemsPos( const css::uno::Sequence<sal_Int16>& aPositions, sal_Bool bSelect )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ListBox > pBox = GetAs< ListBox >();
+ if ( !pBox )
+ return;
+
+ std::vector<sal_Int32> aPositionVec;
+ aPositionVec.reserve(aPositions.getLength());
+
+ bool bChanged = false;
+ for ( auto n = aPositions.getLength(); n; )
+ {
+ const auto nPos = aPositions.getConstArray()[--n];
+ if ( pBox->IsEntryPosSelected( nPos ) != bool(bSelect) )
+ {
+ aPositionVec.push_back(nPos);
+ bChanged = true;
+ }
+ }
+
+ if ( !bChanged )
+ return;
+
+ bool bOrigUpdateMode = pBox->IsUpdateMode();
+ pBox->SetUpdateMode(false);
+
+ pBox->SelectEntriesPos(aPositionVec, bSelect);
+
+ pBox->SetUpdateMode(bOrigUpdateMode);
+
+ // VCL doesn't call select handler after API call.
+ // ImplCallItemListeners();
+
+ // #107218# Call same listeners like VCL would do after user interaction
+ SetSynthesizingVCLEvent( true );
+ pBox->Select();
+ SetSynthesizingVCLEvent( false );
+}
+
+void VCLXListBox::selectItem( const OUString& rItemText, sal_Bool bSelect )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ListBox > pBox = GetAs< ListBox >();
+ if ( pBox )
+ {
+ selectItemPos( pBox->GetEntryPos( rItemText ), bSelect );
+ }
+}
+
+void VCLXListBox::setDropDownLineCount( sal_Int16 nLines )
+{
+ SolarMutexGuard aGuard;
+ VclPtr< ListBox > pBox = GetAs< ListBox >();
+ if ( pBox )
+ pBox->SetDropDownLineCount( nLines );
+}
+
+sal_Int16 VCLXListBox::getDropDownLineCount()
+{
+ SolarMutexGuard aGuard;
+
+ sal_Int16 nLines = 0;
+ VclPtr< ListBox > pBox = GetAs< ListBox >();
+ if ( pBox )
+ nLines = pBox->GetDropDownLineCount();
+ return nLines;
+}
+
+sal_Bool VCLXListBox::isMutipleMode()
+{
+ SolarMutexGuard aGuard;
+ bool bMulti = false;
+ VclPtr< ListBox > pBox = GetAs< ListBox >();
+ if ( pBox )
+ bMulti = pBox->IsMultiSelectionEnabled();
+ return bMulti;
+}
+
+void VCLXListBox::setMultipleMode( sal_Bool bMulti )
+{
+ SolarMutexGuard aGuard;
+ VclPtr< ListBox > pBox = GetAs< ListBox >();
+ if ( pBox )
+ pBox->EnableMultiSelection( bMulti );
+}
+
+void VCLXListBox::makeVisible( sal_Int16 nEntry )
+{
+ SolarMutexGuard aGuard;
+ VclPtr< ListBox > pBox = GetAs< ListBox >();
+ if ( pBox )
+ pBox->SetTopEntry( nEntry );
+}
+
+void VCLXListBox::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ css::uno::Reference< css::awt::XWindow > xKeepAlive( this );
+ // since we call listeners below, there is a potential that we will be destroyed
+ // in during the listener call. To prevent the resulting crashes, we keep us
+ // alive as long as we're here
+
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::ListboxSelect:
+ {
+ VclPtr< ListBox > pListBox = GetAs< ListBox >();
+ if( pListBox )
+ {
+ bool bDropDown = ( pListBox->GetStyle() & WB_DROPDOWN ) != 0;
+ if ( bDropDown && !IsSynthesizingVCLEvent() && maActionListeners.getLength() )
+ {
+ // Call ActionListener on DropDown event
+ css::awt::ActionEvent aEvent;
+ aEvent.Source = getXWeak();
+ aEvent.ActionCommand = pListBox->GetSelectedEntry();
+ maActionListeners.actionPerformed( aEvent );
+ }
+
+ if ( maItemListeners.getLength() )
+ {
+ ImplCallItemListeners();
+ }
+ }
+ }
+ break;
+
+ case VclEventId::ListboxDoubleClick:
+ if ( GetWindow() && maActionListeners.getLength() )
+ {
+ css::awt::ActionEvent aEvent;
+ aEvent.Source = getXWeak();
+ aEvent.ActionCommand = GetAs<ListBox>()->GetSelectedEntry();
+ maActionListeners.actionPerformed( aEvent );
+ }
+ break;
+
+ default:
+ VCLXWindow::ProcessWindowEvent( rVclWindowEvent );
+ break;
+ }
+}
+
+css::uno::Reference< css::accessibility::XAccessibleContext > VCLXListBox::CreateAccessibleContext()
+{
+ SolarMutexGuard aGuard;
+
+ return getAccessibleFactory().createAccessibleContext( this );
+}
+
+void VCLXListBox::setProperty( const OUString& PropertyName, const css::uno::Any& Value)
+{
+ SolarMutexGuard aGuard;
+ VclPtr< ListBox > pListBox = GetAs< ListBox >();
+ if ( !pListBox )
+ return;
+
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_ITEM_SEPARATOR_POS:
+ {
+ sal_Int16 nSeparatorPos(0);
+ if ( Value >>= nSeparatorPos )
+ pListBox->SetSeparatorPos( nSeparatorPos );
+ }
+ break;
+ case BASEPROPERTY_READONLY:
+ {
+ bool b = false;
+ if ( Value >>= b )
+ pListBox->SetReadOnly( b);
+ }
+ break;
+ case BASEPROPERTY_MULTISELECTION:
+ {
+ bool b = false;
+ if ( Value >>= b )
+ pListBox->EnableMultiSelection( b );
+ }
+ break;
+ case BASEPROPERTY_MULTISELECTION_SIMPLEMODE:
+ ::toolkit::adjustBooleanWindowStyle( Value, pListBox, WB_SIMPLEMODE, false );
+ break;
+ case BASEPROPERTY_LINECOUNT:
+ {
+ sal_Int16 n = 0;
+ if ( Value >>= n )
+ pListBox->SetDropDownLineCount( n );
+ }
+ break;
+ case BASEPROPERTY_STRINGITEMLIST:
+ {
+ css::uno::Sequence< OUString> aItems;
+ if ( Value >>= aItems )
+ {
+ pListBox->Clear();
+ addItems( aItems, 0 );
+ }
+ }
+ break;
+ case BASEPROPERTY_SELECTEDITEMS:
+ {
+ css::uno::Sequence<sal_Int16> aItems;
+ if ( Value >>= aItems )
+ {
+ for ( auto n = pListBox->GetEntryCount(); n; )
+ pListBox->SelectEntryPos( --n, false );
+
+ if ( aItems.hasElements() )
+ selectItemsPos( aItems, true );
+ else
+ pListBox->SetNoSelection();
+
+ if ( !pListBox->GetSelectedEntryCount() )
+ pListBox->SetTopEntry( 0 );
+ }
+ }
+ break;
+ case BASEPROPERTY_HIGHLIGHT_COLOR:
+ {
+ Color nColor = 0;
+ bool bVoid = Value.getValueType().getTypeClass() == css::uno::TypeClass_VOID;
+ if (bVoid)
+ {
+ nColor = Application::GetSettings().GetStyleSettings().GetHighlightColor();
+ }
+ else
+ {
+ if (!(Value >>= nColor))
+ break;
+ }
+ pListBox->SetHighlightColor(nColor);
+ }
+ break;
+ case BASEPROPERTY_HIGHLIGHT_TEXT_COLOR:
+ {
+ Color nColor = 0;
+ bool bVoid = Value.getValueType().getTypeClass() == css::uno::TypeClass_VOID;
+ if (bVoid)
+ {
+ nColor = Application::GetSettings().GetStyleSettings().GetHighlightTextColor();
+ }
+ else
+ {
+ if (!(Value >>= nColor))
+ break;
+ }
+ pListBox->SetHighlightTextColor(nColor);
+ }
+ break;
+ default:
+ {
+ VCLXWindow::setProperty( PropertyName, Value );
+ }
+ }
+}
+
+css::uno::Any VCLXListBox::getProperty( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+ css::uno::Any aProp;
+ VclPtr< ListBox > pListBox = GetAs< ListBox >();
+ if ( pListBox )
+ {
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_ITEM_SEPARATOR_POS:
+ aProp <<= sal_Int16( pListBox->GetSeparatorPos() );
+ break;
+ case BASEPROPERTY_READONLY:
+ {
+ aProp <<= pListBox->IsReadOnly();
+ }
+ break;
+ case BASEPROPERTY_MULTISELECTION:
+ {
+ aProp <<= pListBox->IsMultiSelectionEnabled();
+ }
+ break;
+ case BASEPROPERTY_MULTISELECTION_SIMPLEMODE:
+ {
+ aProp <<= ( ( pListBox->GetStyle() & WB_SIMPLEMODE ) == 0 );
+ }
+ break;
+ case BASEPROPERTY_LINECOUNT:
+ {
+ aProp <<= static_cast<sal_Int16>(pListBox->GetDropDownLineCount());
+ }
+ break;
+ case BASEPROPERTY_STRINGITEMLIST:
+ {
+ const sal_Int32 nItems = pListBox->GetEntryCount();
+ css::uno::Sequence< OUString> aSeq( nItems );
+ OUString* pStrings = aSeq.getArray();
+ for ( sal_Int32 n = 0; n < nItems; ++n )
+ pStrings[n] = pListBox->GetEntry( n );
+ aProp <<= aSeq;
+
+ }
+ break;
+ default:
+ {
+ aProp = VCLXWindow::getProperty( PropertyName );
+ }
+ }
+ }
+ return aProp;
+}
+
+css::awt::Size VCLXListBox::getMinimumSize( )
+{
+ SolarMutexGuard aGuard;
+ Size aSz;
+ VclPtr< ListBox > pListBox = GetAs< ListBox >();
+ if ( pListBox )
+ aSz = pListBox->CalcMinimumSize();
+ return AWTSize(aSz);
+}
+
+css::awt::Size VCLXListBox::getPreferredSize( )
+{
+ SolarMutexGuard aGuard;
+ Size aSz;
+ VclPtr< ListBox > pListBox = GetAs< ListBox >();
+ if ( pListBox )
+ {
+ aSz = pListBox->CalcMinimumSize();
+ if ( pListBox->GetStyle() & WB_DROPDOWN )
+ aSz.AdjustHeight(4 );
+ }
+ return AWTSize(aSz);
+}
+
+css::awt::Size VCLXListBox::calcAdjustedSize( const css::awt::Size& rNewSize )
+{
+ SolarMutexGuard aGuard;
+ Size aSz = VCLSize(rNewSize);
+ VclPtr< ListBox > pListBox = GetAs< ListBox >();
+ if ( pListBox )
+ aSz = pListBox->CalcAdjustedSize( aSz );
+ return AWTSize(aSz);
+}
+
+css::awt::Size VCLXListBox::getMinimumSize( sal_Int16 nCols, sal_Int16 nLines )
+{
+ SolarMutexGuard aGuard;
+ Size aSz;
+ VclPtr< ListBox > pListBox = GetAs< ListBox >();
+ if ( pListBox )
+ aSz = pListBox->CalcBlockSize( nCols, nLines );
+ return AWTSize(aSz);
+}
+
+void VCLXListBox::getColumnsAndLines( sal_Int16& nCols, sal_Int16& nLines )
+{
+ SolarMutexGuard aGuard;
+ nCols = nLines = 0;
+ VclPtr< ListBox > pListBox = GetAs< ListBox >();
+ if ( pListBox )
+ {
+ sal_uInt16 nC, nL;
+ pListBox->GetMaxVisColumnsAndLines( nC, nL );
+ nCols = nC;
+ nLines = nL;
+ }
+}
+
+void VCLXListBox::ImplCallItemListeners()
+{
+ VclPtr< ListBox > pListBox = GetAs< ListBox >();
+ if ( pListBox && maItemListeners.getLength() )
+ {
+ css::awt::ItemEvent aEvent;
+ aEvent.Source = getXWeak();
+ aEvent.Highlighted = 0;
+
+ // Set to 0xFFFF on multiple selection, selected entry ID otherwise
+ aEvent.Selected = (pListBox->GetSelectedEntryCount() == 1 ) ? pListBox->GetSelectedEntryPos() : 0xFFFF;
+
+ maItemListeners.itemStateChanged( aEvent );
+ }
+}
+namespace
+{
+ Image lcl_getImageFromURL( const OUString& i_rImageURL )
+ {
+ if ( i_rImageURL.isEmpty() )
+ return Image();
+
+ try
+ {
+ Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
+ Reference< XGraphicProvider > xProvider(graphic::GraphicProvider::create(xContext));
+ ::comphelper::NamedValueCollection aMediaProperties;
+ aMediaProperties.put( "URL", i_rImageURL );
+ Reference< XGraphic > xGraphic = xProvider->queryGraphic( aMediaProperties.getPropertyValues() );
+ return Image( xGraphic );
+ }
+ catch( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit");
+ }
+ return Image();
+ }
+}
+void SAL_CALL VCLXListBox::listItemInserted( const ItemListEvent& i_rEvent )
+{
+ SolarMutexGuard aGuard;
+ VclPtr< ListBox > pListBox = GetAs< ListBox >();
+
+ ENSURE_OR_RETURN_VOID( pListBox, "VCLXListBox::listItemInserted: no ListBox?!" );
+ ENSURE_OR_RETURN_VOID( ( i_rEvent.ItemPosition >= 0 ) && ( i_rEvent.ItemPosition <= pListBox->GetEntryCount() ),
+ "VCLXListBox::listItemInserted: illegal (inconsistent) item position!" );
+ pListBox->InsertEntry(
+ i_rEvent.ItemText.IsPresent ? i_rEvent.ItemText.Value : OUString(),
+ i_rEvent.ItemImageURL.IsPresent ? TkResMgr::getImageFromURL( i_rEvent.ItemImageURL.Value ) : Image(),
+ i_rEvent.ItemPosition );
+}
+
+void SAL_CALL VCLXListBox::listItemRemoved( const ItemListEvent& i_rEvent )
+{
+ SolarMutexGuard aGuard;
+ VclPtr< ListBox > pListBox = GetAs< ListBox >();
+
+ ENSURE_OR_RETURN_VOID( pListBox, "VCLXListBox::listItemRemoved: no ListBox?!" );
+ ENSURE_OR_RETURN_VOID( ( i_rEvent.ItemPosition >= 0 ) && ( i_rEvent.ItemPosition < pListBox->GetEntryCount() ),
+ "VCLXListBox::listItemRemoved: illegal (inconsistent) item position!" );
+
+ pListBox->RemoveEntry( i_rEvent.ItemPosition );
+}
+
+void SAL_CALL VCLXListBox::listItemModified( const ItemListEvent& i_rEvent )
+{
+ SolarMutexGuard aGuard;
+ VclPtr< ListBox > pListBox = GetAs< ListBox >();
+
+ ENSURE_OR_RETURN_VOID( pListBox, "VCLXListBox::listItemModified: no ListBox?!" );
+ ENSURE_OR_RETURN_VOID( ( i_rEvent.ItemPosition >= 0 ) && ( i_rEvent.ItemPosition < pListBox->GetEntryCount() ),
+ "VCLXListBox::listItemModified: illegal (inconsistent) item position!" );
+
+ // VCL's ListBox does not support changing an entry's text or image, so remove and re-insert
+
+ const OUString sNewText = i_rEvent.ItemText.IsPresent ? i_rEvent.ItemText.Value : pListBox->GetEntry( i_rEvent.ItemPosition );
+ const Image aNewImage( i_rEvent.ItemImageURL.IsPresent ? TkResMgr::getImageFromURL( i_rEvent.ItemImageURL.Value ) : pListBox->GetEntryImage( i_rEvent.ItemPosition ) );
+
+ pListBox->RemoveEntry( i_rEvent.ItemPosition );
+ pListBox->InsertEntry( sNewText, aNewImage, i_rEvent.ItemPosition );
+}
+
+void SAL_CALL VCLXListBox::allItemsRemoved( const EventObject& )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ListBox > pListBox = GetAs< ListBox >();
+ ENSURE_OR_RETURN_VOID( pListBox, "VCLXListBox::listItemModified: no ListBox?!" );
+
+ pListBox->Clear();
+}
+
+void SAL_CALL VCLXListBox::itemListChanged( const EventObject& i_rEvent )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ListBox > pListBox = GetAs< ListBox >();
+ ENSURE_OR_RETURN_VOID( pListBox, "VCLXListBox::listItemModified: no ListBox?!" );
+
+ pListBox->Clear();
+
+ uno::Reference< beans::XPropertySet > xPropSet( i_rEvent.Source, uno::UNO_QUERY_THROW );
+ uno::Reference< beans::XPropertySetInfo > xPSI( xPropSet->getPropertySetInfo(), uno::UNO_SET_THROW );
+ uno::Reference< resource::XStringResourceResolver > xStringResourceResolver;
+ if ( xPSI->hasPropertyByName("ResourceResolver") )
+ {
+ xStringResourceResolver.set(
+ xPropSet->getPropertyValue("ResourceResolver"),
+ uno::UNO_QUERY
+ );
+ }
+
+
+ Reference< XItemList > xItemList( i_rEvent.Source, uno::UNO_QUERY_THROW );
+ const uno::Sequence< beans::Pair< OUString, OUString > > aItems = xItemList->getAllItems();
+ for ( const auto& rItem : aItems )
+ {
+ OUString aLocalizationKey( rItem.First );
+ if ( xStringResourceResolver.is() && aLocalizationKey.startsWith("&") )
+ {
+ aLocalizationKey = xStringResourceResolver->resolveString(aLocalizationKey.copy( 1 ));
+ }
+ pListBox->InsertEntry( aLocalizationKey, lcl_getImageFromURL( rItem.Second ) );
+ }
+}
+
+void SAL_CALL VCLXListBox::disposing( const EventObject& i_rEvent )
+{
+ // just disambiguate
+ VCLXWindow::disposing( i_rEvent );
+}
+
+
+
+
+void VCLXMessageBox::GetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ VCLXTopWindow::ImplGetPropertyIds( rIds );
+}
+
+VCLXMessageBox::VCLXMessageBox()
+{
+}
+
+VCLXMessageBox::~VCLXMessageBox()
+{
+}
+
+void VCLXMessageBox::setCaptionText( const OUString& rText )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ pWindow->SetText( rText );
+}
+
+OUString VCLXMessageBox::getCaptionText()
+{
+ SolarMutexGuard aGuard;
+
+ OUString aText;
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ aText = pWindow->GetText();
+ return aText;
+}
+
+void VCLXMessageBox::setMessageText( const OUString& rText )
+{
+ SolarMutexGuard aGuard;
+ VclPtr< MessBox > pBox = GetAs< MessBox >();
+ if ( pBox )
+ pBox->SetMessText( rText );
+}
+
+OUString VCLXMessageBox::getMessageText()
+{
+ SolarMutexGuard aGuard;
+ OUString aText;
+ VclPtr< MessBox > pBox = GetAs< MessBox >();
+ if ( pBox )
+ aText = pBox->GetMessText();
+ return aText;
+}
+
+sal_Int16 VCLXMessageBox::execute()
+{
+ SolarMutexGuard aGuard;
+ VclPtr< MessBox > pBox = GetAs< MessBox >();
+ return pBox ? pBox->Execute() : 0;
+}
+
+css::awt::Size SAL_CALL VCLXMessageBox::getMinimumSize()
+{
+ return css::awt::Size( 250, 100 );
+}
+
+
+
+void VCLXDialog::GetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ VCLXTopWindow::ImplGetPropertyIds( rIds );
+}
+
+VCLXDialog::VCLXDialog()
+{
+ SAL_INFO("toolkit", "XDialog created");
+}
+
+VCLXDialog::~VCLXDialog()
+{
+ SAL_INFO("toolkit", __FUNCTION__);
+}
+
+void SAL_CALL VCLXDialog::endDialog( ::sal_Int32 i_result )
+{
+ SolarMutexGuard aGuard;
+ VclPtr<Dialog> pDialog = GetAsDynamic< Dialog >();
+ if ( pDialog )
+ pDialog->EndDialog( i_result );
+}
+
+void SAL_CALL VCLXDialog::setHelpId( const OUString& rId )
+{
+ SolarMutexGuard aGuard;
+ VclPtr< vcl::Window > pWindow = GetWindow();
+ if ( pWindow )
+ pWindow->SetHelpId( rId );
+}
+
+void VCLXDialog::setTitle( const OUString& Title )
+{
+ SolarMutexGuard aGuard;
+ VclPtr< vcl::Window > pWindow = GetWindow();
+ if ( pWindow )
+ pWindow->SetText( Title );
+}
+
+OUString VCLXDialog::getTitle()
+{
+ SolarMutexGuard aGuard;
+
+ OUString aTitle;
+ VclPtr< vcl::Window > pWindow = GetWindow();
+ if ( pWindow )
+ aTitle = pWindow->GetText();
+ return aTitle;
+}
+
+sal_Int16 VCLXDialog::execute()
+{
+ SolarMutexGuard aGuard;
+
+ sal_Int16 nRet = 0;
+ if ( GetWindow() )
+ {
+ VclPtr< Dialog > pDlg = GetAs< Dialog >();
+ vcl::Window* pParent = pDlg->GetWindow( GetWindowType::ParentOverlap );
+ vcl::Window* pOldParent = nullptr;
+ vcl::Window* pSetParent = nullptr;
+ if ( pParent && !pParent->IsReallyVisible() )
+ {
+ pOldParent = pDlg->GetParent();
+ vcl::Window* pFrame = pDlg->GetWindow( GetWindowType::Frame );
+ if( pFrame != pDlg )
+ {
+ pDlg->SetParent( pFrame );
+ pSetParent = pFrame;
+ }
+ }
+
+ nRet = pDlg->Execute();
+
+ // set the parent back only in case no new parent was set from outside
+ // in other words, revert only own changes
+ if ( pOldParent && pDlg->GetParent() == pSetParent )
+ pDlg->SetParent( pOldParent );
+ }
+ return nRet;
+}
+
+void VCLXDialog::endExecute()
+{
+ endDialog(0);
+}
+
+void SAL_CALL VCLXDialog::draw( sal_Int32 nX, sal_Int32 nY )
+{
+ SolarMutexGuard aGuard;
+ VclPtr< vcl::Window > pWindow = GetWindow();
+ if ( pWindow )
+ {
+ OutputDevice* pDev = VCLUnoHelper::GetOutputDevice( getGraphics() );
+ if ( !pDev )
+ pDev = pWindow->GetParent()->GetOutDev();
+
+ Point aPos = pDev->PixelToLogic( Point( nX, nY ) );
+ pWindow->Draw( pDev, aPos, SystemTextColorFlags::NoControls );
+ }
+}
+
+css::awt::DeviceInfo VCLXDialog::getInfo()
+{
+ css::awt::DeviceInfo aInfo = VCLXDevice::getInfo();
+
+ SolarMutexGuard aGuard;
+ VclPtr< Dialog > pDlg = GetAs< Dialog >();
+ if ( pDlg )
+ pDlg->GetDrawWindowBorder( aInfo.LeftInset, aInfo.TopInset, aInfo.RightInset, aInfo.BottomInset );
+
+ return aInfo;
+}
+
+void SAL_CALL VCLXDialog::setProperty(
+ const OUString& PropertyName,
+ const css::uno::Any& Value )
+{
+ SolarMutexGuard aGuard;
+ VclPtr< Dialog > pDialog = GetAs< Dialog >();
+ if ( !pDialog )
+ return;
+
+ bool bVoid = Value.getValueType().getTypeClass() == css::uno::TypeClass_VOID;
+
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_GRAPHIC:
+ {
+ Reference< XGraphic > xGraphic;
+ if (( Value >>= xGraphic ) && xGraphic.is() )
+ {
+ Graphic aImage(xGraphic);
+
+ Wallpaper aWallpaper(aImage.GetBitmapEx());
+ aWallpaper.SetStyle( WallpaperStyle::Scale );
+ pDialog->SetBackground( aWallpaper );
+ }
+ else if ( bVoid || !xGraphic.is() )
+ {
+ Color aColor = pDialog->GetControlBackground();
+ if ( aColor == COL_AUTO )
+ aColor = pDialog->GetSettings().GetStyleSettings().GetDialogColor();
+
+ Wallpaper aWallpaper( aColor );
+ pDialog->SetBackground( aWallpaper );
+ }
+ }
+ break;
+
+ default:
+ {
+ VCLXContainer::setProperty( PropertyName, Value );
+ }
+ }
+}
+
+
+
+VCLXMultiPage::VCLXMultiPage() : maTabListeners( *this ), mTabId( 1 )
+{
+ SAL_INFO("toolkit", "VCLXMultiPage::VCLXMultiPage()" );
+}
+
+void VCLXMultiPage::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ BASEPROPERTY_BACKGROUNDCOLOR,
+ BASEPROPERTY_DEFAULTCONTROL,
+ BASEPROPERTY_ENABLED,
+ BASEPROPERTY_MULTIPAGEVALUE,
+ BASEPROPERTY_ENABLEVISIBLE,
+ BASEPROPERTY_FONTDESCRIPTOR,
+ BASEPROPERTY_GRAPHIC,
+ BASEPROPERTY_HELPTEXT,
+ BASEPROPERTY_HELPURL,
+ BASEPROPERTY_IMAGEALIGN,
+ BASEPROPERTY_IMAGEPOSITION,
+ BASEPROPERTY_IMAGEURL,
+ BASEPROPERTY_PRINTABLE,
+ BASEPROPERTY_TABSTOP,
+ BASEPROPERTY_FOCUSONCLICK,
+ 0);
+ VCLXContainer::ImplGetPropertyIds( rIds );
+}
+
+VCLXMultiPage::~VCLXMultiPage()
+{
+}
+void SAL_CALL VCLXMultiPage::dispose()
+{
+ SolarMutexGuard aGuard;
+
+ css::lang::EventObject aObj;
+ aObj.Source = getXWeak();
+ maTabListeners.disposeAndClear( aObj );
+ VCLXContainer::dispose();
+}
+// css::awt::XView
+void SAL_CALL VCLXMultiPage::draw( sal_Int32 nX, sal_Int32 nY )
+{
+ SolarMutexGuard aGuard;
+ VclPtr< vcl::Window > pWindow = GetWindow();
+
+ if ( pWindow )
+ {
+ OutputDevice* pDev = VCLUnoHelper::GetOutputDevice( getGraphics() );
+ if ( !pDev )
+ pDev = pWindow->GetParent()->GetOutDev();
+
+ Point aPos = pDev->PixelToLogic( Point( nX, nY ) );
+ pWindow->Draw( pDev, aPos, SystemTextColorFlags::NoControls );
+ }
+}
+
+uno::Any SAL_CALL VCLXMultiPage::getProperty( const OUString& PropertyName )
+{
+ SAL_INFO("toolkit", " **** VCLXMultiPage::getProperty " << PropertyName );
+ SolarMutexGuard aGuard;
+ css::uno::Any aProp;
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+
+ case BASEPROPERTY_MULTIPAGEVALUE:
+ {
+ aProp <<= getActiveTabID();
+ }
+ break;
+ default:
+ aProp = VCLXContainer::getProperty( PropertyName );
+ }
+ return aProp;
+}
+
+void SAL_CALL VCLXMultiPage::setProperty(
+ const OUString& PropertyName,
+ const css::uno::Any& Value )
+{
+ SAL_INFO("toolkit", " **** VCLXMultiPage::setProperty " << PropertyName );
+ SolarMutexGuard aGuard;
+
+ VclPtr< TabControl > pTabControl = GetAs< TabControl >();
+ if ( !pTabControl )
+ return;
+
+ bool bVoid = Value.getValueType().getTypeClass() == css::uno::TypeClass_VOID;
+
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_MULTIPAGEVALUE:
+ {
+ SAL_INFO("toolkit", "***MULTIPAGE VALUE");
+ sal_Int32 nId(0);
+ Value >>= nId;
+ // when the multipage is created we attempt to set the activepage
+ // but no pages created
+ if ( nId && nId <= getWindows().getLength() )
+ activateTab( nId );
+ break;
+ }
+ case BASEPROPERTY_GRAPHIC:
+ {
+ Reference< XGraphic > xGraphic;
+ if (( Value >>= xGraphic ) && xGraphic.is() )
+ {
+ Graphic aImage(xGraphic);
+
+ Wallpaper aWallpaper(aImage.GetBitmapEx());
+ aWallpaper.SetStyle( WallpaperStyle::Scale );
+ pTabControl->SetBackground( aWallpaper );
+ }
+ else if ( bVoid || !xGraphic.is() )
+ {
+ Color aColor = pTabControl->GetControlBackground();
+ if ( aColor == COL_AUTO )
+ aColor = pTabControl->GetSettings().GetStyleSettings().GetDialogColor();
+
+ Wallpaper aWallpaper( aColor );
+ pTabControl->SetBackground( aWallpaper );
+ }
+ }
+ break;
+
+ default:
+ {
+ VCLXContainer::setProperty( PropertyName, Value );
+ }
+ }
+}
+
+TabControl *VCLXMultiPage::getTabControl() const
+{
+ VclPtr<TabControl> pTabControl = GetAsDynamic< TabControl >();
+ if ( pTabControl )
+ return pTabControl;
+ throw uno::RuntimeException();
+}
+sal_Int32 SAL_CALL VCLXMultiPage::insertTab()
+{
+ TabControl *pTabControl = getTabControl();
+ VclPtrInstance<TabPage> pTab( pTabControl );
+ return static_cast< sal_Int32 >( insertTab( pTab, OUString() ) );
+}
+
+sal_uInt16 VCLXMultiPage::insertTab( TabPage* pPage, OUString const & sTitle )
+{
+ TabControl *pTabControl = getTabControl();
+ sal_uInt16 id = sal::static_int_cast< sal_uInt16 >( mTabId++ );
+ pTabControl->InsertPage( id, sTitle );
+ pTabControl->SetTabPage( id, pPage );
+ return id;
+}
+
+void SAL_CALL VCLXMultiPage::removeTab( sal_Int32 ID )
+{
+ TabControl *pTabControl = getTabControl();
+ if ( pTabControl->GetTabPage( sal::static_int_cast< sal_uInt16 >( ID ) ) == nullptr )
+ throw lang::IndexOutOfBoundsException();
+ pTabControl->RemovePage( sal::static_int_cast< sal_uInt16 >( ID ) );
+}
+
+void SAL_CALL VCLXMultiPage::activateTab( sal_Int32 ID )
+{
+ TabControl *pTabControl = getTabControl();
+ SAL_INFO(
+ "toolkit",
+ "Attempting to activate tab " << ID << ", active tab is "
+ << getActiveTabID() << ", numtabs is " << getWindows().getLength());
+ if ( pTabControl->GetTabPage( sal::static_int_cast< sal_uInt16 >( ID ) ) == nullptr )
+ throw lang::IndexOutOfBoundsException();
+ pTabControl->SelectTabPage( sal::static_int_cast< sal_uInt16 >( ID ) );
+}
+
+sal_Int32 SAL_CALL VCLXMultiPage::getActiveTabID()
+{
+ return getTabControl()->GetCurPageId( );
+}
+
+void SAL_CALL VCLXMultiPage::addTabListener( const uno::Reference< awt::XTabListener >& xListener )
+{
+ SolarMutexGuard aGuard;
+ maTabListeners.addInterface( xListener );
+}
+
+void SAL_CALL VCLXMultiPage::removeTabListener( const uno::Reference< awt::XTabListener >& xListener )
+{
+ SolarMutexGuard aGuard;
+ maTabListeners.addInterface( xListener );
+}
+
+void SAL_CALL VCLXMultiPage::setTabProps( sal_Int32 ID, const uno::Sequence< beans::NamedValue >& Properties )
+{
+ SolarMutexGuard aGuard;
+ TabControl *pTabControl = getTabControl();
+ if ( pTabControl->GetTabPage( sal::static_int_cast< sal_uInt16 >( ID ) ) == nullptr )
+ throw lang::IndexOutOfBoundsException();
+
+ for (const auto& rProp : Properties)
+ {
+ const OUString &name = rProp.Name;
+ const uno::Any &value = rProp.Value;
+
+ if (name == "Title")
+ {
+ OUString title = value.get<OUString>();
+ pTabControl->SetPageText( sal::static_int_cast< sal_uInt16 >( ID ), title );
+ }
+ }
+}
+
+uno::Sequence< beans::NamedValue > SAL_CALL VCLXMultiPage::getTabProps( sal_Int32 ID )
+{
+ SolarMutexGuard aGuard;
+ TabControl *pTabControl = getTabControl();
+ if ( pTabControl->GetTabPage( sal::static_int_cast< sal_uInt16 >( ID ) ) == nullptr )
+ throw lang::IndexOutOfBoundsException();
+
+ uno::Sequence< beans::NamedValue > props
+ {
+ { "Title", css::uno::Any(pTabControl->GetPageText( sal::static_int_cast< sal_uInt16 >( ID ) )) },
+ { "Position", css::uno::Any(pTabControl->GetPagePos( sal::static_int_cast< sal_uInt16 >( ID ) )) }
+ };
+ return props;
+}
+void VCLXMultiPage::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ css::uno::Reference< css::awt::XWindow > xKeepAlive( this );
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::TabpageDeactivate:
+ {
+ sal_uLong nPageID = reinterpret_cast<sal_uLong>( rVclWindowEvent.GetData() );
+ maTabListeners.deactivated( nPageID );
+ break;
+
+ }
+ case VclEventId::TabpageActivate:
+ {
+ sal_uLong nPageID = reinterpret_cast<sal_uLong>( rVclWindowEvent.GetData() );
+ maTabListeners.activated( nPageID );
+ break;
+ }
+ default:
+ VCLXContainer::ProcessWindowEvent( rVclWindowEvent );
+ break;
+ }
+}
+
+
+
+VCLXTabPage::VCLXTabPage()
+{
+}
+
+void VCLXTabPage::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ BASEPROPERTY_BACKGROUNDCOLOR,
+ BASEPROPERTY_DEFAULTCONTROL,
+ BASEPROPERTY_ENABLED,
+ BASEPROPERTY_ENABLEVISIBLE,
+ BASEPROPERTY_FONTDESCRIPTOR,
+ BASEPROPERTY_GRAPHIC,
+ BASEPROPERTY_HELPTEXT,
+ BASEPROPERTY_HELPURL,
+ BASEPROPERTY_IMAGEALIGN,
+ BASEPROPERTY_IMAGEPOSITION,
+ BASEPROPERTY_IMAGEURL,
+ BASEPROPERTY_PRINTABLE,
+ BASEPROPERTY_TABSTOP,
+ BASEPROPERTY_FOCUSONCLICK,
+ 0);
+ VCLXContainer::ImplGetPropertyIds( rIds );
+}
+
+VCLXTabPage::~VCLXTabPage()
+{
+}
+
+// css::awt::XView
+void SAL_CALL VCLXTabPage::draw( sal_Int32 nX, sal_Int32 nY )
+{
+ SolarMutexGuard aGuard;
+ VclPtr< vcl::Window > pWindow = GetWindow();
+
+ if ( pWindow )
+ {
+ OutputDevice* pDev = VCLUnoHelper::GetOutputDevice( getGraphics() );
+ if ( !pDev )
+ pDev = pWindow->GetParent()->GetOutDev();
+
+ Point aPos = pDev->PixelToLogic( Point( nX, nY ) );
+ pWindow->Draw( pDev, aPos, SystemTextColorFlags::NoControls );
+ }
+}
+
+void SAL_CALL VCLXTabPage::setProperty(
+ const OUString& PropertyName,
+ const css::uno::Any& Value )
+{
+ SolarMutexGuard aGuard;
+ VclPtr< TabPage > pTabPage = GetAs< TabPage >();
+ if ( !pTabPage )
+ return;
+
+ bool bVoid = Value.getValueType().getTypeClass() == css::uno::TypeClass_VOID;
+
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_GRAPHIC:
+ {
+ Reference< XGraphic > xGraphic;
+ if (( Value >>= xGraphic ) && xGraphic.is() )
+ {
+ Graphic aImage(xGraphic);
+
+ Wallpaper aWallpaper(aImage.GetBitmapEx());
+ aWallpaper.SetStyle( WallpaperStyle::Scale );
+ pTabPage->SetBackground( aWallpaper );
+ }
+ else if ( bVoid || !xGraphic.is() )
+ {
+ Color aColor = pTabPage->GetControlBackground();
+ if ( aColor == COL_AUTO )
+ aColor = pTabPage->GetSettings().GetStyleSettings().GetDialogColor();
+
+ Wallpaper aWallpaper( aColor );
+ pTabPage->SetBackground( aWallpaper );
+ }
+ }
+ break;
+ case BASEPROPERTY_TITLE:
+ {
+ OUString sTitle;
+ if ( Value >>= sTitle )
+ {
+ pTabPage->SetText(sTitle);
+ }
+ }
+ break;
+
+ default:
+ {
+ VCLXContainer::setProperty( PropertyName, Value );
+ }
+ }
+}
+
+TabPage *VCLXTabPage::getTabPage() const
+{
+ VclPtr< TabPage > pTabPage = GetAsDynamic< TabPage >();
+ if ( pTabPage )
+ return pTabPage;
+ throw uno::RuntimeException();
+}
+
+
+
+
+VCLXFixedHyperlink::VCLXFixedHyperlink() :
+
+ maActionListeners( *this )
+
+{
+}
+
+VCLXFixedHyperlink::~VCLXFixedHyperlink()
+{
+}
+
+void VCLXFixedHyperlink::dispose()
+{
+ SolarMutexGuard aGuard;
+
+ css::lang::EventObject aObj;
+ aObj.Source = getXWeak();
+ maActionListeners.disposeAndClear( aObj );
+ VCLXWindow::dispose();
+}
+
+void VCLXFixedHyperlink::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::ButtonClick:
+ {
+ if ( maActionListeners.getLength() )
+ {
+ css::awt::ActionEvent aEvent;
+ aEvent.Source = getXWeak();
+ maActionListeners.actionPerformed( aEvent );
+ }
+ [[fallthrough]];
+ }
+ default:
+ VCLXWindow::ProcessWindowEvent( rVclWindowEvent );
+ break;
+ }
+}
+
+css::uno::Reference< css::accessibility::XAccessibleContext > VCLXFixedHyperlink::CreateAccessibleContext()
+{
+ return getAccessibleFactory().createAccessibleContext( this );
+}
+
+void VCLXFixedHyperlink::setText( const OUString& Text )
+{
+ SolarMutexGuard aGuard;
+ VclPtr< FixedHyperlink > pBase = GetAs< FixedHyperlink >();
+ if (pBase)
+ pBase->SetText(Text);
+}
+
+OUString VCLXFixedHyperlink::getText()
+{
+ SolarMutexGuard aGuard;
+
+ OUString aText;
+ VclPtr< vcl::Window > pWindow = GetWindow();
+ if ( pWindow )
+ aText = pWindow->GetText();
+ return aText;
+}
+
+void VCLXFixedHyperlink::setURL( const OUString& URL )
+{
+ SolarMutexGuard aGuard;
+ VclPtr< FixedHyperlink > pBase = GetAs< FixedHyperlink >();
+ if ( pBase )
+ pBase->SetURL( URL );
+}
+
+OUString VCLXFixedHyperlink::getURL( )
+{
+ SolarMutexGuard aGuard;
+
+ OUString aText;
+ VclPtr< FixedHyperlink > pBase = GetAs< FixedHyperlink >();
+ if ( pBase )
+ aText = pBase->GetURL();
+ return aText;
+}
+
+void VCLXFixedHyperlink::setAlignment( sal_Int16 nAlign )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< vcl::Window > pWindow = GetWindow();
+ if ( !pWindow )
+ return;
+
+ WinBits nNewBits = 0;
+ if ( nAlign == css::awt::TextAlign::LEFT )
+ nNewBits = WB_LEFT;
+ else if ( nAlign == css::awt::TextAlign::CENTER )
+ nNewBits = WB_CENTER;
+ else
+ nNewBits = WB_RIGHT;
+
+ WinBits nStyle = pWindow->GetStyle();
+ nStyle &= ~(WB_LEFT|WB_CENTER|WB_RIGHT);
+ pWindow->SetStyle( nStyle | nNewBits );
+}
+
+sal_Int16 VCLXFixedHyperlink::getAlignment()
+{
+ SolarMutexGuard aGuard;
+
+ sal_Int16 nAlign = 0;
+ VclPtr< vcl::Window > pWindow = GetWindow();
+ if ( pWindow )
+ {
+ WinBits nStyle = pWindow->GetStyle();
+ if ( nStyle & WB_LEFT )
+ nAlign = css::awt::TextAlign::LEFT;
+ else if ( nStyle & WB_CENTER )
+ nAlign = css::awt::TextAlign::CENTER;
+ else
+ nAlign = css::awt::TextAlign::RIGHT;
+ }
+ return nAlign;
+}
+
+void VCLXFixedHyperlink::addActionListener( const css::uno::Reference< css::awt::XActionListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maActionListeners.addInterface( l );
+}
+
+void VCLXFixedHyperlink::removeActionListener( const css::uno::Reference< css::awt::XActionListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maActionListeners.removeInterface( l );
+}
+
+css::awt::Size VCLXFixedHyperlink::getMinimumSize( )
+{
+ SolarMutexGuard aGuard;
+ Size aSz;
+ VclPtr< FixedText > pFixedText = GetAs< FixedText >();
+ if ( pFixedText )
+ aSz = pFixedText->CalcMinimumSize();
+ return AWTSize(aSz);
+}
+
+css::awt::Size VCLXFixedHyperlink::getPreferredSize( )
+{
+ return getMinimumSize();
+}
+
+css::awt::Size VCLXFixedHyperlink::calcAdjustedSize( const css::awt::Size& rNewSize )
+{
+ SolarMutexGuard aGuard;
+ Size aSz( VCLUnoHelper::ConvertToVCLSize( rNewSize ));
+ VclPtr< FixedText > pFixedText = GetAs< FixedText >();
+ if (pFixedText)
+ {
+ Size aMinSz = pFixedText->CalcMinimumSize(rNewSize.Width);
+ if ( ( aSz.Width() > aMinSz.Width() ) && ( aSz.Height() < aMinSz.Height() ) )
+ aSz.setHeight( aMinSz.Height() );
+ else
+ aSz = aMinSz;
+ }
+
+ return VCLUnoHelper::ConvertToAWTSize(aSz);
+}
+
+void VCLXFixedHyperlink::setProperty( const OUString& PropertyName, const css::uno::Any& Value)
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< FixedHyperlink > pBase = GetAs< FixedHyperlink >();
+ if ( !pBase )
+ return;
+
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_LABEL:
+ {
+ OUString sNewLabel;
+ if ( Value >>= sNewLabel )
+ pBase->SetText(sNewLabel);
+ break;
+ }
+
+ case BASEPROPERTY_URL:
+ {
+ OUString sNewURL;
+ if ( Value >>= sNewURL )
+ pBase->SetURL( sNewURL );
+ break;
+ }
+
+ default:
+ {
+ VCLXWindow::setProperty( PropertyName, Value );
+ }
+ }
+}
+
+css::uno::Any VCLXFixedHyperlink::getProperty( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Any aProp;
+ VclPtr< FixedHyperlink > pBase = GetAs< FixedHyperlink >();
+ if ( pBase )
+ {
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_URL:
+ {
+ aProp <<= pBase->GetURL();
+ break;
+ }
+
+ default:
+ {
+ aProp = VCLXWindow::getProperty( PropertyName );
+ }
+ }
+ }
+ return aProp;
+}
+
+void VCLXFixedHyperlink::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ BASEPROPERTY_ALIGN,
+ BASEPROPERTY_BACKGROUNDCOLOR,
+ BASEPROPERTY_BORDER,
+ BASEPROPERTY_BORDERCOLOR,
+ BASEPROPERTY_DEFAULTCONTROL,
+ BASEPROPERTY_ENABLED,
+ BASEPROPERTY_ENABLEVISIBLE,
+ BASEPROPERTY_FONTDESCRIPTOR,
+ BASEPROPERTY_HELPTEXT,
+ BASEPROPERTY_HELPURL,
+ BASEPROPERTY_LABEL,
+ BASEPROPERTY_MULTILINE,
+ BASEPROPERTY_NOLABEL,
+ BASEPROPERTY_PRINTABLE,
+ BASEPROPERTY_TABSTOP,
+ BASEPROPERTY_VERTICALALIGN,
+ BASEPROPERTY_URL,
+ BASEPROPERTY_WRITING_MODE,
+ BASEPROPERTY_CONTEXT_WRITING_MODE,
+ 0);
+ VCLXWindow::ImplGetPropertyIds( rIds );
+}
+
+
+
+void VCLXFixedText::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ BASEPROPERTY_ALIGN,
+ BASEPROPERTY_BACKGROUNDCOLOR,
+ BASEPROPERTY_BORDER,
+ BASEPROPERTY_BORDERCOLOR,
+ BASEPROPERTY_DEFAULTCONTROL,
+ BASEPROPERTY_ENABLED,
+ BASEPROPERTY_ENABLEVISIBLE,
+ BASEPROPERTY_FONTDESCRIPTOR,
+ BASEPROPERTY_HELPTEXT,
+ BASEPROPERTY_HELPURL,
+ BASEPROPERTY_LABEL,
+ BASEPROPERTY_MULTILINE,
+ BASEPROPERTY_NOLABEL,
+ BASEPROPERTY_PRINTABLE,
+ BASEPROPERTY_TABSTOP,
+ BASEPROPERTY_VERTICALALIGN,
+ BASEPROPERTY_WRITING_MODE,
+ BASEPROPERTY_CONTEXT_WRITING_MODE,
+ BASEPROPERTY_REFERENCE_DEVICE,
+ BASEPROPERTY_HIGHLIGHT_COLOR,
+ BASEPROPERTY_HIGHLIGHT_TEXT_COLOR,
+ 0);
+ VCLXWindow::ImplGetPropertyIds( rIds );
+}
+
+VCLXFixedText::VCLXFixedText()
+{
+}
+
+VCLXFixedText::~VCLXFixedText()
+{
+}
+
+css::uno::Reference< css::accessibility::XAccessibleContext > VCLXFixedText::CreateAccessibleContext()
+{
+ return getAccessibleFactory().createAccessibleContext( this );
+}
+
+void VCLXFixedText::setText( const OUString& Text )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< vcl::Window > pWindow = GetWindow();
+ if ( pWindow )
+ pWindow->SetText( Text );
+}
+
+OUString VCLXFixedText::getText()
+{
+ SolarMutexGuard aGuard;
+
+ OUString aText;
+ VclPtr< vcl::Window > pWindow = GetWindow();
+ if ( pWindow )
+ aText = pWindow->GetText();
+ return aText;
+}
+
+void VCLXFixedText::setAlignment( sal_Int16 nAlign )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< vcl::Window > pWindow = GetWindow();
+ if ( !pWindow )
+ return;
+
+ WinBits nNewBits = 0;
+ if ( nAlign == css::awt::TextAlign::LEFT )
+ nNewBits = WB_LEFT;
+ else if ( nAlign == css::awt::TextAlign::CENTER )
+ nNewBits = WB_CENTER;
+ else
+ nNewBits = WB_RIGHT;
+
+ WinBits nStyle = pWindow->GetStyle();
+ nStyle &= ~(WB_LEFT|WB_CENTER|WB_RIGHT);
+ pWindow->SetStyle( nStyle | nNewBits );
+}
+
+sal_Int16 VCLXFixedText::getAlignment()
+{
+ SolarMutexGuard aGuard;
+
+ sal_Int16 nAlign = 0;
+ VclPtr< vcl::Window > pWindow = GetWindow();
+ if ( pWindow )
+ {
+ WinBits nStyle = pWindow->GetStyle();
+ if ( nStyle & WB_LEFT )
+ nAlign = css::awt::TextAlign::LEFT;
+ else if ( nStyle & WB_CENTER )
+ nAlign = css::awt::TextAlign::CENTER;
+ else
+ nAlign = css::awt::TextAlign::RIGHT;
+ }
+ return nAlign;
+}
+
+css::awt::Size VCLXFixedText::getMinimumSize( )
+{
+ SolarMutexGuard aGuard;
+
+ Size aSz;
+ VclPtr< FixedText > pFixedText = GetAs< FixedText >();
+ if ( pFixedText )
+ aSz = pFixedText->CalcMinimumSize();
+ return AWTSize(aSz);
+}
+
+css::awt::Size VCLXFixedText::getPreferredSize( )
+{
+ return getMinimumSize();
+}
+
+css::awt::Size VCLXFixedText::calcAdjustedSize( const css::awt::Size& rMaxSize )
+{
+ SolarMutexGuard aGuard;
+
+ Size aAdjustedSize( VCLUnoHelper::ConvertToVCLSize( rMaxSize ) );
+ VclPtr< FixedText > pFixedText = GetAs< FixedText >();
+ if ( pFixedText )
+ aAdjustedSize = pFixedText->CalcMinimumSize( rMaxSize.Width );
+ return VCLUnoHelper::ConvertToAWTSize( aAdjustedSize );
+}
+
+
+
+void VCLXScrollBar::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ BASEPROPERTY_BACKGROUNDCOLOR,
+ BASEPROPERTY_BLOCKINCREMENT,
+ BASEPROPERTY_BORDER,
+ BASEPROPERTY_BORDERCOLOR,
+ BASEPROPERTY_DEFAULTCONTROL,
+ BASEPROPERTY_ENABLED,
+ BASEPROPERTY_ENABLEVISIBLE,
+ BASEPROPERTY_HELPTEXT,
+ BASEPROPERTY_HELPURL,
+ BASEPROPERTY_LINEINCREMENT,
+ BASEPROPERTY_LIVE_SCROLL,
+ BASEPROPERTY_ORIENTATION,
+ BASEPROPERTY_PRINTABLE,
+ BASEPROPERTY_REPEAT_DELAY,
+ BASEPROPERTY_SCROLLVALUE,
+ BASEPROPERTY_SCROLLVALUE_MAX,
+ BASEPROPERTY_SCROLLVALUE_MIN,
+ BASEPROPERTY_SYMBOL_COLOR,
+ BASEPROPERTY_TABSTOP,
+ BASEPROPERTY_VISIBLESIZE,
+ BASEPROPERTY_WRITING_MODE,
+ BASEPROPERTY_CONTEXT_WRITING_MODE,
+ 0);
+ VCLXWindow::ImplGetPropertyIds( rIds );
+}
+
+VCLXScrollBar::VCLXScrollBar() : maAdjustmentListeners( *this )
+{
+}
+
+css::uno::Reference< css::accessibility::XAccessibleContext > VCLXScrollBar::CreateAccessibleContext()
+{
+ return getAccessibleFactory().createAccessibleContext( this );
+}
+
+// css::lang::XComponent
+void VCLXScrollBar::dispose()
+{
+ SolarMutexGuard aGuard;
+
+ css::lang::EventObject aObj;
+ aObj.Source = getXWeak();
+ maAdjustmentListeners.disposeAndClear( aObj );
+ VCLXWindow::dispose();
+}
+
+// css::awt::XScrollbar
+void VCLXScrollBar::addAdjustmentListener( const css::uno::Reference< css::awt::XAdjustmentListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maAdjustmentListeners.addInterface( l );
+}
+
+void VCLXScrollBar::removeAdjustmentListener( const css::uno::Reference< css::awt::XAdjustmentListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maAdjustmentListeners.removeInterface( l );
+}
+
+void VCLXScrollBar::setValue( sal_Int32 n )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ScrollBar > pScrollBar = GetAs< ScrollBar >();
+ if ( pScrollBar )
+ pScrollBar->DoScroll( n );
+}
+
+void VCLXScrollBar::setValues( sal_Int32 nValue, sal_Int32 nVisible, sal_Int32 nMax )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ScrollBar > pScrollBar = GetAs< ScrollBar >();
+ if ( pScrollBar )
+ {
+ pScrollBar->SetVisibleSize( nVisible );
+ pScrollBar->SetRangeMax( nMax );
+ pScrollBar->DoScroll( nValue );
+ }
+}
+
+sal_Int32 VCLXScrollBar::getValue()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ScrollBar > pScrollBar = GetAs< ScrollBar >();
+ return pScrollBar ? pScrollBar->GetThumbPos() : 0;
+}
+
+void VCLXScrollBar::setMaximum( sal_Int32 n )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ScrollBar > pScrollBar = GetAs< ScrollBar >();
+ if ( pScrollBar )
+ pScrollBar->SetRangeMax( n );
+}
+
+sal_Int32 VCLXScrollBar::getMaximum()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ScrollBar > pScrollBar = GetAs< ScrollBar >();
+ return pScrollBar ? pScrollBar->GetRangeMax() : 0;
+}
+
+void VCLXScrollBar::setMinimum( sal_Int32 n )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ScrollBar > pScrollBar = GetAs< ScrollBar >();
+ if ( pScrollBar )
+ pScrollBar->SetRangeMin( n );
+}
+
+sal_Int32 VCLXScrollBar::getMinimum() const
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ScrollBar > pScrollBar = GetAs< ScrollBar >();
+ return pScrollBar ? pScrollBar->GetRangeMin() : 0;
+}
+
+void VCLXScrollBar::setLineIncrement( sal_Int32 n )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ScrollBar > pScrollBar = GetAs< ScrollBar >();
+ if ( pScrollBar )
+ pScrollBar->SetLineSize( n );
+}
+
+sal_Int32 VCLXScrollBar::getLineIncrement()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ScrollBar > pScrollBar = GetAs< ScrollBar >();
+ return pScrollBar ? pScrollBar->GetLineSize() : 0;
+}
+
+void VCLXScrollBar::setBlockIncrement( sal_Int32 n )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ScrollBar > pScrollBar = GetAs< ScrollBar >();
+ if ( pScrollBar )
+ pScrollBar->SetPageSize( n );
+}
+
+sal_Int32 VCLXScrollBar::getBlockIncrement()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ScrollBar > pScrollBar = GetAs< ScrollBar >();
+ return pScrollBar ? pScrollBar->GetPageSize() : 0;
+}
+
+void VCLXScrollBar::setVisibleSize( sal_Int32 n )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ScrollBar > pScrollBar = GetAs< ScrollBar >();
+ if ( pScrollBar )
+ pScrollBar->SetVisibleSize( n );
+}
+
+sal_Int32 VCLXScrollBar::getVisibleSize()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ScrollBar > pScrollBar = GetAs< ScrollBar >();
+ return pScrollBar ? pScrollBar->GetVisibleSize() : 0;
+}
+
+void VCLXScrollBar::setOrientation( sal_Int32 n )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< vcl::Window > pWindow = GetWindow();
+ if ( pWindow )
+ {
+ WinBits nStyle = pWindow->GetStyle();
+ nStyle &= ~(WB_HORZ|WB_VERT);
+ if ( n == css::awt::ScrollBarOrientation::HORIZONTAL )
+ nStyle |= WB_HORZ;
+ else
+ nStyle |= WB_VERT;
+
+ pWindow->SetStyle( nStyle );
+ pWindow->Resize();
+ }
+}
+
+sal_Int32 VCLXScrollBar::getOrientation()
+{
+ SolarMutexGuard aGuard;
+
+ sal_Int32 n = 0;
+ VclPtr< vcl::Window > pWindow = GetWindow();
+ if ( pWindow )
+ {
+ WinBits nStyle = pWindow->GetStyle();
+ if ( nStyle & WB_HORZ )
+ n = css::awt::ScrollBarOrientation::HORIZONTAL;
+ else
+ n = css::awt::ScrollBarOrientation::VERTICAL;
+ }
+ return n;
+
+}
+
+// css::awt::VclWindowPeer
+void VCLXScrollBar::setProperty( const OUString& PropertyName, const css::uno::Any& Value)
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ScrollBar > pScrollBar = GetAs< ScrollBar >();
+ if ( !pScrollBar )
+ return;
+
+ bool bVoid = Value.getValueType().getTypeClass() == css::uno::TypeClass_VOID;
+
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_LIVE_SCROLL:
+ {
+ bool bDo = false;
+ if ( !bVoid )
+ {
+ OSL_VERIFY( Value >>= bDo );
+ }
+ AllSettings aSettings( pScrollBar->GetSettings() );
+ StyleSettings aStyle( aSettings.GetStyleSettings() );
+ DragFullOptions nDragOptions = aStyle.GetDragFullOptions();
+ if ( bDo )
+ nDragOptions |= DragFullOptions::Scroll;
+ else
+ nDragOptions &= ~DragFullOptions::Scroll;
+ aStyle.SetDragFullOptions( nDragOptions );
+ aSettings.SetStyleSettings( aStyle );
+ pScrollBar->SetSettings( aSettings );
+ }
+ break;
+
+ case BASEPROPERTY_SCROLLVALUE:
+ {
+ if ( !bVoid )
+ {
+ sal_Int32 n = 0;
+ if ( Value >>= n )
+ setValue( n );
+ }
+ }
+ break;
+ case BASEPROPERTY_SCROLLVALUE_MAX:
+ case BASEPROPERTY_SCROLLVALUE_MIN:
+ {
+ if ( !bVoid )
+ {
+ sal_Int32 n = 0;
+ if ( Value >>= n )
+ {
+ if ( nPropType == BASEPROPERTY_SCROLLVALUE_MAX )
+ setMaximum( n );
+ else
+ setMinimum( n );
+ }
+ }
+ }
+ break;
+ case BASEPROPERTY_LINEINCREMENT:
+ {
+ if ( !bVoid )
+ {
+ sal_Int32 n = 0;
+ if ( Value >>= n )
+ setLineIncrement( n );
+ }
+ }
+ break;
+ case BASEPROPERTY_BLOCKINCREMENT:
+ {
+ if ( !bVoid )
+ {
+ sal_Int32 n = 0;
+ if ( Value >>= n )
+ setBlockIncrement( n );
+ }
+ }
+ break;
+ case BASEPROPERTY_VISIBLESIZE:
+ {
+ if ( !bVoid )
+ {
+ sal_Int32 n = 0;
+ if ( Value >>= n )
+ setVisibleSize( n );
+ }
+ }
+ break;
+ case BASEPROPERTY_ORIENTATION:
+ {
+ if ( !bVoid )
+ {
+ sal_Int32 n = 0;
+ if ( Value >>= n )
+ setOrientation( n );
+ }
+ }
+ break;
+
+ case BASEPROPERTY_BACKGROUNDCOLOR:
+ {
+ // the default implementation of the base class doesn't work here, since our
+ // interpretation for this property is slightly different
+ ::toolkit::setButtonLikeFaceColor( pScrollBar, Value);
+ }
+ break;
+
+ default:
+ {
+ VCLXWindow::setProperty( PropertyName, Value );
+ }
+ }
+}
+
+css::uno::Any VCLXScrollBar::getProperty( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Any aProp;
+ VclPtr< ScrollBar > pScrollBar = GetAs< ScrollBar >();
+ if ( pScrollBar )
+ {
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_LIVE_SCROLL:
+ {
+ aProp <<= bool( pScrollBar->GetSettings().GetStyleSettings().GetDragFullOptions() & DragFullOptions::Scroll );
+ }
+ break;
+ case BASEPROPERTY_SCROLLVALUE:
+ {
+ aProp <<= getValue();
+ }
+ break;
+ case BASEPROPERTY_SCROLLVALUE_MAX:
+ {
+ aProp <<= getMaximum();
+ }
+ break;
+ case BASEPROPERTY_SCROLLVALUE_MIN:
+ {
+ aProp <<= getMinimum();
+ }
+ break;
+ case BASEPROPERTY_LINEINCREMENT:
+ {
+ aProp <<= getLineIncrement();
+ }
+ break;
+ case BASEPROPERTY_BLOCKINCREMENT:
+ {
+ aProp <<= getBlockIncrement();
+ }
+ break;
+ case BASEPROPERTY_VISIBLESIZE:
+ {
+ aProp <<= getVisibleSize();
+ }
+ break;
+ case BASEPROPERTY_ORIENTATION:
+ {
+ aProp <<= getOrientation();
+ }
+ break;
+ case BASEPROPERTY_BACKGROUNDCOLOR:
+ {
+ // the default implementation of the base class doesn't work here, since our
+ // interpretation for this property is slightly different
+ aProp = ::toolkit::getButtonLikeFaceColor( pScrollBar );
+ }
+ break;
+
+ default:
+ {
+ aProp = VCLXWindow::getProperty( PropertyName );
+ }
+ }
+ }
+ return aProp;
+}
+
+void VCLXScrollBar::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::ScrollbarScroll:
+ {
+ css::uno::Reference< css::awt::XWindow > xKeepAlive( this );
+ // since we call listeners below, there is a potential that we will be destroyed
+ // in during the listener call. To prevent the resulting crashes, we keep us
+ // alive as long as we're here
+
+ if ( maAdjustmentListeners.getLength() )
+ {
+ VclPtr< ScrollBar > pScrollBar = GetAs< ScrollBar >();
+
+ if( pScrollBar )
+ {
+ css::awt::AdjustmentEvent aEvent;
+ aEvent.Source = getXWeak();
+ aEvent.Value = pScrollBar->GetThumbPos();
+
+ // set adjustment type
+ ScrollType aType = pScrollBar->GetType();
+ if ( aType == ScrollType::LineUp || aType == ScrollType::LineDown )
+ {
+ aEvent.Type = css::awt::AdjustmentType_ADJUST_LINE;
+ }
+ else if ( aType == ScrollType::PageUp || aType == ScrollType::PageDown )
+ {
+ aEvent.Type = css::awt::AdjustmentType_ADJUST_PAGE;
+ }
+ else if ( aType == ScrollType::Drag )
+ {
+ aEvent.Type = css::awt::AdjustmentType_ADJUST_ABS;
+ }
+
+ maAdjustmentListeners.adjustmentValueChanged( aEvent );
+ }
+ }
+ }
+ break;
+
+ default:
+ VCLXWindow::ProcessWindowEvent( rVclWindowEvent );
+ break;
+ }
+}
+
+css::awt::Size VCLXScrollBar::implGetMinimumSize( vcl::Window const * p )
+{
+ tools::Long n = p->GetSettings().GetStyleSettings().GetScrollBarSize();
+ return css::awt::Size( n, n );
+}
+
+css::awt::Size SAL_CALL VCLXScrollBar::getMinimumSize()
+{
+ SolarMutexGuard aGuard;
+ return implGetMinimumSize( GetWindow() );
+}
+
+
+
+
+void VCLXEdit::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ BASEPROPERTY_ALIGN,
+ BASEPROPERTY_BACKGROUNDCOLOR,
+ BASEPROPERTY_BORDER,
+ BASEPROPERTY_BORDERCOLOR,
+ BASEPROPERTY_DEFAULTCONTROL,
+ BASEPROPERTY_ECHOCHAR,
+ BASEPROPERTY_ENABLED,
+ BASEPROPERTY_ENABLEVISIBLE,
+ BASEPROPERTY_FONTDESCRIPTOR,
+ BASEPROPERTY_HARDLINEBREAKS,
+ BASEPROPERTY_HELPTEXT,
+ BASEPROPERTY_HELPURL,
+ BASEPROPERTY_HSCROLL,
+ BASEPROPERTY_LINE_END_FORMAT,
+ BASEPROPERTY_MAXTEXTLEN,
+ BASEPROPERTY_MULTILINE,
+ BASEPROPERTY_PRINTABLE,
+ BASEPROPERTY_READONLY,
+ BASEPROPERTY_TABSTOP,
+ BASEPROPERTY_TEXT,
+ BASEPROPERTY_VSCROLL,
+ BASEPROPERTY_HIDEINACTIVESELECTION,
+ BASEPROPERTY_PAINTTRANSPARENT,
+ BASEPROPERTY_AUTOHSCROLL,
+ BASEPROPERTY_AUTOVSCROLL,
+ BASEPROPERTY_VERTICALALIGN,
+ BASEPROPERTY_WRITING_MODE,
+ BASEPROPERTY_CONTEXT_WRITING_MODE,
+ BASEPROPERTY_HIGHLIGHT_COLOR,
+ BASEPROPERTY_HIGHLIGHT_TEXT_COLOR,
+ 0);
+ VCLXWindow::ImplGetPropertyIds( rIds );
+}
+
+VCLXEdit::VCLXEdit() : maTextListeners( *this )
+{
+}
+
+css::uno::Reference< css::accessibility::XAccessibleContext > VCLXEdit::CreateAccessibleContext()
+{
+ return getAccessibleFactory().createAccessibleContext( this );
+}
+
+void VCLXEdit::dispose()
+{
+ SolarMutexGuard aGuard;
+
+ css::lang::EventObject aObj;
+ aObj.Source = getXWeak();
+ maTextListeners.disposeAndClear( aObj );
+ VCLXWindow::dispose();
+}
+
+void VCLXEdit::addTextListener( const css::uno::Reference< css::awt::XTextListener > & l )
+{
+ SolarMutexGuard aGuard;
+ GetTextListeners().addInterface( l );
+}
+
+void VCLXEdit::removeTextListener( const css::uno::Reference< css::awt::XTextListener > & l )
+{
+ SolarMutexGuard aGuard;
+ GetTextListeners().removeInterface( l );
+}
+
+void VCLXEdit::setText( const OUString& aText )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< Edit > pEdit = GetAs< Edit >();
+ if ( pEdit )
+ {
+ pEdit->SetText( aText );
+
+ // #107218# Call same listeners like VCL would do after user interaction
+ SetSynthesizingVCLEvent( true );
+ pEdit->SetModifyFlag();
+ pEdit->Modify();
+ SetSynthesizingVCLEvent( false );
+ }
+}
+
+void VCLXEdit::insertText( const css::awt::Selection& rSel, const OUString& aText )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< Edit > pEdit = GetAs< Edit >();
+ if ( pEdit )
+ {
+ pEdit->SetSelection( Selection( rSel.Min, rSel.Max ) );
+ pEdit->ReplaceSelected( aText );
+
+ // #107218# Call same listeners like VCL would do after user interaction
+ SetSynthesizingVCLEvent( true );
+ pEdit->SetModifyFlag();
+ pEdit->Modify();
+ SetSynthesizingVCLEvent( false );
+ }
+}
+
+OUString VCLXEdit::getText()
+{
+ SolarMutexGuard aGuard;
+
+ OUString aText;
+ VclPtr< vcl::Window > pWindow = GetWindow();
+ if ( pWindow )
+ aText = pWindow->GetText();
+ return aText;
+}
+
+OUString VCLXEdit::getSelectedText()
+{
+ SolarMutexGuard aGuard;
+
+ OUString aText;
+ VclPtr< Edit > pEdit = GetAs< Edit >();
+ if ( pEdit)
+ aText = pEdit->GetSelected();
+ return aText;
+
+}
+
+void VCLXEdit::setSelection( const css::awt::Selection& aSelection )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< Edit > pEdit = GetAs< Edit >();
+ if ( pEdit )
+ pEdit->SetSelection( Selection( aSelection.Min, aSelection.Max ) );
+}
+
+css::awt::Selection VCLXEdit::getSelection()
+{
+ SolarMutexGuard aGuard;
+
+ Selection aSel;
+ VclPtr< Edit > pEdit = GetAs< Edit >();
+ if ( pEdit )
+ aSel = pEdit->GetSelection();
+ return css::awt::Selection( aSel.Min(), aSel.Max() );
+}
+
+sal_Bool VCLXEdit::isEditable()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< Edit > pEdit = GetAs< Edit >();
+ return pEdit && !pEdit->IsReadOnly() && pEdit->IsEnabled();
+}
+
+void VCLXEdit::setEditable( sal_Bool bEditable )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< Edit > pEdit = GetAs< Edit >();
+ if ( pEdit )
+ pEdit->SetReadOnly( !bEditable );
+}
+
+
+void VCLXEdit::setMaxTextLen( sal_Int16 nLen )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< Edit > pEdit = GetAs< Edit >();
+ if ( pEdit )
+ pEdit->SetMaxTextLen( nLen );
+}
+
+sal_Int16 VCLXEdit::getMaxTextLen()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< Edit > pEdit = GetAs< Edit >();
+ return pEdit ? pEdit->GetMaxTextLen() : 0;
+}
+
+void VCLXEdit::setEchoChar( sal_Unicode cEcho )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< Edit > pEdit = GetAs< Edit >();
+ if ( pEdit )
+ pEdit->SetEchoChar( cEcho );
+}
+
+void VCLXEdit::setProperty( const OUString& PropertyName, const css::uno::Any& Value)
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< Edit > pEdit = GetAs< Edit >();
+ if ( !pEdit )
+ return;
+
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_HIDEINACTIVESELECTION:
+ ::toolkit::adjustBooleanWindowStyle( Value, pEdit, WB_NOHIDESELECTION, true );
+ if ( pEdit->GetSubEdit() )
+ ::toolkit::adjustBooleanWindowStyle( Value, pEdit->GetSubEdit(), WB_NOHIDESELECTION, true );
+ break;
+
+ case BASEPROPERTY_READONLY:
+ {
+ bool b = bool();
+ if ( Value >>= b )
+ pEdit->SetReadOnly( b );
+ }
+ break;
+ case BASEPROPERTY_ECHOCHAR:
+ {
+ sal_Int16 n = sal_Int16();
+ if ( Value >>= n )
+ pEdit->SetEchoChar( n );
+ }
+ break;
+ case BASEPROPERTY_MAXTEXTLEN:
+ {
+ sal_Int16 n = sal_Int16();
+ if ( Value >>= n )
+ pEdit->SetMaxTextLen( n );
+ }
+ break;
+ default:
+ {
+ VCLXWindow::setProperty( PropertyName, Value );
+ }
+ }
+}
+
+css::uno::Any VCLXEdit::getProperty( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Any aProp;
+ VclPtr< Edit > pEdit = GetAs< Edit >();
+ if ( pEdit )
+ {
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_HIDEINACTIVESELECTION:
+ aProp <<= ( ( pEdit->GetStyle() & WB_NOHIDESELECTION ) == 0 );
+ break;
+ case BASEPROPERTY_READONLY:
+ aProp <<= pEdit->IsReadOnly();
+ break;
+ case BASEPROPERTY_ECHOCHAR:
+ aProp <<= static_cast<sal_Int16>(pEdit->GetEchoChar());
+ break;
+ case BASEPROPERTY_MAXTEXTLEN:
+ aProp <<= static_cast<sal_Int16>(pEdit->GetMaxTextLen());
+ break;
+ default:
+ {
+ aProp = VCLXWindow::getProperty( PropertyName );
+ }
+ }
+ }
+ return aProp;
+}
+
+css::awt::Size VCLXEdit::getMinimumSize( )
+{
+ SolarMutexGuard aGuard;
+
+ Size aSz;
+ VclPtr< Edit > pEdit = GetAs< Edit >();
+ if ( pEdit )
+ aSz = pEdit->CalcMinimumSize();
+ return AWTSize(aSz);
+}
+
+css::awt::Size VCLXEdit::getPreferredSize( )
+{
+ SolarMutexGuard aGuard;
+
+ Size aSz;
+ VclPtr< Edit > pEdit = GetAs< Edit >();
+ if ( pEdit )
+ {
+ aSz = pEdit->CalcMinimumSize();
+ aSz.AdjustHeight(4 );
+ }
+ return AWTSize(aSz);
+}
+
+css::awt::Size VCLXEdit::calcAdjustedSize( const css::awt::Size& rNewSize )
+{
+ SolarMutexGuard aGuard;
+
+ css::awt::Size aSz = rNewSize;
+ css::awt::Size aMinSz = getMinimumSize();
+ if ( aSz.Height != aMinSz.Height )
+ aSz.Height = aMinSz.Height;
+
+ return aSz;
+}
+
+css::awt::Size VCLXEdit::getMinimumSize( sal_Int16 nCols, sal_Int16 )
+{
+ SolarMutexGuard aGuard;
+
+ Size aSz;
+ VclPtr< Edit > pEdit = GetAs< Edit >();
+ if ( pEdit )
+ {
+ if ( nCols )
+ aSz = pEdit->CalcSize( nCols );
+ else
+ aSz = pEdit->CalcMinimumSize();
+ }
+ return AWTSize(aSz);
+}
+
+void VCLXEdit::getColumnsAndLines( sal_Int16& nCols, sal_Int16& nLines )
+{
+ SolarMutexGuard aGuard;
+
+ nLines = 1;
+ nCols = 0;
+ VclPtr< Edit > pEdit = GetAs< Edit >();
+ if ( pEdit )
+ nCols = pEdit->GetMaxVisChars();
+}
+
+void VCLXEdit::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::EditModify:
+ {
+ css::uno::Reference< css::awt::XWindow > xKeepAlive( this );
+ // since we call listeners below, there is a potential that we will be destroyed
+ // during the listener call. To prevent the resulting crashes, we keep us
+ // alive as long as we're here
+
+ if ( GetTextListeners().getLength() )
+ {
+ css::awt::TextEvent aEvent;
+ aEvent.Source = getXWeak();
+ GetTextListeners().textChanged( aEvent );
+ }
+ }
+ break;
+
+ default:
+ VCLXWindow::ProcessWindowEvent( rVclWindowEvent );
+ break;
+ }
+}
+
+
+
+
+void VCLXComboBox::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ BASEPROPERTY_AUTOCOMPLETE,
+ BASEPROPERTY_BACKGROUNDCOLOR,
+ BASEPROPERTY_BORDER,
+ BASEPROPERTY_BORDERCOLOR,
+ BASEPROPERTY_DEFAULTCONTROL,
+ BASEPROPERTY_DROPDOWN,
+ BASEPROPERTY_ENABLED,
+ BASEPROPERTY_ENABLEVISIBLE,
+ BASEPROPERTY_FONTDESCRIPTOR,
+ BASEPROPERTY_HELPTEXT,
+ BASEPROPERTY_HELPURL,
+ BASEPROPERTY_LINECOUNT,
+ BASEPROPERTY_MAXTEXTLEN,
+ BASEPROPERTY_PRINTABLE,
+ BASEPROPERTY_READONLY,
+ BASEPROPERTY_STRINGITEMLIST,
+ BASEPROPERTY_TYPEDITEMLIST,
+ BASEPROPERTY_TABSTOP,
+ BASEPROPERTY_TEXT,
+ BASEPROPERTY_HIDEINACTIVESELECTION,
+ BASEPROPERTY_ALIGN,
+ BASEPROPERTY_WRITING_MODE,
+ BASEPROPERTY_CONTEXT_WRITING_MODE,
+ BASEPROPERTY_REFERENCE_DEVICE,
+ BASEPROPERTY_MOUSE_WHEEL_BEHAVIOUR,
+ BASEPROPERTY_HIGHLIGHT_COLOR,
+ BASEPROPERTY_HIGHLIGHT_TEXT_COLOR,
+ 0);
+ // no, don't call VCLXEdit here - it has properties which we do *not* want to have at combo box
+ // #i92690# / 2008-08-12 / frank.schoenheit@sun.com
+ // VCLXEdit::ImplGetPropertyIds( rIds );
+ VCLXWindow::ImplGetPropertyIds( rIds );
+}
+
+VCLXComboBox::VCLXComboBox()
+ : maActionListeners( *this ), maItemListeners( *this )
+{
+}
+
+VCLXComboBox::~VCLXComboBox()
+{
+ SAL_INFO("toolkit", __FUNCTION__);
+}
+
+css::uno::Reference< css::accessibility::XAccessibleContext > VCLXComboBox::CreateAccessibleContext()
+{
+ SolarMutexGuard aGuard;
+
+ return getAccessibleFactory().createAccessibleContext( this );
+}
+
+void VCLXComboBox::dispose()
+{
+ SolarMutexGuard aGuard;
+
+ css::lang::EventObject aObj;
+ aObj.Source = getXWeak();
+ maItemListeners.disposeAndClear( aObj );
+ maActionListeners.disposeAndClear( aObj );
+ VCLXEdit::dispose();
+}
+
+
+void VCLXComboBox::addItemListener( const css::uno::Reference< css::awt::XItemListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maItemListeners.addInterface( l );
+}
+
+void VCLXComboBox::removeItemListener( const css::uno::Reference< css::awt::XItemListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maItemListeners.removeInterface( l );
+}
+
+void VCLXComboBox::addActionListener( const css::uno::Reference< css::awt::XActionListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maActionListeners.addInterface( l );
+}
+
+void VCLXComboBox::removeActionListener( const css::uno::Reference< css::awt::XActionListener > & l )
+{
+ SolarMutexGuard aGuard;
+ maActionListeners.removeInterface( l );
+}
+
+void VCLXComboBox::addItem( const OUString& aItem, sal_Int16 nPos )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ComboBox > pBox = GetAs< ComboBox >();
+ if ( pBox )
+ pBox->InsertEntry( aItem, nPos );
+}
+
+void VCLXComboBox::addItems( const css::uno::Sequence< OUString>& aItems, sal_Int16 nPos )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ComboBox > pBox = GetAs< ComboBox >();
+ if ( !pBox )
+ return;
+
+ sal_uInt16 nP = nPos;
+ for ( const auto& rItem : aItems )
+ {
+ pBox->InsertEntry( rItem, nP );
+ if ( nP == 0xFFFF )
+ {
+ OSL_FAIL( "VCLXComboBox::addItems: too many entries!" );
+ // skip remaining entries, list cannot hold them, anyway
+ break;
+ }
+ }
+}
+
+void VCLXComboBox::removeItems( sal_Int16 nPos, sal_Int16 nCount )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ComboBox > pBox = GetAs< ComboBox >();
+ if ( pBox )
+ {
+ for ( sal_uInt16 n = nCount; n; )
+ pBox->RemoveEntryAt( nPos + (--n) );
+ }
+}
+
+sal_Int16 VCLXComboBox::getItemCount()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ComboBox > pBox = GetAs< ComboBox >();
+ return pBox ? pBox->GetEntryCount() : 0;
+}
+
+OUString VCLXComboBox::getItem( sal_Int16 nPos )
+{
+ SolarMutexGuard aGuard;
+
+ OUString aItem;
+ VclPtr< ComboBox > pBox = GetAs< ComboBox >();
+ if ( pBox )
+ aItem = pBox->GetEntry( nPos );
+ return aItem;
+}
+
+css::uno::Sequence< OUString> VCLXComboBox::getItems()
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Sequence< OUString> aSeq;
+ VclPtr< ComboBox > pBox = GetAs< ComboBox >();
+ if ( pBox )
+ {
+ auto n = pBox->GetEntryCount();
+ aSeq = css::uno::Sequence< OUString>( n );
+ while ( n )
+ {
+ --n;
+ aSeq.getArray()[n] = pBox->GetEntry( n );
+ }
+ }
+ return aSeq;
+}
+
+void VCLXComboBox::setDropDownLineCount( sal_Int16 nLines )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ComboBox > pBox = GetAs< ComboBox >();
+ if ( pBox )
+ pBox->SetDropDownLineCount( nLines );
+}
+
+sal_Int16 VCLXComboBox::getDropDownLineCount()
+{
+ SolarMutexGuard aGuard;
+
+ sal_Int16 nLines = 0;
+ VclPtr< ComboBox > pBox = GetAs< ComboBox >();
+ if ( pBox )
+ nLines = pBox->GetDropDownLineCount();
+ return nLines;
+}
+
+void VCLXComboBox::setProperty( const OUString& PropertyName, const css::uno::Any& Value)
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ComboBox > pComboBox = GetAs< ComboBox >();
+ if ( !pComboBox )
+ return;
+
+ bool bVoid = Value.getValueType().getTypeClass() == css::uno::TypeClass_VOID;
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_LINECOUNT:
+ {
+ sal_Int16 n = sal_Int16();
+ if ( Value >>= n )
+ pComboBox->SetDropDownLineCount( n );
+ }
+ break;
+ case BASEPROPERTY_AUTOCOMPLETE:
+ {
+ sal_Int16 n = sal_Int16();
+ if ( Value >>= n )
+ pComboBox->EnableAutocomplete( n != 0 );
+ else
+ {
+ bool b = bool();
+ if ( Value >>= b )
+ pComboBox->EnableAutocomplete( b );
+ }
+ }
+ break;
+ case BASEPROPERTY_STRINGITEMLIST:
+ {
+ css::uno::Sequence< OUString> aItems;
+ if ( Value >>= aItems )
+ {
+ pComboBox->Clear();
+ addItems( aItems, 0 );
+ }
+ }
+ break;
+ case BASEPROPERTY_HIGHLIGHT_COLOR:
+ {
+ Color nColor = 0;
+ if (bVoid)
+ {
+ nColor = Application::GetSettings().GetStyleSettings().GetHighlightColor();
+ }
+ else
+ {
+ if (!(Value >>= nColor))
+ break;
+ }
+ pComboBox->SetHighlightColor(nColor);
+ }
+ break;
+ case BASEPROPERTY_HIGHLIGHT_TEXT_COLOR:
+ {
+ Color nColor = 0;
+ if (bVoid)
+ {
+ nColor = Application::GetSettings().GetStyleSettings().GetHighlightTextColor();
+ }
+ else
+ {
+ if (!(Value >>= nColor))
+ break;
+ }
+ pComboBox->SetHighlightTextColor(nColor);
+ }
+ break;
+ default:
+ {
+ VCLXEdit::setProperty( PropertyName, Value );
+
+ // #109385# SetBorderStyle is not virtual
+ if ( nPropType == BASEPROPERTY_BORDER )
+ {
+ sal_uInt16 nBorder = sal_uInt16();
+ if ( (Value >>= nBorder) && nBorder != 0 )
+ pComboBox->SetBorderStyle( static_cast<WindowBorderStyle>(nBorder) );
+ }
+ }
+ }
+}
+
+css::uno::Any VCLXComboBox::getProperty( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Any aProp;
+ VclPtr< ComboBox > pComboBox = GetAs< ComboBox >();
+ if ( pComboBox )
+ {
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_LINECOUNT:
+ {
+ aProp <<= static_cast<sal_Int16>(pComboBox->GetDropDownLineCount());
+ }
+ break;
+ case BASEPROPERTY_AUTOCOMPLETE:
+ {
+ aProp <<= pComboBox->IsAutocompleteEnabled();
+ }
+ break;
+ case BASEPROPERTY_STRINGITEMLIST:
+ {
+ const sal_Int32 nItems = pComboBox->GetEntryCount();
+ css::uno::Sequence< OUString> aSeq( nItems );
+ OUString* pStrings = aSeq.getArray();
+ for ( sal_Int32 n = 0; n < nItems; ++n )
+ pStrings[n] = pComboBox->GetEntry( n );
+ aProp <<= aSeq;
+
+ }
+ break;
+ default:
+ {
+ aProp = VCLXEdit::getProperty( PropertyName );
+ }
+ }
+ }
+ return aProp;
+}
+
+void VCLXComboBox::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ css::uno::Reference< css::awt::XWindow > xKeepAlive( this );
+ // since we call listeners below, there is a potential that we will be destroyed
+ // during the listener call. To prevent the resulting crashes, we keep us
+ // alive as long as we're here
+
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::ComboboxSelect:
+ if ( maItemListeners.getLength() )
+ {
+ VclPtr< ComboBox > pComboBox = GetAs< ComboBox >();
+ if( pComboBox )
+ {
+ if ( !pComboBox->IsTravelSelect() )
+ {
+ css::awt::ItemEvent aEvent;
+ aEvent.Source = getXWeak();
+ aEvent.Highlighted = 0;
+
+ // Set to 0xFFFF on multiple selection, selected entry ID otherwise
+ aEvent.Selected = pComboBox->GetEntryPos( pComboBox->GetText() );
+
+ maItemListeners.itemStateChanged( aEvent );
+ }
+ }
+ }
+ break;
+
+ case VclEventId::ComboboxDoubleClick:
+ if ( maActionListeners.getLength() )
+ {
+ css::awt::ActionEvent aEvent;
+ aEvent.Source = getXWeak();
+// aEvent.ActionCommand = ...;
+ maActionListeners.actionPerformed( aEvent );
+ }
+ break;
+
+ default:
+ VCLXEdit::ProcessWindowEvent( rVclWindowEvent );
+ break;
+ }
+}
+
+css::awt::Size VCLXComboBox::getMinimumSize( )
+{
+ SolarMutexGuard aGuard;
+
+ Size aSz;
+ VclPtr< ComboBox > pComboBox = GetAs< ComboBox >();
+ if ( pComboBox )
+ aSz = pComboBox->CalcMinimumSize();
+ return AWTSize(aSz);
+}
+
+css::awt::Size VCLXComboBox::getPreferredSize( )
+{
+ SolarMutexGuard aGuard;
+
+ Size aSz;
+ VclPtr< ComboBox > pComboBox = GetAs< ComboBox >();
+ if ( pComboBox )
+ {
+ aSz = pComboBox->CalcMinimumSize();
+ if ( pComboBox->GetStyle() & WB_DROPDOWN )
+ aSz.AdjustHeight(4 );
+ }
+ return AWTSize(aSz);
+}
+
+css::awt::Size VCLXComboBox::calcAdjustedSize( const css::awt::Size& rNewSize )
+{
+ SolarMutexGuard aGuard;
+
+ Size aSz = VCLSize(rNewSize);
+ VclPtr< ComboBox > pComboBox = GetAs< ComboBox >();
+ if ( pComboBox )
+ aSz = pComboBox->CalcAdjustedSize( aSz );
+ return AWTSize(aSz);
+}
+
+css::awt::Size VCLXComboBox::getMinimumSize( sal_Int16 nCols, sal_Int16 nLines )
+{
+ SolarMutexGuard aGuard;
+
+ Size aSz;
+ VclPtr< ComboBox > pComboBox = GetAs< ComboBox >();
+ if ( pComboBox )
+ aSz = pComboBox->CalcBlockSize( nCols, nLines );
+ return AWTSize(aSz);
+}
+
+void VCLXComboBox::getColumnsAndLines( sal_Int16& nCols, sal_Int16& nLines )
+{
+ SolarMutexGuard aGuard;
+
+ nCols = nLines = 0;
+ VclPtr< ComboBox > pComboBox = GetAs< ComboBox >();
+ if ( pComboBox )
+ {
+ sal_uInt16 nC, nL;
+ pComboBox->GetMaxVisColumnsAndLines( nC, nL );
+ nCols = nC;
+ nLines = nL;
+ }
+}
+void SAL_CALL VCLXComboBox::listItemInserted( const ItemListEvent& i_rEvent )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ComboBox > pComboBox = GetAsDynamic< ComboBox >();
+
+ ENSURE_OR_RETURN_VOID( pComboBox, "VCLXComboBox::listItemInserted: no ComboBox?!" );
+ ENSURE_OR_RETURN_VOID( ( i_rEvent.ItemPosition >= 0 ) && ( i_rEvent.ItemPosition <= pComboBox->GetEntryCount() ),
+ "VCLXComboBox::listItemInserted: illegal (inconsistent) item position!" );
+ pComboBox->InsertEntryWithImage(
+ i_rEvent.ItemText.IsPresent ? i_rEvent.ItemText.Value : OUString(),
+ i_rEvent.ItemImageURL.IsPresent ? lcl_getImageFromURL( i_rEvent.ItemImageURL.Value ) : Image(),
+ i_rEvent.ItemPosition );
+}
+
+void SAL_CALL VCLXComboBox::listItemRemoved( const ItemListEvent& i_rEvent )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ComboBox > pComboBox = GetAsDynamic< ComboBox >();
+
+ ENSURE_OR_RETURN_VOID( pComboBox, "VCLXComboBox::listItemRemoved: no ComboBox?!" );
+ ENSURE_OR_RETURN_VOID( ( i_rEvent.ItemPosition >= 0 ) && ( i_rEvent.ItemPosition < pComboBox->GetEntryCount() ),
+ "VCLXComboBox::listItemRemoved: illegal (inconsistent) item position!" );
+
+ pComboBox->RemoveEntryAt( i_rEvent.ItemPosition );
+}
+
+void SAL_CALL VCLXComboBox::listItemModified( const ItemListEvent& i_rEvent )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ComboBox > pComboBox = GetAsDynamic< ComboBox >();
+
+ ENSURE_OR_RETURN_VOID( pComboBox, "VCLXComboBox::listItemModified: no ComboBox?!" );
+ ENSURE_OR_RETURN_VOID( ( i_rEvent.ItemPosition >= 0 ) && ( i_rEvent.ItemPosition < pComboBox->GetEntryCount() ),
+ "VCLXComboBox::listItemModified: illegal (inconsistent) item position!" );
+
+ // VCL's ComboBox does not support changing an entry's text or image, so remove and re-insert
+
+ const OUString sNewText = i_rEvent.ItemText.IsPresent ? i_rEvent.ItemText.Value : pComboBox->GetEntry( i_rEvent.ItemPosition );
+ const Image aNewImage( i_rEvent.ItemImageURL.IsPresent ? lcl_getImageFromURL( i_rEvent.ItemImageURL.Value ) : pComboBox->GetEntryImage( i_rEvent.ItemPosition ) );
+
+ pComboBox->RemoveEntryAt( i_rEvent.ItemPosition );
+ pComboBox->InsertEntryWithImage(sNewText, aNewImage, i_rEvent.ItemPosition);
+}
+
+void SAL_CALL VCLXComboBox::allItemsRemoved( const EventObject& )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ComboBox > pComboBox = GetAsDynamic< ComboBox >();
+ ENSURE_OR_RETURN_VOID( pComboBox, "VCLXComboBox::listItemModified: no ComboBox?!" );
+
+ pComboBox->Clear();
+}
+
+void SAL_CALL VCLXComboBox::itemListChanged( const EventObject& i_rEvent )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ComboBox > pComboBox = GetAsDynamic< ComboBox >();
+ ENSURE_OR_RETURN_VOID( pComboBox, "VCLXComboBox::listItemModified: no ComboBox?!" );
+
+ pComboBox->Clear();
+
+ uno::Reference< beans::XPropertySet > xPropSet( i_rEvent.Source, uno::UNO_QUERY_THROW );
+ uno::Reference< beans::XPropertySetInfo > xPSI( xPropSet->getPropertySetInfo(), uno::UNO_SET_THROW );
+ // bool localize = xPSI->hasPropertyByName("ResourceResolver");
+ uno::Reference< resource::XStringResourceResolver > xStringResourceResolver;
+ if ( xPSI->hasPropertyByName("ResourceResolver") )
+ {
+ xStringResourceResolver.set(
+ xPropSet->getPropertyValue("ResourceResolver"),
+ uno::UNO_QUERY
+ );
+ }
+
+
+ Reference< XItemList > xItemList( i_rEvent.Source, uno::UNO_QUERY_THROW );
+ const uno::Sequence< beans::Pair< OUString, OUString > > aItems = xItemList->getAllItems();
+ for ( const auto& rItem : aItems )
+ {
+ OUString aLocalizationKey( rItem.First );
+ if ( xStringResourceResolver.is() && !aLocalizationKey.isEmpty() && aLocalizationKey[0] == '&' )
+ {
+ aLocalizationKey = xStringResourceResolver->resolveString(aLocalizationKey.copy( 1 ));
+ }
+ pComboBox->InsertEntryWithImage(aLocalizationKey,
+ lcl_getImageFromURL(rItem.Second));
+ }
+}
+void SAL_CALL VCLXComboBox::disposing( const EventObject& i_rEvent )
+{
+ // just disambiguate
+ VCLXEdit::disposing( i_rEvent );
+}
+
+
+
+void VCLXFormattedSpinField::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ // Interestingly in the UnoControl API this is
+ // - not derived from XEdit ultimately, (correct ?) - so cut this here ...
+// VCLXSpinField::ImplGetPropertyIds( rIds );
+ VCLXWindow::ImplGetPropertyIds( rIds );
+}
+
+VCLXFormattedSpinField::VCLXFormattedSpinField()
+ : mpFormatter(nullptr)
+{
+}
+
+VCLXFormattedSpinField::~VCLXFormattedSpinField()
+{
+}
+
+void VCLXFormattedSpinField::setStrictFormat( bool bStrict )
+{
+ SolarMutexGuard aGuard;
+
+ FormatterBase* pFormatter = GetFormatter();
+ if ( pFormatter )
+ pFormatter->SetStrictFormat( bStrict );
+}
+
+bool VCLXFormattedSpinField::isStrictFormat() const
+{
+ FormatterBase* pFormatter = GetFormatter();
+ return pFormatter && pFormatter->IsStrictFormat();
+}
+
+
+void VCLXFormattedSpinField::setProperty( const OUString& PropertyName, const css::uno::Any& Value)
+{
+ SolarMutexGuard aGuard;
+
+ FormatterBase* pFormatter = GetFormatter();
+ if ( !pFormatter )
+ return;
+
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_SPIN:
+ {
+ bool b = bool();
+ if ( Value >>= b )
+ {
+ WinBits nStyle = GetWindow()->GetStyle() | WB_SPIN;
+ if ( !b )
+ nStyle &= ~WB_SPIN;
+ GetWindow()->SetStyle( nStyle );
+ }
+ }
+ break;
+ case BASEPROPERTY_STRICTFORMAT:
+ {
+ bool b = bool();
+ if ( Value >>= b )
+ {
+ pFormatter->SetStrictFormat( b );
+ }
+ }
+ break;
+ default:
+ {
+ VCLXSpinField::setProperty( PropertyName, Value );
+ }
+ }
+}
+
+css::uno::Any VCLXFormattedSpinField::getProperty( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Any aProp;
+ FormatterBase* pFormatter = GetFormatter();
+ if ( pFormatter )
+ {
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_TABSTOP:
+ {
+ aProp <<= ( GetWindow()->GetStyle() & WB_SPIN ) != 0;
+ }
+ break;
+ case BASEPROPERTY_STRICTFORMAT:
+ {
+ aProp <<= pFormatter->IsStrictFormat();
+ }
+ break;
+ default:
+ {
+ aProp = VCLXSpinField::getProperty( PropertyName );
+ }
+ }
+ }
+ return aProp;
+}
+
+
+
+
+void VCLXDateField::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ BASEPROPERTY_ALIGN,
+ BASEPROPERTY_BACKGROUNDCOLOR,
+ BASEPROPERTY_BORDER,
+ BASEPROPERTY_BORDERCOLOR,
+ BASEPROPERTY_DATE,
+ BASEPROPERTY_DATEMAX,
+ BASEPROPERTY_DATEMIN,
+ BASEPROPERTY_DATESHOWCENTURY,
+ BASEPROPERTY_DEFAULTCONTROL,
+ BASEPROPERTY_DROPDOWN,
+ BASEPROPERTY_ENABLED,
+ BASEPROPERTY_ENABLEVISIBLE,
+ BASEPROPERTY_EXTDATEFORMAT,
+ BASEPROPERTY_FONTDESCRIPTOR,
+ BASEPROPERTY_HELPTEXT,
+ BASEPROPERTY_HELPURL,
+ BASEPROPERTY_PRINTABLE,
+ BASEPROPERTY_READONLY,
+ BASEPROPERTY_REPEAT,
+ BASEPROPERTY_REPEAT_DELAY,
+ BASEPROPERTY_SPIN,
+ BASEPROPERTY_STRICTFORMAT,
+ BASEPROPERTY_TABSTOP,
+ BASEPROPERTY_ENFORCE_FORMAT,
+ BASEPROPERTY_TEXT,
+ BASEPROPERTY_HIDEINACTIVESELECTION,
+ BASEPROPERTY_VERTICALALIGN,
+ BASEPROPERTY_WRITING_MODE,
+ BASEPROPERTY_CONTEXT_WRITING_MODE,
+ BASEPROPERTY_MOUSE_WHEEL_BEHAVIOUR,
+ BASEPROPERTY_HIGHLIGHT_COLOR,
+ BASEPROPERTY_HIGHLIGHT_TEXT_COLOR,
+ 0);
+ VCLXFormattedSpinField::ImplGetPropertyIds( rIds );
+}
+
+VCLXDateField::VCLXDateField()
+{
+}
+
+VCLXDateField::~VCLXDateField()
+{
+}
+
+//change the window type here to match the role
+css::uno::Reference< css::accessibility::XAccessibleContext > VCLXDateField::CreateAccessibleContext()
+{
+ VclPtr< vcl::Window > pWindow = GetWindow();
+ if ( pWindow )
+ {
+ pWindow->SetType( WindowType::DATEFIELD );
+ }
+ return getAccessibleFactory().createAccessibleContext( this );
+}
+
+void VCLXDateField::setProperty( const OUString& PropertyName, const css::uno::Any& Value)
+{
+ SolarMutexGuard aGuard;
+
+ if ( !(GetWindow()) )
+ return;
+
+ bool bVoid = Value.getValueType().getTypeClass() == css::uno::TypeClass_VOID;
+
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_DATE:
+ {
+ if ( bVoid )
+ {
+ GetAs< DateField >()->EnableEmptyFieldValue( true );
+ GetAs< DateField >()->SetEmptyFieldValue();
+ }
+ else
+ {
+ util::Date d;
+ if ((Value >>= d) && d.Year != 0)
+ setDate( d );
+ }
+ }
+ break;
+ case BASEPROPERTY_DATEMIN:
+ {
+ util::Date d;
+ if ((Value >>= d) && d.Year != 0)
+ setMin( d );
+ }
+ break;
+ case BASEPROPERTY_DATEMAX:
+ {
+ util::Date d;
+ if ((Value >>= d) && d.Year != 0)
+ setMax( d );
+ }
+ break;
+ case BASEPROPERTY_EXTDATEFORMAT:
+ {
+ sal_Int16 n = sal_Int16();
+ if ( Value >>= n )
+ GetAs< DateField >()->SetExtDateFormat( static_cast<ExtDateFieldFormat>(n) );
+ }
+ break;
+ case BASEPROPERTY_DATESHOWCENTURY:
+ {
+ bool b = bool();
+ if ( Value >>= b )
+ GetAs< DateField >()->SetShowDateCentury( b );
+ }
+ break;
+ case BASEPROPERTY_ENFORCE_FORMAT:
+ {
+ bool bEnforce( true );
+ OSL_VERIFY( Value >>= bEnforce );
+ GetAs< DateField >()->EnforceValidValue( bEnforce );
+ }
+ break;
+ default:
+ {
+ VCLXFormattedSpinField::setProperty( PropertyName, Value );
+ }
+ }
+}
+
+css::uno::Any VCLXDateField::getProperty( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Any aProp;
+ FormatterBase* pFormatter = GetFormatter();
+ if ( pFormatter )
+ {
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_DATE:
+ {
+ aProp <<= getDate();
+ }
+ break;
+ case BASEPROPERTY_DATEMIN:
+ {
+ aProp <<= getMin();
+ }
+ break;
+ case BASEPROPERTY_DATEMAX:
+ {
+ aProp <<= getMax();
+ }
+ break;
+ case BASEPROPERTY_DATESHOWCENTURY:
+ {
+ aProp <<= GetAs< DateField >()->IsShowDateCentury();
+ }
+ break;
+ case BASEPROPERTY_ENFORCE_FORMAT:
+ {
+ aProp <<= GetAs< DateField >()->IsEnforceValidValue( );
+ }
+ break;
+ default:
+ {
+ aProp = VCLXFormattedSpinField::getProperty( PropertyName );
+ }
+ }
+ }
+ return aProp;
+}
+
+
+void VCLXDateField::setDate( const util::Date& aDate )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< DateField > pDateField = GetAs< DateField >();
+ if ( pDateField )
+ {
+ pDateField->SetDate( aDate );
+
+ // #107218# Call same listeners like VCL would do after user interaction
+ SetSynthesizingVCLEvent( true );
+ pDateField->SetModifyFlag();
+ pDateField->Modify();
+ SetSynthesizingVCLEvent( false );
+ }
+}
+
+util::Date VCLXDateField::getDate()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< DateField > pDateField = GetAs< DateField >();
+ if ( pDateField )
+ return pDateField->GetDate().GetUNODate();
+ else
+ return util::Date();
+}
+
+void VCLXDateField::setMin( const util::Date& aDate )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< DateField > pDateField = GetAs< DateField >();
+ if ( pDateField )
+ pDateField->SetMin( aDate );
+}
+
+util::Date VCLXDateField::getMin()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< DateField > pDateField = GetAs< DateField >();
+ if ( pDateField )
+ return pDateField->GetMin().GetUNODate();
+ else
+ return util::Date();
+}
+
+void VCLXDateField::setMax( const util::Date& aDate )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< DateField > pDateField = GetAs< DateField >();
+ if ( pDateField )
+ pDateField->SetMax( aDate );
+}
+
+util::Date VCLXDateField::getMax()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< DateField > pDateField = GetAs< DateField >();
+ if ( pDateField )
+ return pDateField->GetMax().GetUNODate();
+ else
+ return util::Date();
+}
+
+void VCLXDateField::setFirst( const util::Date& aDate )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< DateField > pDateField = GetAs< DateField >();
+ if ( pDateField )
+ pDateField->SetFirst( aDate );
+}
+
+util::Date VCLXDateField::getFirst()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< DateField > pDateField = GetAs< DateField >();
+ if ( pDateField )
+ return pDateField->GetFirst().GetUNODate();
+ else
+ return util::Date();
+}
+
+void VCLXDateField::setLast( const util::Date& aDate )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< DateField > pDateField = GetAs< DateField >();
+ if ( pDateField )
+ pDateField->SetLast( aDate );
+}
+
+util::Date VCLXDateField::getLast()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< DateField > pDateField = GetAs< DateField >();
+ if ( pDateField )
+ return pDateField->GetLast().GetUNODate();
+ else
+ return util::Date();
+}
+
+void VCLXDateField::setLongFormat( sal_Bool bLong )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< DateField > pDateField = GetAs< DateField >();
+ if ( pDateField )
+ pDateField->SetLongFormat( bLong );
+}
+
+sal_Bool VCLXDateField::isLongFormat()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< DateField > pDateField = GetAs< DateField >();
+ return pDateField && pDateField->IsLongFormat();
+}
+
+void VCLXDateField::setEmpty()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< DateField > pDateField = GetAs< DateField >();
+ if ( pDateField )
+ {
+ pDateField->SetEmptyDate();
+
+ // #107218# Call same listeners like VCL would do after user interaction
+ SetSynthesizingVCLEvent( true );
+ pDateField->SetModifyFlag();
+ pDateField->Modify();
+ SetSynthesizingVCLEvent( false );
+ }
+}
+
+sal_Bool VCLXDateField::isEmpty()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< DateField > pDateField = GetAs< DateField >();
+ return pDateField && pDateField->IsEmptyDate();
+}
+
+void VCLXDateField::setStrictFormat( sal_Bool bStrict )
+{
+ VCLXFormattedSpinField::setStrictFormat( bStrict );
+}
+
+sal_Bool VCLXDateField::isStrictFormat()
+{
+ return VCLXFormattedSpinField::isStrictFormat();
+}
+
+
+
+
+void VCLXTimeField::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ BASEPROPERTY_ALIGN,
+ BASEPROPERTY_BACKGROUNDCOLOR,
+ BASEPROPERTY_BORDER,
+ BASEPROPERTY_BORDERCOLOR,
+ BASEPROPERTY_DEFAULTCONTROL,
+ BASEPROPERTY_ENABLED,
+ BASEPROPERTY_ENABLEVISIBLE,
+ BASEPROPERTY_EXTTIMEFORMAT,
+ BASEPROPERTY_FONTDESCRIPTOR,
+ BASEPROPERTY_HELPTEXT,
+ BASEPROPERTY_HELPURL,
+ BASEPROPERTY_PRINTABLE,
+ BASEPROPERTY_READONLY,
+ BASEPROPERTY_REPEAT,
+ BASEPROPERTY_REPEAT_DELAY,
+ BASEPROPERTY_SPIN,
+ BASEPROPERTY_STRICTFORMAT,
+ BASEPROPERTY_TABSTOP,
+ BASEPROPERTY_TIME,
+ BASEPROPERTY_TIMEMAX,
+ BASEPROPERTY_TIMEMIN,
+ BASEPROPERTY_ENFORCE_FORMAT,
+ BASEPROPERTY_TEXT,
+ BASEPROPERTY_HIDEINACTIVESELECTION,
+ BASEPROPERTY_VERTICALALIGN,
+ BASEPROPERTY_WRITING_MODE,
+ BASEPROPERTY_CONTEXT_WRITING_MODE,
+ BASEPROPERTY_MOUSE_WHEEL_BEHAVIOUR,
+ BASEPROPERTY_HIGHLIGHT_COLOR,
+ BASEPROPERTY_HIGHLIGHT_TEXT_COLOR,
+ 0);
+ VCLXFormattedSpinField::ImplGetPropertyIds( rIds );
+}
+
+VCLXTimeField::VCLXTimeField()
+{
+}
+
+VCLXTimeField::~VCLXTimeField()
+{
+}
+
+//change the window type here to match the role
+css::uno::Reference< css::accessibility::XAccessibleContext > VCLXTimeField::CreateAccessibleContext()
+{
+ VclPtr< vcl::Window > pWindow = GetWindow();
+ if ( pWindow )
+ {
+ pWindow->SetType( WindowType::TIMEFIELD );
+ }
+ return getAccessibleFactory().createAccessibleContext( this );
+}
+
+void VCLXTimeField::setTime( const util::Time& aTime )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TimeField > pTimeField = GetAs< TimeField >();
+ if ( pTimeField )
+ {
+ pTimeField->SetTime( aTime );
+
+ // #107218# Call same listeners like VCL would do after user interaction
+ SetSynthesizingVCLEvent( true );
+ pTimeField->SetModifyFlag();
+ pTimeField->Modify();
+ SetSynthesizingVCLEvent( false );
+ }
+}
+
+util::Time VCLXTimeField::getTime()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TimeField > pTimeField = GetAs< TimeField >();
+ if ( pTimeField )
+ return pTimeField->GetTime().GetUNOTime();
+ else
+ return util::Time();
+}
+
+void VCLXTimeField::setMin( const util::Time& aTime )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TimeField > pTimeField = GetAs< TimeField >();
+ if ( pTimeField )
+ pTimeField->SetMin( aTime );
+}
+
+util::Time VCLXTimeField::getMin()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TimeField > pTimeField = GetAs< TimeField >();
+ if ( pTimeField )
+ return pTimeField->GetMin().GetUNOTime();
+ else
+ return util::Time();
+}
+
+void VCLXTimeField::setMax( const util::Time& aTime )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TimeField > pTimeField = GetAs< TimeField >();
+ if ( pTimeField )
+ pTimeField->SetMax( aTime );
+}
+
+util::Time VCLXTimeField::getMax()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TimeField > pTimeField = GetAs< TimeField >();
+ if ( pTimeField )
+ return pTimeField->GetMax().GetUNOTime();
+ else
+ return util::Time();
+}
+
+void VCLXTimeField::setFirst( const util::Time& aTime )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TimeField > pTimeField = GetAs< TimeField >();
+ if ( pTimeField )
+ pTimeField->SetFirst( aTime );
+}
+
+util::Time VCLXTimeField::getFirst()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TimeField > pTimeField = GetAs< TimeField >();
+ if ( pTimeField )
+ return pTimeField->GetFirst().GetUNOTime();
+ else
+ return util::Time();
+}
+
+void VCLXTimeField::setLast( const util::Time& aTime )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TimeField > pTimeField = GetAs< TimeField >();
+ if ( pTimeField )
+ pTimeField->SetLast( aTime );
+}
+
+util::Time VCLXTimeField::getLast()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TimeField > pTimeField = GetAs< TimeField >();
+ if ( pTimeField )
+ return pTimeField->GetLast().GetUNOTime();
+ else
+ return util::Time();
+}
+
+void VCLXTimeField::setEmpty()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TimeField > pTimeField = GetAs< TimeField >();
+ if ( pTimeField )
+ pTimeField->SetEmptyTime();
+}
+
+sal_Bool VCLXTimeField::isEmpty()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TimeField > pTimeField = GetAs< TimeField >();
+ return pTimeField && pTimeField->IsEmptyTime();
+}
+
+void VCLXTimeField::setStrictFormat( sal_Bool bStrict )
+{
+ VCLXFormattedSpinField::setStrictFormat( bStrict );
+}
+
+sal_Bool VCLXTimeField::isStrictFormat()
+{
+ return VCLXFormattedSpinField::isStrictFormat();
+}
+
+
+void VCLXTimeField::setProperty( const OUString& PropertyName, const css::uno::Any& Value)
+{
+ SolarMutexGuard aGuard;
+
+ if ( !(GetWindow()) )
+ return;
+
+ bool bVoid = Value.getValueType().getTypeClass() == css::uno::TypeClass_VOID;
+
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_TIME:
+ {
+ if ( bVoid )
+ {
+ GetAs< TimeField >()->EnableEmptyFieldValue( true );
+ GetAs< TimeField >()->SetEmptyFieldValue();
+ }
+ else
+ {
+ util::Time t;
+ if ( Value >>= t )
+ setTime( t );
+ }
+ }
+ break;
+ case BASEPROPERTY_TIMEMIN:
+ {
+ util::Time t;
+ if ( Value >>= t )
+ setMin( t );
+ }
+ break;
+ case BASEPROPERTY_TIMEMAX:
+ {
+ util::Time t;
+ if ( Value >>= t )
+ setMax( t );
+ }
+ break;
+ case BASEPROPERTY_EXTTIMEFORMAT:
+ {
+ sal_Int16 n = sal_Int16();
+ if ( Value >>= n )
+ GetAs< TimeField >()->SetExtFormat( static_cast<ExtTimeFieldFormat>(n) );
+ }
+ break;
+ case BASEPROPERTY_ENFORCE_FORMAT:
+ {
+ bool bEnforce( true );
+ OSL_VERIFY( Value >>= bEnforce );
+ GetAs< TimeField >()->EnforceValidValue( bEnforce );
+ }
+ break;
+ default:
+ {
+ VCLXFormattedSpinField::setProperty( PropertyName, Value );
+ }
+ }
+}
+
+css::uno::Any VCLXTimeField::getProperty( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Any aProp;
+ if ( GetWindow() )
+ {
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_TIME:
+ {
+ aProp <<= getTime();
+ }
+ break;
+ case BASEPROPERTY_TIMEMIN:
+ {
+ aProp <<= getMin();
+ }
+ break;
+ case BASEPROPERTY_TIMEMAX:
+ {
+ aProp <<= getMax();
+ }
+ break;
+ case BASEPROPERTY_ENFORCE_FORMAT:
+ {
+ aProp <<= GetAs< TimeField >()->IsEnforceValidValue( );
+ }
+ break;
+ default:
+ {
+ aProp = VCLXFormattedSpinField::getProperty( PropertyName );
+ }
+ }
+ }
+ return aProp;
+}
+
+
+
+
+void VCLXNumericField::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ BASEPROPERTY_ALIGN,
+ BASEPROPERTY_BACKGROUNDCOLOR,
+ BASEPROPERTY_BORDER,
+ BASEPROPERTY_BORDERCOLOR,
+ BASEPROPERTY_DECIMALACCURACY,
+ BASEPROPERTY_DEFAULTCONTROL,
+ BASEPROPERTY_ENABLED,
+ BASEPROPERTY_ENABLEVISIBLE,
+ BASEPROPERTY_FONTDESCRIPTOR,
+ BASEPROPERTY_HELPTEXT,
+ BASEPROPERTY_HELPURL,
+ BASEPROPERTY_NUMSHOWTHOUSANDSEP,
+ BASEPROPERTY_PRINTABLE,
+ BASEPROPERTY_READONLY,
+ BASEPROPERTY_REPEAT,
+ BASEPROPERTY_REPEAT_DELAY,
+ BASEPROPERTY_SPIN,
+ BASEPROPERTY_STRICTFORMAT,
+ BASEPROPERTY_TABSTOP,
+ BASEPROPERTY_VALUEMAX_DOUBLE,
+ BASEPROPERTY_VALUEMIN_DOUBLE,
+ BASEPROPERTY_VALUESTEP_DOUBLE,
+ BASEPROPERTY_VALUE_DOUBLE,
+ BASEPROPERTY_ENFORCE_FORMAT,
+ BASEPROPERTY_HIDEINACTIVESELECTION,
+ BASEPROPERTY_VERTICALALIGN,
+ BASEPROPERTY_WRITING_MODE,
+ BASEPROPERTY_CONTEXT_WRITING_MODE,
+ BASEPROPERTY_MOUSE_WHEEL_BEHAVIOUR,
+ BASEPROPERTY_HIGHLIGHT_COLOR,
+ BASEPROPERTY_HIGHLIGHT_TEXT_COLOR,
+ 0);
+ VCLXFormattedSpinField::ImplGetPropertyIds( rIds );
+}
+
+VCLXNumericField::VCLXNumericField()
+{
+}
+
+VCLXNumericField::~VCLXNumericField()
+{
+}
+
+void VCLXNumericField::setValue( double Value )
+{
+ SolarMutexGuard aGuard;
+
+ NumericFormatter* pNumericFormatter = static_cast<NumericFormatter*>(GetFormatter());
+ if ( !pNumericFormatter )
+ return;
+
+ // shift long value using decimal digits
+ // (e.g., input 105 using 2 digits returns 1,05)
+ // Thus, to set a value of 1,05, insert 105 and 2 digits
+ pNumericFormatter->SetValue(
+ static_cast<tools::Long>(ImplCalcLongValue( Value, pNumericFormatter->GetDecimalDigits() )) );
+
+ // #107218# Call same listeners like VCL would do after user interaction
+ VclPtr< Edit > pEdit = GetAs< Edit >();
+ if ( pEdit )
+ {
+ SetSynthesizingVCLEvent( true );
+ pEdit->SetModifyFlag();
+ pEdit->Modify();
+ SetSynthesizingVCLEvent( false );
+ }
+}
+
+double VCLXNumericField::getValue()
+{
+ SolarMutexGuard aGuard;
+
+ NumericFormatter* pNumericFormatter = static_cast<NumericFormatter*>(GetFormatter());
+ return pNumericFormatter
+ ? ImplCalcDoubleValue( static_cast<double>(pNumericFormatter->GetValue()), pNumericFormatter->GetDecimalDigits() )
+ : 0;
+}
+
+void VCLXNumericField::setMin( double Value )
+{
+ SolarMutexGuard aGuard;
+
+ NumericFormatter* pNumericFormatter = static_cast<NumericFormatter*>(GetFormatter());
+ if ( pNumericFormatter )
+ pNumericFormatter->SetMin(
+ static_cast<tools::Long>(ImplCalcLongValue( Value, pNumericFormatter->GetDecimalDigits() )) );
+}
+
+double VCLXNumericField::getMin()
+{
+ SolarMutexGuard aGuard;
+
+ NumericFormatter* pNumericFormatter = static_cast<NumericFormatter*>(GetFormatter());
+ return pNumericFormatter
+ ? ImplCalcDoubleValue( static_cast<double>(pNumericFormatter->GetMin()), pNumericFormatter->GetDecimalDigits() )
+ : 0;
+}
+
+void VCLXNumericField::setMax( double Value )
+{
+ SolarMutexGuard aGuard;
+
+ NumericFormatter* pNumericFormatter = static_cast<NumericFormatter*>(GetFormatter());
+ if ( pNumericFormatter )
+ pNumericFormatter->SetMax(
+ static_cast<tools::Long>(ImplCalcLongValue( Value, pNumericFormatter->GetDecimalDigits() )) );
+}
+
+double VCLXNumericField::getMax()
+{
+ SolarMutexGuard aGuard;
+
+ NumericFormatter* pNumericFormatter = static_cast<NumericFormatter*>(GetFormatter());
+ return pNumericFormatter
+ ? ImplCalcDoubleValue( static_cast<double>(pNumericFormatter->GetMax()), pNumericFormatter->GetDecimalDigits() )
+ : 0;
+}
+
+void VCLXNumericField::setFirst( double Value )
+{
+ SolarMutexGuard aGuard;
+
+ NumericFormatter* pNumericFormatter = static_cast<NumericFormatter*>(GetFormatter());
+ if ( pNumericFormatter )
+ pNumericFormatter->SetFirst(
+ static_cast<tools::Long>(ImplCalcLongValue( Value, pNumericFormatter->GetDecimalDigits() )) );
+}
+
+double VCLXNumericField::getFirst()
+{
+ SolarMutexGuard aGuard;
+
+ NumericFormatter* pNumericFormatter = static_cast<NumericFormatter*>(GetFormatter());
+ return pNumericFormatter
+ ? ImplCalcDoubleValue( static_cast<double>(pNumericFormatter->GetFirst()), pNumericFormatter->GetDecimalDigits() )
+ : 0;
+}
+
+void VCLXNumericField::setLast( double Value )
+{
+ SolarMutexGuard aGuard;
+
+ NumericFormatter* pNumericFormatter = static_cast<NumericFormatter*>(GetFormatter());
+ if ( pNumericFormatter )
+ pNumericFormatter->SetLast(
+ static_cast<tools::Long>(ImplCalcLongValue( Value, pNumericFormatter->GetDecimalDigits() )) );
+}
+
+double VCLXNumericField::getLast()
+{
+ SolarMutexGuard aGuard;
+
+ NumericFormatter* pNumericFormatter = static_cast<NumericFormatter*>(GetFormatter());
+ return pNumericFormatter
+ ? ImplCalcDoubleValue( static_cast<double>(pNumericFormatter->GetLast()), pNumericFormatter->GetDecimalDigits() )
+ : 0;
+}
+
+void VCLXNumericField::setStrictFormat( sal_Bool bStrict )
+{
+ VCLXFormattedSpinField::setStrictFormat( bStrict );
+}
+
+sal_Bool VCLXNumericField::isStrictFormat()
+{
+ return VCLXFormattedSpinField::isStrictFormat();
+}
+
+void VCLXNumericField::setSpinSize( double Value )
+{
+ SolarMutexGuard aGuard;
+
+ NumericFormatter* pNumericFormatter = static_cast<NumericFormatter*>(GetFormatter());
+ if ( pNumericFormatter )
+ pNumericFormatter->SetSpinSize(
+ static_cast<tools::Long>(ImplCalcLongValue( Value, pNumericFormatter->GetDecimalDigits() )) );
+}
+
+double VCLXNumericField::getSpinSize()
+{
+ SolarMutexGuard aGuard;
+
+ NumericFormatter* pNumericFormatter = static_cast<NumericFormatter*>(GetFormatter());
+ return pNumericFormatter
+ ? ImplCalcDoubleValue( static_cast<double>(pNumericFormatter->GetSpinSize()), pNumericFormatter->GetDecimalDigits() )
+ : 0;
+}
+
+void VCLXNumericField::setDecimalDigits( sal_Int16 Value )
+{
+ SolarMutexGuard aGuard;
+
+ NumericFormatter* pNumericFormatter = static_cast<NumericFormatter*>(GetFormatter());
+ if ( pNumericFormatter )
+ {
+ double n = getValue();
+ pNumericFormatter->SetDecimalDigits( Value );
+ setValue( n );
+ }
+}
+
+sal_Int16 VCLXNumericField::getDecimalDigits()
+{
+ SolarMutexGuard aGuard;
+
+ NumericFormatter* pNumericFormatter = static_cast<NumericFormatter*>(GetFormatter());
+ return pNumericFormatter ? pNumericFormatter->GetDecimalDigits() : 0;
+}
+
+void VCLXNumericField::setProperty( const OUString& PropertyName, const css::uno::Any& Value)
+{
+ SolarMutexGuard aGuard;
+
+ if ( !(GetWindow()) )
+ return;
+
+ bool bVoid = Value.getValueType().getTypeClass() == css::uno::TypeClass_VOID;
+
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_VALUE_DOUBLE:
+ {
+ if ( bVoid )
+ {
+ NumericFormatter* pNumericFormatter = static_cast<NumericFormatter*>(GetFormatter());
+ if (!pNumericFormatter)
+ return;
+ pNumericFormatter->EnableEmptyFieldValue( true );
+ pNumericFormatter->SetEmptyFieldValue();
+ }
+ else
+ {
+ double d = 0;
+ if ( Value >>= d )
+ setValue( d );
+ }
+ }
+ break;
+ case BASEPROPERTY_VALUEMIN_DOUBLE:
+ {
+ double d = 0;
+ if ( Value >>= d )
+ setMin( d );
+ }
+ break;
+ case BASEPROPERTY_VALUEMAX_DOUBLE:
+ {
+ double d = 0;
+ if ( Value >>= d )
+ setMax( d );
+ }
+ break;
+ case BASEPROPERTY_VALUESTEP_DOUBLE:
+ {
+ double d = 0;
+ if ( Value >>= d )
+ setSpinSize( d );
+ }
+ break;
+ case BASEPROPERTY_DECIMALACCURACY:
+ {
+ sal_Int16 n = sal_Int16();
+ if ( Value >>= n )
+ setDecimalDigits( n );
+ }
+ break;
+ case BASEPROPERTY_NUMSHOWTHOUSANDSEP:
+ {
+ bool b = bool();
+ if ( Value >>= b )
+ {
+ NumericFormatter* pNumericFormatter = static_cast<NumericFormatter*>(GetFormatter());
+ if (!pNumericFormatter)
+ return;
+ pNumericFormatter->SetUseThousandSep( b );
+ }
+ }
+ break;
+ default:
+ {
+ VCLXFormattedSpinField::setProperty( PropertyName, Value );
+ }
+ }
+}
+
+css::uno::Any VCLXNumericField::getProperty( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Any aProp;
+ FormatterBase* pFormatter = GetFormatter();
+ if ( pFormatter )
+ {
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_VALUE_DOUBLE:
+ {
+ aProp <<= getValue();
+ }
+ break;
+ case BASEPROPERTY_VALUEMIN_DOUBLE:
+ {
+ aProp <<= getMin();
+ }
+ break;
+ case BASEPROPERTY_VALUEMAX_DOUBLE:
+ {
+ aProp <<= getMax();
+ }
+ break;
+ case BASEPROPERTY_VALUESTEP_DOUBLE:
+ {
+ aProp <<= getSpinSize();
+ }
+ break;
+ case BASEPROPERTY_NUMSHOWTHOUSANDSEP:
+ {
+ NumericFormatter* pNumericFormatter = static_cast<NumericFormatter*>(pFormatter);
+ aProp <<= pNumericFormatter->IsUseThousandSep();
+ }
+ break;
+ default:
+ {
+ aProp = VCLXFormattedSpinField::getProperty( PropertyName );
+ }
+ }
+ }
+ return aProp;
+}
+
+
+// ----------------------------------------------------
+// ----------------------------------------------------
+
+void VCLXMetricField::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ BASEPROPERTY_ALIGN,
+ BASEPROPERTY_BACKGROUNDCOLOR,
+ BASEPROPERTY_BORDER,
+ BASEPROPERTY_BORDERCOLOR,
+ BASEPROPERTY_DECIMALACCURACY,
+ BASEPROPERTY_DEFAULTCONTROL,
+ BASEPROPERTY_ENABLED,
+ BASEPROPERTY_ENABLEVISIBLE,
+ BASEPROPERTY_FONTDESCRIPTOR,
+ BASEPROPERTY_HELPTEXT,
+ BASEPROPERTY_HELPURL,
+ BASEPROPERTY_NUMSHOWTHOUSANDSEP,
+ BASEPROPERTY_PRINTABLE,
+ BASEPROPERTY_READONLY,
+ BASEPROPERTY_REPEAT,
+ BASEPROPERTY_REPEAT_DELAY,
+ BASEPROPERTY_SPIN,
+ BASEPROPERTY_STRICTFORMAT,
+ BASEPROPERTY_TABSTOP,
+ BASEPROPERTY_ENFORCE_FORMAT,
+ BASEPROPERTY_HIDEINACTIVESELECTION,
+ BASEPROPERTY_UNIT,
+ BASEPROPERTY_CUSTOMUNITTEXT,
+ BASEPROPERTY_WRITING_MODE,
+ BASEPROPERTY_CONTEXT_WRITING_MODE,
+ BASEPROPERTY_MOUSE_WHEEL_BEHAVIOUR,
+ 0);
+ VCLXFormattedSpinField::ImplGetPropertyIds( rIds );
+}
+
+VCLXMetricField::VCLXMetricField()
+{
+}
+
+VCLXMetricField::~VCLXMetricField()
+{
+}
+
+MetricFormatter *VCLXMetricField::GetMetricFormatter()
+{
+ MetricFormatter *pFormatter = static_cast<MetricFormatter *>(GetFormatter());
+ if (!pFormatter)
+ throw css::uno::RuntimeException();
+ return pFormatter;
+}
+
+MetricField *VCLXMetricField::GetMetricField()
+{
+ VclPtr< MetricField > pField = GetAs< MetricField >();
+ if (!pField)
+ throw css::uno::RuntimeException();
+ return pField;
+}
+
+// FIXME: later ...
+#define MetricUnitUnoToVcl(a) (static_cast<FieldUnit>(a))
+
+#define METRIC_MAP_PAIR(method,parent) \
+ sal_Int64 VCLXMetricField::get##method( sal_Int16 nUnit ) \
+ { \
+ SolarMutexGuard aGuard; \
+ return GetMetric##parent()->Get##method( MetricUnitUnoToVcl( nUnit ) ); \
+ } \
+ void VCLXMetricField::set##method( sal_Int64 nValue, sal_Int16 nUnit ) \
+ { \
+ SolarMutexGuard aGuard; \
+ GetMetric##parent()->Set##method( nValue, MetricUnitUnoToVcl( nUnit ) ); \
+ }
+
+METRIC_MAP_PAIR(Min, Formatter)
+METRIC_MAP_PAIR(Max, Formatter)
+METRIC_MAP_PAIR(First, Field)
+METRIC_MAP_PAIR(Last, Field)
+
+#undef METRIC_MAP_PAIR
+
+::sal_Int64 VCLXMetricField::getValue( ::sal_Int16 nUnit )
+{
+ SolarMutexGuard aGuard;
+ return GetMetricFormatter()->GetValue( MetricUnitUnoToVcl( nUnit ) );
+}
+
+::sal_Int64 VCLXMetricField::getCorrectedValue( ::sal_Int16 nUnit )
+{
+ SolarMutexGuard aGuard;
+ return GetMetricFormatter()->GetCorrectedValue( MetricUnitUnoToVcl( nUnit ) );
+}
+
+// FIXME: acute cut/paste evilness - move this to the parent Edit class ?
+void VCLXMetricField::CallListeners()
+{
+ // #107218# Call same listeners like VCL would do after user interaction
+ VclPtr< Edit > pEdit = GetAs< Edit >();
+ if ( pEdit )
+ {
+ SetSynthesizingVCLEvent( true );
+ pEdit->SetModifyFlag();
+ pEdit->Modify();
+ SetSynthesizingVCLEvent( false );
+ }
+}
+
+void VCLXMetricField::setValue( ::sal_Int64 Value, ::sal_Int16 Unit )
+{
+ SolarMutexGuard aGuard;
+ GetMetricFormatter()->SetValue( Value, MetricUnitUnoToVcl( Unit ) );
+ CallListeners();
+}
+
+void VCLXMetricField::setUserValue( ::sal_Int64 Value, ::sal_Int16 Unit )
+{
+ SolarMutexGuard aGuard;
+ GetMetricFormatter()->SetUserValue( Value, MetricUnitUnoToVcl( Unit ) );
+ CallListeners();
+}
+
+void VCLXMetricField::setStrictFormat( sal_Bool bStrict )
+{
+ VCLXFormattedSpinField::setStrictFormat( bStrict );
+}
+
+sal_Bool VCLXMetricField::isStrictFormat()
+{
+ return VCLXFormattedSpinField::isStrictFormat();
+}
+
+void VCLXMetricField::setSpinSize( sal_Int64 Value )
+{
+ SolarMutexGuard aGuard;
+ GetMetricField()->SetSpinSize( Value );
+}
+
+sal_Int64 VCLXMetricField::getSpinSize()
+{
+ SolarMutexGuard aGuard;
+ return GetMetricField()->GetSpinSize();
+}
+
+void VCLXMetricField::setDecimalDigits( sal_Int16 Value )
+{
+ SolarMutexGuard aGuard;
+ GetMetricFormatter()->SetDecimalDigits( Value );
+}
+
+sal_Int16 VCLXMetricField::getDecimalDigits()
+{
+ SolarMutexGuard aGuard;
+
+ NumericFormatter* pNumericFormatter = static_cast<NumericFormatter*>(GetFormatter());
+ return pNumericFormatter ? pNumericFormatter->GetDecimalDigits() : 0;
+}
+
+void VCLXMetricField::setProperty( const OUString& PropertyName, const css::uno::Any& Value)
+{
+ SolarMutexGuard aGuard;
+
+ if ( !(GetWindow()) )
+ return;
+
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_DECIMALACCURACY:
+ {
+ sal_Int16 n = 0;
+ if ( Value >>= n )
+ setDecimalDigits( n );
+ break;
+ }
+ case BASEPROPERTY_NUMSHOWTHOUSANDSEP:
+ {
+ bool b = false;
+ if ( Value >>= b )
+ {
+ NumericFormatter* pNumericFormatter = static_cast<NumericFormatter*>(GetFormatter());
+ if (!pNumericFormatter)
+ return;
+ pNumericFormatter->SetUseThousandSep( b );
+ }
+ }
+ break;
+ case BASEPROPERTY_UNIT:
+ {
+ sal_uInt16 nVal = 0;
+ if ( Value >>= nVal )
+ GetAs< MetricField >()->SetUnit( static_cast<FieldUnit>(nVal) );
+ break;
+ }
+ case BASEPROPERTY_CUSTOMUNITTEXT:
+ {
+ OUString aStr;
+ if ( Value >>= aStr )
+ GetAs< MetricField >()->SetCustomUnitText( aStr );
+ break;
+ }
+ default:
+ {
+ VCLXFormattedSpinField::setProperty( PropertyName, Value );
+ break;
+ }
+ }
+}
+
+css::uno::Any VCLXMetricField::getProperty( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Any aProp;
+ FormatterBase* pFormatter = GetFormatter();
+ if ( pFormatter )
+ {
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_NUMSHOWTHOUSANDSEP:
+ {
+ NumericFormatter* pNumericFormatter = static_cast<NumericFormatter*>(pFormatter);
+ aProp <<= pNumericFormatter->IsUseThousandSep();
+ break;
+ }
+ case BASEPROPERTY_UNIT:
+ aProp <<= static_cast<sal_uInt16>(GetAs< MetricField >()->GetUnit());
+ break;
+ case BASEPROPERTY_CUSTOMUNITTEXT:
+ aProp <<= GetAs< MetricField >()->GetCustomUnitText();
+ break;
+ default:
+ {
+ aProp = VCLXFormattedSpinField::getProperty( PropertyName );
+ break;
+ }
+ }
+ }
+ return aProp;
+}
+
+void VCLXPatternField::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ BASEPROPERTY_ALIGN,
+ BASEPROPERTY_BACKGROUNDCOLOR,
+ BASEPROPERTY_BORDER,
+ BASEPROPERTY_BORDERCOLOR,
+ BASEPROPERTY_DEFAULTCONTROL,
+ BASEPROPERTY_EDITMASK,
+ BASEPROPERTY_ENABLED,
+ BASEPROPERTY_ENABLEVISIBLE,
+ BASEPROPERTY_FONTDESCRIPTOR,
+ BASEPROPERTY_HELPTEXT,
+ BASEPROPERTY_HELPURL,
+ BASEPROPERTY_LITERALMASK,
+ BASEPROPERTY_MAXTEXTLEN,
+ BASEPROPERTY_PRINTABLE,
+ BASEPROPERTY_READONLY,
+ BASEPROPERTY_STRICTFORMAT,
+ BASEPROPERTY_TABSTOP,
+ BASEPROPERTY_TEXT,
+ BASEPROPERTY_HIDEINACTIVESELECTION,
+ BASEPROPERTY_VERTICALALIGN,
+ BASEPROPERTY_WRITING_MODE,
+ BASEPROPERTY_CONTEXT_WRITING_MODE,
+ BASEPROPERTY_MOUSE_WHEEL_BEHAVIOUR,
+ BASEPROPERTY_HIGHLIGHT_COLOR,
+ BASEPROPERTY_HIGHLIGHT_TEXT_COLOR,
+ 0);
+ VCLXFormattedSpinField::ImplGetPropertyIds( rIds );
+}
+
+VCLXPatternField::VCLXPatternField()
+{
+}
+
+VCLXPatternField::~VCLXPatternField()
+{
+}
+
+void VCLXPatternField::setMasks( const OUString& EditMask, const OUString& LiteralMask )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< PatternField > pPatternField = GetAs< PatternField >();
+ if ( pPatternField )
+ {
+ pPatternField->SetMask( OUStringToOString(EditMask, RTL_TEXTENCODING_ASCII_US), LiteralMask );
+ }
+}
+
+void VCLXPatternField::getMasks( OUString& EditMask, OUString& LiteralMask )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< PatternField > pPatternField = GetAs< PatternField >();
+ if ( pPatternField )
+ {
+ EditMask = OStringToOUString(pPatternField->GetEditMask(), RTL_TEXTENCODING_ASCII_US);
+ LiteralMask = pPatternField->GetLiteralMask();
+ }
+}
+
+void VCLXPatternField::setString( const OUString& Str )
+{
+ SolarMutexGuard aGuard;
+ VclPtr< PatternField > pPatternField = GetAs< PatternField >();
+ if ( pPatternField )
+ pPatternField->SetString( Str );
+}
+
+OUString VCLXPatternField::getString()
+{
+ SolarMutexGuard aGuard;
+
+ OUString aString;
+ VclPtr< PatternField > pPatternField = GetAs< PatternField >();
+ if ( pPatternField )
+ aString = pPatternField->GetString();
+ return aString;
+}
+
+void VCLXPatternField::setStrictFormat( sal_Bool bStrict )
+{
+ VCLXFormattedSpinField::setStrictFormat( bStrict );
+}
+
+sal_Bool VCLXPatternField::isStrictFormat()
+{
+ return VCLXFormattedSpinField::isStrictFormat();
+}
+
+void VCLXPatternField::setProperty( const OUString& PropertyName, const css::uno::Any& Value)
+{
+ SolarMutexGuard aGuard;
+
+ if ( !(GetWindow()) )
+ return;
+
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_EDITMASK:
+ case BASEPROPERTY_LITERALMASK:
+ {
+ OUString aString;
+ if ( Value >>= aString )
+ {
+ OUString aEditMask, aLiteralMask;
+ getMasks( aEditMask, aLiteralMask );
+ if ( nPropType == BASEPROPERTY_EDITMASK )
+ aEditMask = aString;
+ else
+ aLiteralMask = aString;
+ setMasks( aEditMask, aLiteralMask );
+ }
+ }
+ break;
+ default:
+ {
+ VCLXFormattedSpinField::setProperty( PropertyName, Value );
+ }
+ }
+}
+
+css::uno::Any VCLXPatternField::getProperty( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Any aProp;
+ if ( GetWindow() )
+ {
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_EDITMASK:
+ case BASEPROPERTY_LITERALMASK:
+ {
+ OUString aEditMask, aLiteralMask;
+ getMasks( aEditMask, aLiteralMask );
+ if ( nPropType == BASEPROPERTY_EDITMASK )
+ aProp <<= aEditMask;
+ else
+ aProp <<= aLiteralMask;
+ }
+ break;
+ default:
+ {
+ aProp = VCLXFormattedSpinField::getProperty( PropertyName );
+ }
+ }
+ }
+ return aProp;
+}
+
+
+
+VCLXToolBox::VCLXToolBox()
+{
+}
+
+VCLXToolBox::~VCLXToolBox()
+{
+}
+
+css::uno::Reference< css::accessibility::XAccessibleContext > VCLXToolBox::CreateAccessibleContext()
+{
+ return getAccessibleFactory().createAccessibleContext( this );
+}
+
+VCLXHeaderBar::VCLXHeaderBar()
+{
+}
+
+VCLXHeaderBar::~VCLXHeaderBar()
+{
+}
+
+css::uno::Reference< css::accessibility::XAccessibleContext > VCLXHeaderBar::CreateAccessibleContext()
+{
+ return getAccessibleFactory().createAccessibleContext( this );
+}
+
+
+VCLXFrame::VCLXFrame()
+{
+}
+
+void VCLXFrame::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ BASEPROPERTY_BACKGROUNDCOLOR,
+ BASEPROPERTY_DEFAULTCONTROL,
+ BASEPROPERTY_ENABLED,
+ BASEPROPERTY_ENABLEVISIBLE,
+ BASEPROPERTY_FONTDESCRIPTOR,
+ BASEPROPERTY_GRAPHIC,
+ BASEPROPERTY_HELPTEXT,
+ BASEPROPERTY_HELPURL,
+ BASEPROPERTY_PRINTABLE,
+ BASEPROPERTY_LABEL,
+ 0);
+ VCLXContainer::ImplGetPropertyIds( rIds );
+}
+
+VCLXFrame::~VCLXFrame()
+{
+}
+
+// css::awt::XView
+void SAL_CALL VCLXFrame::draw( sal_Int32 nX, sal_Int32 nY )
+{
+ SolarMutexGuard aGuard;
+ VclPtr< vcl::Window > pWindow = GetWindow();
+
+ if ( pWindow )
+ {
+ OutputDevice* pDev = VCLUnoHelper::GetOutputDevice( getGraphics() );
+ if ( !pDev )
+ pDev = pWindow->GetParent()->GetOutDev();
+
+ Point aPos = pDev->PixelToLogic( Point( nX, nY ) );
+ pWindow->Draw( pDev, aPos, SystemTextColorFlags::NoControls );
+ }
+}
+
+void SAL_CALL VCLXFrame::setProperty(
+ const OUString& PropertyName,
+ const css::uno::Any& Value )
+{
+ SolarMutexGuard aGuard;
+
+ VCLXContainer::setProperty( PropertyName, Value );
+}
+
+void VCLXFrame::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ css::uno::Reference< css::awt::XWindow > xKeepAlive( this );
+ VCLXContainer::ProcessWindowEvent( rVclWindowEvent );
+}
+
+VCLXProgressBar::VCLXProgressBar()
+ :m_nValue(0)
+ ,m_nValueMin(0)
+ ,m_nValueMax(100)
+{
+}
+
+VCLXProgressBar::~VCLXProgressBar()
+{
+}
+
+void VCLXProgressBar::ImplUpdateValue()
+{
+ VclPtr< ProgressBar > pProgressBar = GetAs< ProgressBar >();
+ if ( !pProgressBar )
+ return;
+
+ sal_Int32 nVal;
+ sal_Int32 nValMin;
+ sal_Int32 nValMax;
+
+ // check min and max
+ if (m_nValueMin < m_nValueMax)
+ {
+ nValMin = m_nValueMin;
+ nValMax = m_nValueMax;
+ }
+ else
+ {
+ nValMin = m_nValueMax;
+ nValMax = m_nValueMin;
+ }
+
+ // check value
+ if (m_nValue < nValMin)
+ {
+ nVal = nValMin;
+ }
+ else if (m_nValue > nValMax)
+ {
+ nVal = nValMax;
+ }
+ else
+ {
+ nVal = m_nValue;
+ }
+
+ // calculate percent
+ sal_Int32 nPercent;
+ if (nValMin != nValMax)
+ {
+ nPercent = 100 * (nVal - nValMin) / (nValMax - nValMin);
+ }
+ else
+ {
+ nPercent = 0;
+ }
+
+ // set progressbar value
+ pProgressBar->SetValue( static_cast<sal_uInt16>(nPercent) );
+}
+
+// css::awt::XProgressBar
+void VCLXProgressBar::setForegroundColor( sal_Int32 nColor )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ pWindow->SetControlForeground( Color(ColorTransparency, nColor) );
+ }
+}
+
+void VCLXProgressBar::setBackgroundColor( sal_Int32 nColor )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ Color aColor( ColorTransparency, nColor );
+ pWindow->SetBackground( aColor );
+ pWindow->SetControlBackground( aColor );
+ pWindow->Invalidate();
+ }
+}
+
+void VCLXProgressBar::setValue( sal_Int32 nValue )
+{
+ SolarMutexGuard aGuard;
+
+ m_nValue = nValue;
+ ImplUpdateValue();
+}
+
+void VCLXProgressBar::setRange( sal_Int32 nMin, sal_Int32 nMax )
+{
+ SolarMutexGuard aGuard;
+
+ if ( nMin < nMax )
+ {
+ // take correct min and max
+ m_nValueMin = nMin;
+ m_nValueMax = nMax;
+ }
+ else
+ {
+ // change min and max
+ m_nValueMin = nMax;
+ m_nValueMax = nMin;
+ }
+
+ ImplUpdateValue();
+}
+
+sal_Int32 VCLXProgressBar::getValue()
+{
+ SolarMutexGuard aGuard;
+
+ return m_nValue;
+}
+
+// css::awt::VclWindowPeer
+void VCLXProgressBar::setProperty( const OUString& PropertyName, const css::uno::Any& Value)
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< ProgressBar > pProgressBar = GetAs< ProgressBar >();
+ if ( !pProgressBar )
+ return;
+
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_PROGRESSVALUE:
+ {
+ if ( Value >>= m_nValue )
+ ImplUpdateValue();
+ }
+ break;
+ case BASEPROPERTY_PROGRESSVALUE_MIN:
+ {
+ if ( Value >>= m_nValueMin )
+ ImplUpdateValue();
+ }
+ break;
+ case BASEPROPERTY_PROGRESSVALUE_MAX:
+ {
+ if ( Value >>= m_nValueMax )
+ ImplUpdateValue();
+ }
+ break;
+ case BASEPROPERTY_FILLCOLOR:
+ {
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ bool bVoid = Value.getValueType().getTypeClass() == css::uno::TypeClass_VOID;
+
+ if ( bVoid )
+ {
+ pWindow->SetControlForeground();
+ }
+ else
+ {
+ Color nColor;
+ if ( Value >>= nColor )
+ pWindow->SetControlForeground( nColor );
+ }
+ }
+ }
+ break;
+ default:
+ VCLXWindow::setProperty( PropertyName, Value );
+ break;
+ }
+}
+
+css::uno::Any VCLXProgressBar::getProperty( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Any aProp;
+ VclPtr< ProgressBar > pProgressBar = GetAs< ProgressBar >();
+ if ( pProgressBar )
+ {
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_PROGRESSVALUE:
+ {
+ aProp <<= m_nValue;
+ }
+ break;
+ case BASEPROPERTY_PROGRESSVALUE_MIN:
+ {
+ aProp <<= m_nValueMin;
+ }
+ break;
+ case BASEPROPERTY_PROGRESSVALUE_MAX:
+ {
+ aProp <<= m_nValueMax;
+ }
+ break;
+ default:
+ aProp = VCLXWindow::getProperty( PropertyName );
+ break;
+ }
+ }
+ return aProp;
+}
+
+void VCLXProgressBar::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ BASEPROPERTY_PROGRESSVALUE,
+ BASEPROPERTY_PROGRESSVALUE_MIN,
+ BASEPROPERTY_PROGRESSVALUE_MAX,
+ BASEPROPERTY_FILLCOLOR,
+ 0);
+ VCLXWindow::ImplGetPropertyIds( rIds, true );
+}
+
+VCLXFileControl::VCLXFileControl() : maTextListeners( *this )
+{
+}
+
+VCLXFileControl::~VCLXFileControl()
+{
+ VclPtr< FileControl > pControl = GetAs< FileControl >();
+ if ( pControl )
+ pControl->GetEdit().SetModifyHdl( Link<Edit&,void>() );
+}
+
+namespace
+{
+ void lcl_setWinBits( vcl::Window* _pWindow, WinBits _nBits, bool _bSet )
+ {
+ WinBits nStyle = _pWindow->GetStyle();
+ if ( _bSet )
+ nStyle |= _nBits;
+ else
+ nStyle &= ~_nBits;
+ _pWindow->SetStyle( nStyle );
+ }
+}
+
+void SAL_CALL VCLXFileControl::setProperty( const OUString& PropertyName, const css::uno::Any& Value)
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< FileControl > pControl = GetAs< FileControl >();
+ if ( !pControl )
+ return;
+
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_HIDEINACTIVESELECTION:
+ {
+ bool bValue(false);
+ OSL_VERIFY( Value >>= bValue );
+
+ lcl_setWinBits( pControl, WB_NOHIDESELECTION, !bValue );
+ lcl_setWinBits( &pControl->GetEdit(), WB_NOHIDESELECTION, !bValue );
+ }
+ break;
+
+ default:
+ VCLXWindow::setProperty( PropertyName, Value );
+ break;
+ }
+}
+
+void VCLXFileControl::SetWindow( const VclPtr< vcl::Window > &pWindow )
+{
+ VclPtr< FileControl > pPrevFileControl = GetAsDynamic< FileControl >();
+ if ( pPrevFileControl )
+ pPrevFileControl->SetEditModifyHdl( Link<Edit&,void>() );
+
+ FileControl* pNewFileControl = dynamic_cast<FileControl*>( pWindow.get() );
+ if ( pNewFileControl )
+ pNewFileControl->SetEditModifyHdl( LINK( this, VCLXFileControl, ModifyHdl ) );
+
+ VCLXWindow::SetWindow( pWindow );
+}
+
+void VCLXFileControl::addTextListener( const css::uno::Reference< css::awt::XTextListener > & l )
+{
+ maTextListeners.addInterface( l );
+}
+
+void VCLXFileControl::removeTextListener( const css::uno::Reference< css::awt::XTextListener > & l )
+{
+ maTextListeners.removeInterface( l );
+}
+
+void VCLXFileControl::setText( const OUString& aText )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ pWindow->SetText( aText );
+
+ // also in Java a textChanged is triggered, not in VCL.
+ // css::awt::Toolkit should be JAVA-compliant...
+ ModifyHdl();
+ }
+}
+
+void VCLXFileControl::insertText( const css::awt::Selection& rSel, const OUString& aText )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< FileControl > pFileControl = GetAs< FileControl >();
+ if ( pFileControl )
+ {
+ pFileControl->GetEdit().SetSelection( Selection( rSel.Min, rSel.Max ) );
+ pFileControl->GetEdit().ReplaceSelected( aText );
+ }
+}
+
+OUString VCLXFileControl::getText()
+{
+ SolarMutexGuard aGuard;
+
+ OUString aText;
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ aText = pWindow->GetText();
+ return aText;
+}
+
+OUString VCLXFileControl::getSelectedText()
+{
+ SolarMutexGuard aGuard;
+
+ OUString aText;
+ VclPtr< FileControl > pFileControl = GetAs< FileControl >();
+ if ( pFileControl)
+ aText = pFileControl->GetEdit().GetSelected();
+ return aText;
+
+}
+
+void VCLXFileControl::setSelection( const css::awt::Selection& aSelection )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< FileControl > pFileControl = GetAs< FileControl >();
+ if ( pFileControl )
+ pFileControl->GetEdit().SetSelection( Selection( aSelection.Min, aSelection.Max ) );
+}
+
+css::awt::Selection VCLXFileControl::getSelection()
+{
+ SolarMutexGuard aGuard;
+
+ css::awt::Selection aSel;
+ VclPtr< FileControl > pFileControl = GetAs< FileControl >();
+ if ( pFileControl )
+ {
+ aSel.Min = pFileControl->GetEdit().GetSelection().Min();
+ aSel.Max = pFileControl->GetEdit().GetSelection().Max();
+ }
+ return aSel;
+}
+
+sal_Bool VCLXFileControl::isEditable()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< FileControl > pFileControl = GetAs< FileControl >();
+ return pFileControl && !pFileControl->GetEdit().IsReadOnly() && pFileControl->GetEdit().IsEnabled();
+}
+
+void VCLXFileControl::setEditable( sal_Bool bEditable )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< FileControl > pFileControl = GetAs< FileControl >();
+ if ( pFileControl )
+ pFileControl->GetEdit().SetReadOnly( !bEditable );
+}
+
+void VCLXFileControl::setMaxTextLen( sal_Int16 nLen )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< FileControl > pFileControl = GetAs< FileControl >();
+ if ( pFileControl )
+ pFileControl->GetEdit().SetMaxTextLen( nLen );
+}
+
+sal_Int16 VCLXFileControl::getMaxTextLen()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< FileControl > pFileControl = GetAs< FileControl >();
+ return pFileControl ? pFileControl->GetEdit().GetMaxTextLen() : 0;
+}
+
+
+IMPL_LINK_NOARG(VCLXFileControl, ModifyHdl, Edit&, void)
+{
+ ModifyHdl();
+}
+
+void VCLXFileControl::ModifyHdl()
+{
+ css::awt::TextEvent aEvent;
+ aEvent.Source = getXWeak();
+ maTextListeners.textChanged( aEvent );
+}
+
+css::awt::Size VCLXFileControl::getMinimumSize()
+{
+ SolarMutexGuard aGuard;
+
+ css::awt::Size aSz;
+ VclPtr< FileControl > pControl = GetAs< FileControl >();
+ if ( pControl )
+ {
+ Size aTmpSize = pControl->GetEdit().CalcMinimumSize();
+ aTmpSize.AdjustWidth(pControl->GetButton().CalcMinimumSize().Width() );
+ aSz = AWTSize(pControl->CalcWindowSize( aTmpSize ));
+ }
+ return aSz;
+}
+
+css::awt::Size VCLXFileControl::getPreferredSize()
+{
+ css::awt::Size aSz = getMinimumSize();
+ aSz.Height += 4;
+ return aSz;
+}
+
+css::awt::Size VCLXFileControl::calcAdjustedSize( const css::awt::Size& rNewSize )
+{
+ SolarMutexGuard aGuard;
+
+ css::awt::Size aSz =rNewSize;
+ VclPtr< FileControl > pControl = GetAs< FileControl >();
+ if ( pControl )
+ {
+ css::awt::Size aMinSz = getMinimumSize();
+ if ( aSz.Height != aMinSz.Height )
+ aSz.Height = aMinSz.Height;
+ }
+ return aSz;
+}
+
+css::awt::Size VCLXFileControl::getMinimumSize( sal_Int16 nCols, sal_Int16 )
+{
+ SolarMutexGuard aGuard;
+
+ css::awt::Size aSz;
+ VclPtr< FileControl > pControl = GetAs< FileControl >();
+ if ( pControl )
+ {
+ aSz = AWTSize(pControl->GetEdit().CalcSize( nCols ));
+ aSz.Width += pControl->GetButton().CalcMinimumSize().Width();
+ }
+ return aSz;
+}
+
+void VCLXFileControl::getColumnsAndLines( sal_Int16& nCols, sal_Int16& nLines )
+{
+ SolarMutexGuard aGuard;
+
+ nCols = 0;
+ nLines = 1;
+ VclPtr< FileControl > pControl = GetAs< FileControl >();
+ if ( pControl )
+ nCols = pControl->GetEdit().GetMaxVisChars();
+}
+
+void VCLXFileControl::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ // FIXME: elide duplication ?
+ BASEPROPERTY_HIDEINACTIVESELECTION,
+ 0);
+ VCLXWindow::ImplGetPropertyIds( rIds, true );
+}
+
+SVTXFormattedField::SVTXFormattedField()
+ :bIsStandardSupplier(true)
+ ,nKeyToSetDelayed(-1)
+{
+}
+
+SVTXFormattedField::~SVTXFormattedField()
+{
+}
+
+void SVTXFormattedField::SetWindow( const VclPtr< vcl::Window > &_pWindow )
+{
+ VCLXSpinField::SetWindow(_pWindow);
+ if (GetAs< FormattedField >())
+ GetAs< FormattedField >()->GetFormatter().SetAutoColor(true);
+}
+
+void SVTXFormattedField::setProperty( const OUString& PropertyName, const css::uno::Any& Value)
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if ( pField )
+ {
+ Formatter& rFormatter = pField->GetFormatter();
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch (nPropType)
+ {
+ case BASEPROPERTY_ENFORCE_FORMAT:
+ {
+ bool bEnable( true );
+ if ( Value >>= bEnable )
+ rFormatter.EnableNotANumber( !bEnable );
+ }
+ break;
+
+ case BASEPROPERTY_EFFECTIVE_MIN:
+ case BASEPROPERTY_VALUEMIN_DOUBLE:
+ SetMinValue(Value);
+ break;
+
+ case BASEPROPERTY_EFFECTIVE_MAX:
+ case BASEPROPERTY_VALUEMAX_DOUBLE:
+ SetMaxValue(Value);
+ break;
+
+ case BASEPROPERTY_EFFECTIVE_DEFAULT:
+ SetDefaultValue(Value);
+ break;
+
+ case BASEPROPERTY_TREATASNUMBER:
+ {
+ bool b;
+ if ( Value >>= b )
+ SetTreatAsNumber(b);
+ }
+ break;
+
+ case BASEPROPERTY_FORMATSSUPPLIER:
+ if (!Value.hasValue())
+ setFormatsSupplier(css::uno::Reference< css::util::XNumberFormatsSupplier > (nullptr));
+ else
+ {
+ css::uno::Reference< css::util::XNumberFormatsSupplier > xNFS;
+ if ( Value >>= xNFS )
+ setFormatsSupplier(xNFS);
+ }
+ break;
+ case BASEPROPERTY_FORMATKEY:
+ if (!Value.hasValue())
+ setFormatKey(0);
+ else
+ {
+ sal_Int32 n = 0;
+ if ( Value >>= n )
+ setFormatKey(n);
+ }
+ break;
+
+ case BASEPROPERTY_EFFECTIVE_VALUE:
+ case BASEPROPERTY_VALUE_DOUBLE:
+ {
+ const css::uno::TypeClass rTC = Value.getValueType().getTypeClass();
+ if (rTC != css::uno::TypeClass_STRING)
+ // no string
+ if (rTC != css::uno::TypeClass_DOUBLE)
+ // no double
+ if (Value.hasValue())
+ { // but a value
+ // try if it is something convertible
+ sal_Int32 nValue = 0;
+ if (!(Value >>= nValue))
+ throw css::lang::IllegalArgumentException();
+ SetValue(css::uno::Any(static_cast<double>(nValue)));
+ break;
+ }
+
+ SetValue(Value);
+ }
+ break;
+ case BASEPROPERTY_VALUESTEP_DOUBLE:
+ {
+ double d = 0.0;
+ if ( Value >>= d )
+ rFormatter.SetSpinSize( d );
+ else
+ {
+ sal_Int32 n = 0;
+ if ( Value >>= n )
+ rFormatter.SetSpinSize( n );
+ }
+ }
+ break;
+ case BASEPROPERTY_DECIMALACCURACY:
+ {
+ sal_Int32 n = 0;
+ if ( Value >>= n )
+ rFormatter.SetDecimalDigits( static_cast<sal_uInt16>(n) );
+ }
+ break;
+ case BASEPROPERTY_NUMSHOWTHOUSANDSEP:
+ {
+ bool b;
+ if ( Value >>= b )
+ rFormatter.SetThousandsSep( b );
+ }
+ break;
+
+ default:
+ VCLXSpinField::setProperty( PropertyName, Value );
+ }
+
+ if (BASEPROPERTY_TEXTCOLOR == nPropType)
+ { // after setting a new text color, think again about the AutoColor flag of the control
+ // 17.05.2001 - 86859 - frank.schoenheit@germany.sun.com
+ rFormatter.SetAutoColor(!Value.hasValue());
+ }
+ }
+ else
+ VCLXSpinField::setProperty( PropertyName, Value );
+}
+
+css::uno::Any SVTXFormattedField::getProperty( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Any aReturn;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if ( pField )
+ {
+ Formatter& rFormatter = pField->GetFormatter();
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch (nPropType)
+ {
+ case BASEPROPERTY_EFFECTIVE_MIN:
+ case BASEPROPERTY_VALUEMIN_DOUBLE:
+ aReturn = GetMinValue();
+ break;
+
+ case BASEPROPERTY_EFFECTIVE_MAX:
+ case BASEPROPERTY_VALUEMAX_DOUBLE:
+ aReturn = GetMaxValue();
+ break;
+
+ case BASEPROPERTY_EFFECTIVE_DEFAULT:
+ aReturn = GetDefaultValue();
+ break;
+
+ case BASEPROPERTY_TREATASNUMBER:
+ aReturn <<= GetTreatAsNumber();
+ break;
+
+ case BASEPROPERTY_EFFECTIVE_VALUE:
+ case BASEPROPERTY_VALUE_DOUBLE:
+ aReturn = GetValue();
+ break;
+
+ case BASEPROPERTY_VALUESTEP_DOUBLE:
+ aReturn <<= rFormatter.GetSpinSize();
+ break;
+
+ case BASEPROPERTY_DECIMALACCURACY:
+ aReturn <<= rFormatter.GetDecimalDigits();
+ break;
+
+ case BASEPROPERTY_FORMATSSUPPLIER:
+ {
+ if (!bIsStandardSupplier)
+ { // ansonsten void
+ css::uno::Reference< css::util::XNumberFormatsSupplier > xSupplier = m_xCurrentSupplier;
+ aReturn <<= xSupplier;
+ }
+ }
+ break;
+
+ case BASEPROPERTY_FORMATKEY:
+ {
+ if (!bIsStandardSupplier)
+ aReturn <<= getFormatKey();
+ }
+ break;
+
+ default:
+ aReturn = VCLXSpinField::getProperty(PropertyName);
+ }
+ }
+ return aReturn;
+}
+
+css::uno::Any SVTXFormattedField::convertEffectiveValue(const css::uno::Any& rValue) const
+{
+ css::uno::Any aReturn;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if (!pField)
+ return aReturn;
+
+ Formatter& rFieldFormatter = pField->GetFormatter();
+ switch (rValue.getValueType().getTypeClass())
+ {
+ case css::uno::TypeClass_DOUBLE:
+ if (rFieldFormatter.TreatingAsNumber())
+ {
+ double d = 0.0;
+ rValue >>= d;
+ aReturn <<= d;
+ }
+ else
+ {
+ SvNumberFormatter* pFormatter = rFieldFormatter.GetFormatter();
+ if (!pFormatter)
+ pFormatter = rFieldFormatter.StandardFormatter();
+ // should never fail
+
+ const Color* pDum;
+ double d = 0.0;
+ rValue >>= d;
+ OUString sConverted;
+ pFormatter->GetOutputString(d, 0, sConverted, &pDum);
+ aReturn <<= sConverted;
+ }
+ break;
+ case css::uno::TypeClass_STRING:
+ {
+ OUString aStr;
+ rValue >>= aStr;
+ if (rFieldFormatter.TreatingAsNumber())
+ {
+ SvNumberFormatter* pFormatter = rFieldFormatter.GetFormatter();
+ if (!pFormatter)
+ pFormatter = rFieldFormatter.StandardFormatter();
+
+ double dVal;
+ sal_uInt32 nTestFormat(0);
+ if (!pFormatter->IsNumberFormat(aStr, nTestFormat, dVal))
+ aReturn.clear();
+ aReturn <<= dVal;
+ }
+ else
+ aReturn <<= aStr;
+ }
+ break;
+ default:
+ aReturn.clear();
+ break;
+ }
+ return aReturn;
+}
+
+void SVTXFormattedField::SetMinValue(const css::uno::Any& rValue)
+{
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if (!pField)
+ return;
+
+ Formatter& rFormatter = pField->GetFormatter();
+ switch (rValue.getValueType().getTypeClass())
+
+ {
+ case css::uno::TypeClass_DOUBLE:
+ {
+ double d = 0.0;
+ rValue >>= d;
+ rFormatter.SetMinValue(d);
+ break;
+ }
+ default:
+ DBG_ASSERT(rValue.getValueType().getTypeClass() == css::uno::TypeClass_VOID, "SVTXFormattedField::SetMinValue : invalid argument (an exception will be thrown) !");
+ if ( rValue.getValueType().getTypeClass() != css::uno::TypeClass_VOID )
+
+ {
+ throw css::lang::IllegalArgumentException();
+ }
+ rFormatter.ClearMinValue();
+ break;
+ }
+}
+
+css::uno::Any SVTXFormattedField::GetMinValue() const
+{
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if (!pField)
+ return css::uno::Any();
+ Formatter& rFormatter = pField->GetFormatter();
+ if (!rFormatter.HasMinValue())
+ return css::uno::Any();
+
+ css::uno::Any aReturn;
+ aReturn <<= rFormatter.GetMinValue();
+ return aReturn;
+}
+
+void SVTXFormattedField::SetMaxValue(const css::uno::Any& rValue)
+{
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if (!pField)
+ return;
+
+ Formatter& rFormatter = pField->GetFormatter();
+ switch (rValue.getValueType().getTypeClass())
+ {
+ case css::uno::TypeClass_DOUBLE:
+ {
+ double d = 0.0;
+ rValue >>= d;
+ rFormatter.SetMaxValue(d);
+ break;
+ }
+ default:
+ if (rValue.getValueType().getTypeClass() != css::uno::TypeClass_VOID)
+
+ {
+ throw css::lang::IllegalArgumentException();
+ }
+ rFormatter.ClearMaxValue();
+ break;
+ }
+}
+
+css::uno::Any SVTXFormattedField::GetMaxValue() const
+{
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if (!pField)
+ return css::uno::Any();
+ Formatter& rFormatter = pField->GetFormatter();
+ if (!rFormatter.HasMaxValue())
+ return css::uno::Any();
+
+ css::uno::Any aReturn;
+ aReturn <<= rFormatter.GetMaxValue();
+ return aReturn;
+}
+
+void SVTXFormattedField::SetDefaultValue(const css::uno::Any& rValue)
+{
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if (!pField)
+ return;
+
+ css::uno::Any aConverted = convertEffectiveValue(rValue);
+
+ Formatter& rFormatter = pField->GetFormatter();
+ switch (aConverted.getValueType().getTypeClass())
+ {
+ case css::uno::TypeClass_DOUBLE:
+ {
+ double d = 0.0;
+ aConverted >>= d;
+ rFormatter.SetDefaultValue(d);
+ }
+ break;
+ case css::uno::TypeClass_STRING:
+ {
+ OUString aStr;
+ aConverted >>= aStr;
+ rFormatter.SetDefaultText( aStr );
+ }
+ break;
+ default:
+ rFormatter.EnableEmptyField(true);
+ // only void accepted
+ break;
+ }
+}
+
+css::uno::Any SVTXFormattedField::GetDefaultValue() const
+{
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if (!pField)
+ return css::uno::Any();
+ Formatter& rFormatter = pField->GetFormatter();
+ if (rFormatter.IsEmptyFieldEnabled())
+ return css::uno::Any();
+
+ css::uno::Any aReturn;
+ if (rFormatter.TreatingAsNumber())
+ aReturn <<= rFormatter.GetDefaultValue();
+ else
+ aReturn <<= rFormatter.GetDefaultText();
+ return aReturn;
+}
+
+bool SVTXFormattedField::GetTreatAsNumber() const
+{
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if (pField)
+ return pField->GetFormatter().TreatingAsNumber();
+
+ return true;
+}
+
+void SVTXFormattedField::SetTreatAsNumber(bool bSet)
+{
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if (pField)
+ pField->GetFormatter().TreatAsNumber(bSet);
+}
+
+css::uno::Any SVTXFormattedField::GetValue() const
+{
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if (!pField)
+ return css::uno::Any();
+
+ Formatter& rFormatter = pField->GetFormatter();
+ css::uno::Any aReturn;
+ if (!rFormatter.TreatingAsNumber())
+ {
+ OUString sText = rFormatter.GetTextValue();
+ aReturn <<= sText;
+ }
+ else
+ {
+ if (!pField->GetText().isEmpty()) // empty is returned as void by default
+ aReturn <<= rFormatter.GetValue();
+ }
+
+ return aReturn;
+}
+
+void SVTXFormattedField::SetValue(const css::uno::Any& rValue)
+{
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if (!pField)
+ return;
+
+ if (!rValue.hasValue())
+ {
+ pField->SetText("");
+ }
+ else
+ {
+ Formatter& rFormatter = pField->GetFormatter();
+ if (rValue.getValueType().getTypeClass() == css::uno::TypeClass_DOUBLE )
+ {
+ double d = 0.0;
+ rValue >>= d;
+ rFormatter.SetValue(d);
+ }
+ else
+ {
+ DBG_ASSERT(rValue.getValueType().getTypeClass() == css::uno::TypeClass_STRING, "SVTXFormattedField::SetValue : invalid argument !");
+
+ OUString sText;
+ rValue >>= sText;
+ if (!rFormatter.TreatingAsNumber())
+ rFormatter.SetTextFormatted(sText);
+ else
+ rFormatter.SetTextValue(sText);
+ }
+ }
+// NotifyTextListeners();
+}
+
+void SVTXFormattedField::setFormatsSupplier(const css::uno::Reference< css::util::XNumberFormatsSupplier > & xSupplier)
+{
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+
+ rtl::Reference<SvNumberFormatsSupplierObj> pNew;
+ if (!xSupplier.is())
+ {
+ if (pField)
+ {
+ Formatter& rFormatter = pField->GetFormatter();
+ pNew = new SvNumberFormatsSupplierObj(rFormatter.StandardFormatter());
+ bIsStandardSupplier = true;
+ }
+ }
+ else
+ {
+ pNew = comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>(xSupplier);
+ bIsStandardSupplier = false;
+ }
+
+ if (!pNew)
+ return; // TODO : how to process ?
+
+ m_xCurrentSupplier = pNew;
+ if (!pField)
+ return;
+
+ // save the actual value
+ css::uno::Any aCurrent = GetValue();
+ Formatter& rFormatter = pField->GetFormatter();
+ rFormatter.SetFormatter(m_xCurrentSupplier->GetNumberFormatter(), false);
+ if (nKeyToSetDelayed != -1)
+ {
+ rFormatter.SetFormatKey(nKeyToSetDelayed);
+ nKeyToSetDelayed = -1;
+ }
+ SetValue(aCurrent);
+ NotifyTextListeners();
+}
+
+sal_Int32 SVTXFormattedField::getFormatKey() const
+{
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ return pField ? pField->GetFormatter().GetFormatKey() : 0;
+}
+
+void SVTXFormattedField::setFormatKey(sal_Int32 nKey)
+{
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if (!pField)
+ return;
+
+ Formatter& rFormatter = pField->GetFormatter();
+ if (rFormatter.GetFormatter())
+ rFormatter.SetFormatKey(nKey);
+ else
+ {
+ // probably I am in a block, in which first the key and next the formatter will be set,
+ // initially this happens quite certain, as the properties are set in alphabetic sequence,
+ // and the FormatsSupplier is processed before the FormatKey
+ nKeyToSetDelayed = nKey;
+ }
+ NotifyTextListeners();
+}
+
+void SVTXFormattedField::NotifyTextListeners()
+{
+ if ( GetTextListeners().getLength() )
+ {
+ css::awt::TextEvent aEvent;
+ aEvent.Source = getXWeak();
+ GetTextListeners().textChanged( aEvent );
+ }
+}
+
+void SVTXFormattedField::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ // FIXME: elide duplication ?
+ BASEPROPERTY_EFFECTIVE_MIN,
+ BASEPROPERTY_VALUEMIN_DOUBLE,
+ BASEPROPERTY_EFFECTIVE_MAX,
+ BASEPROPERTY_VALUEMAX_DOUBLE,
+ BASEPROPERTY_EFFECTIVE_DEFAULT,
+ BASEPROPERTY_TREATASNUMBER,
+ BASEPROPERTY_EFFECTIVE_VALUE,
+ BASEPROPERTY_VALUE_DOUBLE,
+ BASEPROPERTY_VALUESTEP_DOUBLE,
+ BASEPROPERTY_DECIMALACCURACY,
+ BASEPROPERTY_FORMATSSUPPLIER,
+ BASEPROPERTY_NUMSHOWTHOUSANDSEP,
+ BASEPROPERTY_FORMATKEY,
+ BASEPROPERTY_TREATASNUMBER,
+ BASEPROPERTY_ENFORCE_FORMAT,
+ 0);
+ VCLXWindow::ImplGetPropertyIds( rIds, true );
+ VCLXSpinField::ImplGetPropertyIds( rIds );
+}
+
+SVTXCurrencyField::SVTXCurrencyField()
+{
+}
+
+SVTXCurrencyField::~SVTXCurrencyField()
+{
+}
+
+void SVTXCurrencyField::setValue( double Value )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if ( pField )
+ pField->GetFormatter().SetValue( Value );
+}
+
+double SVTXCurrencyField::getValue()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ return pField ? pField->GetFormatter().GetValue() : 0;
+}
+
+void SVTXCurrencyField::setMin( double Value )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if ( pField )
+ pField->GetFormatter().SetMinValue( Value );
+}
+
+double SVTXCurrencyField::getMin()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ return pField ? pField->GetFormatter().GetMinValue() : 0;
+}
+
+void SVTXCurrencyField::setMax( double Value )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if ( pField )
+ pField->GetFormatter().SetMaxValue( Value );
+}
+
+double SVTXCurrencyField::getMax()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ return pField ? pField->GetFormatter().GetMaxValue() : 0;
+}
+
+void SVTXCurrencyField::setFirst( double Value )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if ( pField )
+ pField->GetFormatter().SetSpinFirst( Value );
+}
+
+double SVTXCurrencyField::getFirst()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ return pField ? pField->GetFormatter().GetSpinFirst() : 0;
+}
+
+void SVTXCurrencyField::setLast( double Value )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if ( pField )
+ pField->GetFormatter().SetSpinLast( Value );
+}
+
+double SVTXCurrencyField::getLast()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ return pField ? pField->GetFormatter().GetSpinLast() : 0;
+}
+
+void SVTXCurrencyField::setSpinSize( double Value )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if ( pField )
+ pField->GetFormatter().SetSpinSize( Value );
+}
+
+double SVTXCurrencyField::getSpinSize()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ return pField ? pField->GetFormatter().GetSpinSize() : 0;
+}
+
+void SVTXCurrencyField::setDecimalDigits( sal_Int16 Value )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if ( pField )
+ pField->GetFormatter().SetDecimalDigits( Value );
+}
+
+sal_Int16 SVTXCurrencyField::getDecimalDigits()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ return pField ? pField->GetFormatter().GetDecimalDigits() : 0;
+}
+
+void SVTXCurrencyField::setStrictFormat( sal_Bool bStrict )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if ( pField )
+ pField->GetFormatter().SetStrictFormat( bStrict );
+}
+
+sal_Bool SVTXCurrencyField::isStrictFormat()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ return pField && pField->GetFormatter().IsStrictFormat();
+}
+
+void SVTXCurrencyField::setProperty( const OUString& PropertyName, const css::uno::Any& Value)
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< DoubleCurrencyField > pField = GetAs< DoubleCurrencyField >();
+ if ( pField )
+ {
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch (nPropType)
+ {
+ case BASEPROPERTY_CURRENCYSYMBOL:
+ {
+ OUString aStr;
+ Value >>= aStr;
+ pField->setCurrencySymbol( aStr );
+ }
+ break;
+ case BASEPROPERTY_CURSYM_POSITION:
+ {
+ bool b = false;
+ Value >>= b;
+ pField->setPrependCurrSym(b);
+ }
+ break;
+
+ default:
+ SVTXFormattedField::setProperty(PropertyName, Value);
+ }
+ }
+ else
+ SVTXFormattedField::setProperty(PropertyName, Value);
+}
+
+css::uno::Any SVTXCurrencyField::getProperty( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Any aReturn;
+
+ VclPtr< DoubleCurrencyField > pField = GetAs< DoubleCurrencyField >();
+ if ( pField )
+ {
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch (nPropType)
+ {
+ case BASEPROPERTY_CURRENCYSYMBOL:
+ {
+ aReturn <<= pField->getCurrencySymbol();
+ }
+ break;
+ case BASEPROPERTY_CURSYM_POSITION:
+ {
+ aReturn <<= pField->getPrependCurrSym();
+ }
+ break;
+ default:
+ return SVTXFormattedField::getProperty(PropertyName);
+ }
+ }
+ return SVTXFormattedField::getProperty(PropertyName);
+}
+
+void SVTXCurrencyField::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ BASEPROPERTY_ALIGN,
+ BASEPROPERTY_BACKGROUNDCOLOR,
+ BASEPROPERTY_BORDER,
+ BASEPROPERTY_BORDERCOLOR,
+ BASEPROPERTY_CURRENCYSYMBOL,
+ BASEPROPERTY_CURSYM_POSITION,
+ BASEPROPERTY_DECIMALACCURACY,
+ BASEPROPERTY_DEFAULTCONTROL,
+ BASEPROPERTY_ENABLED,
+ BASEPROPERTY_ENABLEVISIBLE,
+ BASEPROPERTY_FONTDESCRIPTOR,
+ BASEPROPERTY_HELPTEXT,
+ BASEPROPERTY_HELPURL,
+ BASEPROPERTY_NUMSHOWTHOUSANDSEP,
+ BASEPROPERTY_PRINTABLE,
+ BASEPROPERTY_READONLY,
+ BASEPROPERTY_REPEAT,
+ BASEPROPERTY_REPEAT_DELAY,
+ BASEPROPERTY_SPIN,
+ BASEPROPERTY_STRICTFORMAT,
+ BASEPROPERTY_TABSTOP,
+ BASEPROPERTY_VALUEMAX_DOUBLE,
+ BASEPROPERTY_VALUEMIN_DOUBLE,
+ BASEPROPERTY_VALUESTEP_DOUBLE,
+ BASEPROPERTY_VALUE_DOUBLE,
+ BASEPROPERTY_ENFORCE_FORMAT,
+ BASEPROPERTY_HIDEINACTIVESELECTION,
+ BASEPROPERTY_VERTICALALIGN,
+ BASEPROPERTY_WRITING_MODE,
+ BASEPROPERTY_CONTEXT_WRITING_MODE,
+ BASEPROPERTY_MOUSE_WHEEL_BEHAVIOUR,
+ BASEPROPERTY_HIGHLIGHT_COLOR,
+ BASEPROPERTY_HIGHLIGHT_TEXT_COLOR,
+ 0);
+ VCLXWindow::ImplGetPropertyIds( rIds );
+}
+
+SVTXNumericField::SVTXNumericField()
+{
+}
+
+SVTXNumericField::~SVTXNumericField()
+{
+}
+
+
+css::uno::Reference<accessibility::XAccessibleContext> SVTXNumericField::CreateAccessibleContext()
+{
+ return getAccessibleFactory().createAccessibleContext(this);
+}
+
+
+void SVTXNumericField::setValue( double Value )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if ( pField )
+ pField->GetFormatter().SetValue( Value );
+}
+
+double SVTXNumericField::getValue()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ return pField ? pField->GetFormatter().GetValue() : 0;
+}
+
+void SVTXNumericField::setMin( double Value )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if ( pField )
+ pField->GetFormatter().SetMinValue( Value );
+}
+
+double SVTXNumericField::getMin()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ return pField ? pField->GetFormatter().GetMinValue() : 0;
+}
+
+void SVTXNumericField::setMax( double Value )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if ( pField )
+ pField->GetFormatter().SetMaxValue( Value );
+}
+
+double SVTXNumericField::getMax()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ return pField ? pField->GetFormatter().GetMaxValue() : 0;
+}
+
+void SVTXNumericField::setFirst( double Value )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if ( pField )
+ pField->GetFormatter().SetSpinFirst( Value );
+}
+
+double SVTXNumericField::getFirst()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ return pField ? pField->GetFormatter().GetSpinFirst() : 0;
+}
+
+void SVTXNumericField::setLast( double Value )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if ( pField )
+ pField->GetFormatter().SetSpinLast( Value );
+}
+
+double SVTXNumericField::getLast()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ return pField ? pField->GetFormatter().GetSpinLast() : 0;
+}
+
+void SVTXNumericField::setSpinSize( double Value )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if ( pField )
+ pField->GetFormatter().SetSpinSize( Value );
+}
+
+double SVTXNumericField::getSpinSize()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ return pField ? pField->GetFormatter().GetSpinSize() : 0;
+}
+
+void SVTXNumericField::setDecimalDigits( sal_Int16 Value )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if ( pField )
+ pField->GetFormatter().SetDecimalDigits( Value );
+}
+
+sal_Int16 SVTXNumericField::getDecimalDigits()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ return pField ? pField->GetFormatter().GetDecimalDigits() : 0;
+}
+
+void SVTXNumericField::setStrictFormat( sal_Bool bStrict )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ if ( pField )
+ pField->GetFormatter().SetStrictFormat( bStrict );
+}
+
+sal_Bool SVTXNumericField::isStrictFormat()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<FormattedField> pField = GetAs< FormattedField >();
+ return pField && pField->GetFormatter().IsStrictFormat();
+}
+
+void SVTXNumericField::GetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ SVTXFormattedField::ImplGetPropertyIds( rIds );
+}
+
+SVTXDateField::SVTXDateField()
+{
+}
+
+SVTXDateField::~SVTXDateField()
+{
+}
+
+void SAL_CALL SVTXDateField::setProperty( const OUString& PropertyName, const css::uno::Any& Value )
+{
+ VCLXDateField::setProperty( PropertyName, Value );
+
+ // some properties need to be forwarded to the sub edit, too
+ SolarMutexGuard g;
+ VclPtr< Edit > pSubEdit = GetWindow() ? GetAs<Edit>()->GetSubEdit() : nullptr;
+ if ( !pSubEdit )
+ return;
+
+ switch ( GetPropertyId( PropertyName ) )
+ {
+ case BASEPROPERTY_TEXTLINECOLOR:
+ if ( !Value.hasValue() )
+ pSubEdit->SetTextLineColor();
+ else
+ {
+ Color nColor;
+ if ( Value >>= nColor )
+ pSubEdit->SetTextLineColor( nColor );
+ }
+ break;
+ }
+}
+
+void SVTXDateField::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ BASEPROPERTY_TEXTLINECOLOR,
+ 0);
+ VCLXDateField::ImplGetPropertyIds( rIds );
+}
+
+VCLXMultiLineEdit::VCLXMultiLineEdit()
+ :maTextListeners( *this )
+ ,meLineEndType( LINEEND_LF ) // default behavior before introducing this property: LF (unix-like)
+{
+}
+
+VCLXMultiLineEdit::~VCLXMultiLineEdit()
+{
+}
+
+void VCLXMultiLineEdit::addTextListener( const css::uno::Reference< css::awt::XTextListener > & l )
+{
+ maTextListeners.addInterface( l );
+}
+
+void VCLXMultiLineEdit::removeTextListener( const css::uno::Reference< css::awt::XTextListener > & l )
+{
+ maTextListeners.removeInterface( l );
+}
+
+void VCLXMultiLineEdit::setText( const OUString& aText )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< MultiLineEdit > pEdit = GetAs< MultiLineEdit >();
+ if ( pEdit )
+ {
+ pEdit->SetText( aText );
+
+ // #107218# Call same listeners like VCL would do after user interaction
+ SetSynthesizingVCLEvent( true );
+ pEdit->SetModifyFlag();
+ pEdit->Modify();
+ SetSynthesizingVCLEvent( false );
+ }
+}
+
+void VCLXMultiLineEdit::insertText( const css::awt::Selection& rSel, const OUString& aText )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< MultiLineEdit > pEdit = GetAs< MultiLineEdit >();
+ if ( pEdit )
+ {
+ setSelection( rSel );
+ pEdit->ReplaceSelected( aText );
+ }
+}
+
+OUString VCLXMultiLineEdit::getText()
+{
+ SolarMutexGuard aGuard;
+
+ OUString aText;
+ VclPtr< MultiLineEdit > pEdit = GetAs< MultiLineEdit >();
+ if ( pEdit )
+ aText = pEdit->GetText( meLineEndType );
+ return aText;
+}
+
+OUString VCLXMultiLineEdit::getSelectedText()
+{
+ SolarMutexGuard aGuard;
+
+ OUString aText;
+ VclPtr< MultiLineEdit > pMultiLineEdit = GetAs< MultiLineEdit >();
+ if ( pMultiLineEdit)
+ aText = pMultiLineEdit->GetSelected( meLineEndType );
+ return aText;
+
+}
+
+void VCLXMultiLineEdit::setSelection( const css::awt::Selection& aSelection )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< MultiLineEdit > pMultiLineEdit = GetAs< MultiLineEdit >();
+ if ( pMultiLineEdit )
+ {
+ pMultiLineEdit->SetSelection( Selection( aSelection.Min, aSelection.Max ) );
+ }
+}
+
+css::awt::Selection VCLXMultiLineEdit::getSelection()
+{
+ SolarMutexGuard aGuard;
+
+ css::awt::Selection aSel;
+ VclPtr< MultiLineEdit > pMultiLineEdit = GetAs< MultiLineEdit >();
+ if ( pMultiLineEdit )
+ {
+ aSel.Min = pMultiLineEdit->GetSelection().Min();
+ aSel.Max = pMultiLineEdit->GetSelection().Max();
+ }
+ return aSel;
+}
+
+sal_Bool VCLXMultiLineEdit::isEditable()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< MultiLineEdit > pMultiLineEdit = GetAs< MultiLineEdit >();
+ return pMultiLineEdit && !pMultiLineEdit->IsReadOnly() && pMultiLineEdit->IsEnabled();
+}
+
+void VCLXMultiLineEdit::setEditable( sal_Bool bEditable )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< MultiLineEdit > pMultiLineEdit = GetAs< MultiLineEdit >();
+ if ( pMultiLineEdit )
+ pMultiLineEdit->SetReadOnly( !bEditable );
+}
+
+void VCLXMultiLineEdit::setMaxTextLen( sal_Int16 nLen )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< MultiLineEdit > pMultiLineEdit = GetAs< MultiLineEdit >();
+ if ( pMultiLineEdit )
+ pMultiLineEdit->SetMaxTextLen( nLen );
+}
+
+sal_Int16 VCLXMultiLineEdit::getMaxTextLen()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< MultiLineEdit > pMultiLineEdit = GetAs< MultiLineEdit >();
+ return pMultiLineEdit ? static_cast<sal_Int16>(pMultiLineEdit->GetMaxTextLen()) : sal_Int16(0);
+}
+
+OUString VCLXMultiLineEdit::getTextLines()
+{
+ SolarMutexGuard aGuard;
+
+ OUString aText;
+ VclPtr< MultiLineEdit > pEdit = GetAs< MultiLineEdit >();
+ if ( pEdit )
+ aText = pEdit->GetTextLines( meLineEndType );
+ return aText;
+}
+
+css::awt::Size VCLXMultiLineEdit::getMinimumSize()
+{
+ SolarMutexGuard aGuard;
+
+ css::awt::Size aSz;
+ VclPtr< MultiLineEdit > pEdit = GetAs< MultiLineEdit >();
+ if ( pEdit )
+ aSz = AWTSize(pEdit->CalcMinimumSize());
+ return aSz;
+}
+
+css::awt::Size VCLXMultiLineEdit::getPreferredSize()
+{
+ return getMinimumSize();
+}
+
+css::awt::Size VCLXMultiLineEdit::calcAdjustedSize( const css::awt::Size& rNewSize )
+{
+ SolarMutexGuard aGuard;
+
+ css::awt::Size aSz = rNewSize;
+ VclPtr< MultiLineEdit > pEdit = GetAs< MultiLineEdit >();
+ if ( pEdit )
+ aSz = AWTSize(pEdit->CalcAdjustedSize( VCLSize(rNewSize )));
+ return aSz;
+}
+
+css::awt::Size VCLXMultiLineEdit::getMinimumSize( sal_Int16 nCols, sal_Int16 nLines )
+{
+ SolarMutexGuard aGuard;
+
+ css::awt::Size aSz;
+ VclPtr< MultiLineEdit > pEdit = GetAs< MultiLineEdit >();
+ if ( pEdit )
+ aSz = AWTSize(pEdit->CalcBlockSize( nCols, nLines ));
+ return aSz;
+}
+
+void VCLXMultiLineEdit::getColumnsAndLines( sal_Int16& nCols, sal_Int16& nLines )
+{
+ SolarMutexGuard aGuard;
+
+ nCols = nLines = 0;
+ VclPtr< MultiLineEdit > pEdit = GetAs< MultiLineEdit >();
+ if ( pEdit )
+ {
+ sal_uInt16 nC, nL;
+ pEdit->GetMaxVisColumnsAndLines( nC, nL );
+ nCols = nC;
+ nLines = nL;
+ }
+}
+
+void VCLXMultiLineEdit::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::EditModify:
+ {
+ if ( maTextListeners.getLength() )
+ {
+ css::awt::TextEvent aEvent;
+ aEvent.Source = getXWeak();
+ maTextListeners.textChanged( aEvent );
+ }
+ }
+ break;
+ default:
+ {
+ VCLXWindow::ProcessWindowEvent( rVclWindowEvent );
+ }
+ break;
+ }
+}
+
+void VCLXMultiLineEdit::setProperty( const OUString& PropertyName, const css::uno::Any& Value)
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< MultiLineEdit > pMultiLineEdit = GetAs< MultiLineEdit >();
+ if ( !pMultiLineEdit )
+ return;
+
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_LINE_END_FORMAT:
+ {
+ sal_Int16 nLineEndType = css::awt::LineEndFormat::LINE_FEED;
+ OSL_VERIFY( Value >>= nLineEndType );
+ switch ( nLineEndType )
+ {
+ case css::awt::LineEndFormat::CARRIAGE_RETURN: meLineEndType = LINEEND_CR; break;
+ case css::awt::LineEndFormat::LINE_FEED: meLineEndType = LINEEND_LF; break;
+ case css::awt::LineEndFormat::CARRIAGE_RETURN_LINE_FEED: meLineEndType = LINEEND_CRLF; break;
+ default: OSL_FAIL( "VCLXMultiLineEdit::setProperty: invalid line end value!" ); break;
+ }
+ }
+ break;
+
+ case BASEPROPERTY_READONLY:
+ {
+ bool b;
+ if ( Value >>= b )
+ pMultiLineEdit->SetReadOnly( b );
+ }
+ break;
+ case BASEPROPERTY_MAXTEXTLEN:
+ {
+ sal_Int16 n = sal_Int16();
+ if ( Value >>= n )
+ pMultiLineEdit->SetMaxTextLen( n );
+ }
+ break;
+ case BASEPROPERTY_HIDEINACTIVESELECTION:
+ {
+ bool b;
+ if ( Value >>= b )
+ {
+ pMultiLineEdit->EnableFocusSelectionHide( b );
+ lcl_setWinBits( pMultiLineEdit, WB_NOHIDESELECTION, !b );
+ }
+ }
+ break;
+ default:
+ {
+ VCLXWindow::setProperty( PropertyName, Value );
+ }
+ }
+}
+
+css::uno::Any VCLXMultiLineEdit::getProperty( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ css::uno::Any aProp;
+ VclPtr< MultiLineEdit > pMultiLineEdit = GetAs< MultiLineEdit >();
+ if ( pMultiLineEdit )
+ {
+ sal_uInt16 nPropType = GetPropertyId( PropertyName );
+ switch ( nPropType )
+ {
+ case BASEPROPERTY_LINE_END_FORMAT:
+ {
+ sal_Int16 nLineEndType = css::awt::LineEndFormat::LINE_FEED;
+ switch ( meLineEndType )
+ {
+ case LINEEND_CR: nLineEndType = css::awt::LineEndFormat::CARRIAGE_RETURN; break;
+ case LINEEND_LF: nLineEndType = css::awt::LineEndFormat::LINE_FEED; break;
+ case LINEEND_CRLF: nLineEndType = css::awt::LineEndFormat::CARRIAGE_RETURN_LINE_FEED; break;
+ default: OSL_FAIL( "VCLXMultiLineEdit::getProperty: invalid line end value!" ); break;
+ }
+ aProp <<= nLineEndType;
+ }
+ break;
+
+ case BASEPROPERTY_READONLY:
+ {
+ aProp <<= pMultiLineEdit->IsReadOnly();
+ }
+ break;
+ case BASEPROPERTY_MAXTEXTLEN:
+ {
+ aProp <<= static_cast<sal_Int16>(pMultiLineEdit->GetMaxTextLen());
+ }
+ break;
+ default:
+ {
+ aProp = VCLXWindow::getProperty( PropertyName );
+ }
+ }
+ }
+ return aProp;
+}
+
+void SAL_CALL VCLXMultiLineEdit::setFocus( )
+{
+ SolarMutexGuard aGuard;
+
+ // don't grab the focus if we already have it. Reason is that the only thing which the edit
+ // does is forwarding the focus to its text window. This text window then does a "select all".
+ // So if the text window already has the focus, and we give the focus to the multi line
+ // edit, then all which happens is that everything is selected.
+ // #i27072#
+ if ( GetWindow() && !GetWindow()->HasChildPathFocus() )
+ GetWindow()->GrabFocus();
+}
+
+void VCLXMultiLineEdit::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
+{
+ PushPropertyIds( rIds,
+ // FIXME: elide duplication ?
+ BASEPROPERTY_LINE_END_FORMAT,
+ BASEPROPERTY_READONLY,
+ BASEPROPERTY_MAXTEXTLEN,
+ BASEPROPERTY_HIDEINACTIVESELECTION,
+ 0);
+ VCLXWindow::ImplGetPropertyIds( rIds, true );
+}
+
+css::uno::Reference<css::accessibility::XAccessibleContext> VCLXMultiLineEdit::CreateAccessibleContext()
+{
+ return getAccessibleFactory().createAccessibleContext(this);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/awt/vclxwindows_internal.hxx b/toolkit/source/awt/vclxwindows_internal.hxx
new file mode 100644
index 0000000000..0425225865
--- /dev/null
+++ b/toolkit/source/awt/vclxwindows_internal.hxx
@@ -0,0 +1,33 @@
+/* -*- 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_AWT_VCLXWINDOWS_INTERNAL_HXX
+#define INCLUDED_TOOLKIT_SOURCE_AWT_VCLXWINDOWS_INTERNAL_HXX
+
+#include <vcl/window.hxx>
+
+namespace toolkit
+{
+void setButtonLikeFaceColor(vcl::Window* _pWindow, const css::uno::Any& _rColorValue);
+css::uno::Any getButtonLikeFaceColor(const vcl::Window* _pWindow);
+}
+
+#endif // INCLUDED_TOOLKIT_SOURCE_AWT_VCLXWINDOWS_INTERNAL_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/accessiblecontrolcontext.cxx b/toolkit/source/controls/accessiblecontrolcontext.cxx
new file mode 100644
index 0000000000..761821bce6
--- /dev/null
+++ b/toolkit/source/controls/accessiblecontrolcontext.cxx
@@ -0,0 +1,343 @@
+/* -*- 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 <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 <comphelper/accessiblecontexthelper.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#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();
+ }
+
+
+ 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_Int64 SAL_CALL OAccessibleControlContext::getAccessibleChildCount( )
+ {
+ // we do not have children
+ return 0;
+ }
+
+
+ Reference< XAccessible > SAL_CALL OAccessibleControlContext::getAccessibleChild( sal_Int64 )
+ {
+ // 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;
+ }
+
+
+ sal_Int64 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
+
+ sal_Int64 nStateSet = 0;
+ if ( isAlive() )
+ {
+ // no own states, only the ones which are foreign controlled
+ }
+ else
+ { // only the DEFUNC state if we're already disposed
+ nStateSet |= AccessibleStateType::DEFUNC;
+ }
+ return nStateSet;
+ }
+
+
+ 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 0000000000..dec4a8c533
--- /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 <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( std::unique_lock<std::mutex>& i_guard, comphelper::OInterfaceContainerHelper4<XContainerListener>& rContainer,
+ void ( SAL_CALL XContainerListener::*i_notificationMethod )( const ContainerEvent& ),
+ const sal_Int32 i_accessor, const Sequence< OUString >& i_imageURLs, const Reference< XInterface >& i_context )
+ {
+ if ( !rContainer.getLength(i_guard) )
+ return;
+
+ ContainerEvent aEvent;
+ aEvent.Source = i_context;
+ aEvent.Accessor <<= i_accessor;
+ aEvent.Element <<= i_imageURLs;
+
+ rContainer.notifyEach( i_guard, 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 AnimatedImagesControlModel::setFastPropertyValue_NoBroadcast( std::unique_lock<std::mutex>& rGuard, 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( rGuard, 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& 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( )
+ {
+ std::unique_lock aGuard( m_aMutex );
+ if ( m_bDisposed )
+ throw DisposedException();
+
+ return maImageSets.size();
+ }
+
+
+ Sequence< OUString > SAL_CALL AnimatedImagesControlModel::getImageSet( ::sal_Int32 i_index )
+ {
+ std::unique_lock aGuard( m_aMutex );
+ if ( m_bDisposed )
+ 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 )
+ {
+ std::unique_lock aGuard( m_aMutex );
+ // sanity checks
+ if ( m_bDisposed )
+ throw DisposedException();
+
+ lcl_checkIndex( maImageSets, i_index, *this, true );
+
+ // actual insertion
+ maImageSets.insert( maImageSets.begin() + i_index, i_imageURLs );
+
+ // listener notification
+ lcl_notify( aGuard, maContainerListeners, &XContainerListener::elementInserted, i_index, i_imageURLs, *this );
+ }
+
+
+ void SAL_CALL AnimatedImagesControlModel::replaceImageSet( ::sal_Int32 i_index, const Sequence< OUString >& i_imageURLs )
+ {
+ std::unique_lock aGuard( m_aMutex );
+ // sanity checks
+ if ( m_bDisposed )
+ throw DisposedException();
+
+ lcl_checkIndex( maImageSets, i_index, *this );
+
+ // actual insertion
+ maImageSets[ i_index ] = i_imageURLs;
+
+ // listener notification
+ lcl_notify( aGuard, maContainerListeners, &XContainerListener::elementReplaced, i_index, i_imageURLs, *this );
+ }
+
+
+ void SAL_CALL AnimatedImagesControlModel::removeImageSet( ::sal_Int32 i_index )
+ {
+ std::unique_lock aGuard( m_aMutex );
+ // sanity checks
+ if ( m_bDisposed )
+ 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, maContainerListeners, &XContainerListener::elementRemoved, i_index, aRemovedElement, *this );
+ }
+
+
+ void SAL_CALL AnimatedImagesControlModel::addContainerListener( const Reference< XContainerListener >& i_listener )
+ {
+ std::unique_lock aGuard( m_aMutex );
+ maContainerListeners.addInterface( aGuard, i_listener );
+ }
+
+
+ void SAL_CALL AnimatedImagesControlModel::removeContainerListener( const Reference< XContainerListener >& i_listener )
+ {
+ std::unique_lock aGuard( m_aMutex );
+ maContainerListeners.removeInterface( aGuard, 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 0000000000..8c9bba0890
--- /dev/null
+++ b/toolkit/source/controls/controlmodelcontainerbase.cxx
@@ -0,0 +1,1789 @@
+/* -*- 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 <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 <comphelper/diagnose_ex.hxx>
+#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 OUString PROPERTY_RESOURCERESOLVER = u"ResourceResolver"_ustr;
+
+
+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();
+ }
+};
+
+constexpr OUString aTabIndexPropertyNameStr( u"TabIndex"_ustr );
+
+ControlModelContainerBase::ControlModelContainerBase( const Reference< XComponentContext >& rxContext )
+ :ControlModelContainer_IBase( rxContext )
+ ,maContainerListeners( *this )
+ ,mbGroupsUpToDate( false )
+ ,m_nTabPageId(0)
+{
+ ImplRegisterProperty(BASEPROPERTY_ENABLED);
+}
+
+ControlModelContainerBase::ControlModelContainerBase( const ControlModelContainerBase& rModel )
+ : ControlModelContainer_IBase( rModel )
+ , maContainerListeners( *this )
+ , 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
+ {
+ std::unique_lock aGuard( m_aMutex );
+
+ EventObject aDisposeEvent;
+ aDisposeEvent.Source = static_cast< XAggregation* >( static_cast< ::cppu::OWeakAggObject* >( this ) );
+
+ maContainerListeners.disposeAndClear( aGuard, aDisposeEvent );
+ maChangeListeners.disposeAndClear( aGuard, 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 );
+ }
+ }
+ }
+
+ return cppu::getXWeak(pNewModel.get());
+}
+
+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() )
+ throw IllegalArgumentException();
+
+ UnoControlModelHolderVector::iterator aElementPos = ImplFindElement( aName );
+ if ( maModels.end() == aElementPos )
+ throw NoSuchElementException();
+ // 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 )
+ throw NoSuchElementException();
+
+ 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() )
+ throw IllegalArgumentException();
+
+ UnoControlModelHolderVector::iterator aElementPos = ImplFindElement( aName );
+ if ( maModels.end() != aElementPos )
+ throw ElementExistException();
+
+ // 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 )
+ throw NoSuchElementException();
+
+ // 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( aTabIndexPropertyNameStr ) )
+ xProps->setPropertyValue( aTabIndexPropertyNameStr, 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( aTabIndexPropertyNameStr ) )
+ { // yes
+ sal_Int32 nTabIndex = -1;
+ xControlProps->getPropertyValue( aTabIndexPropertyNameStr ) >>= 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;
+ bool bEnabled = false;
+ getPropertyValue(GetPropertyName(BASEPROPERTY_ENABLED)) >>= bEnabled;
+ return bEnabled;
+}
+void SAL_CALL ControlModelContainerBase::setEnabled( sal_Bool _enabled )
+{
+ SolarMutexGuard aGuard;
+ setPropertyValue(GetPropertyName(BASEPROPERTY_ENABLED), Any(_enabled));
+}
+OUString SAL_CALL ControlModelContainerBase::getTitle()
+{
+ SolarMutexGuard aGuard;
+ OUString sTitle;
+ getPropertyValue(GetPropertyName(BASEPROPERTY_TITLE)) >>= sTitle;
+ return sTitle;
+}
+void SAL_CALL ControlModelContainerBase::setTitle( const OUString& _title )
+{
+ SolarMutexGuard aGuard;
+ 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;
+ SolarMutexGuard aGuard;
+ setPropertyValue(GetPropertyName(BASEPROPERTY_IMAGEURL), Any(_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( u"Step"_ustr ) >>= 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 )
+{
+ std::unique_lock g(m_aMutex);
+ maChangeListeners.addInterface( g, _rxListener );
+}
+
+
+void SAL_CALL ControlModelContainerBase::removeChangesListener( const Reference< XChangesListener >& _rxListener )
+{
+ std::unique_lock g(m_aMutex);
+ maChangeListeners.removeInterface( g, _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::unique_lock g(m_aMutex);
+ std::vector< Reference< css::util::XChangesListener > > aChangeListeners( maChangeListeners.getElements(g) );
+ g.unlock();
+ 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( aTabIndexPropertyNameStr ) )
+ xModelProps->addPropertyChangeListener( aTabIndexPropertyNameStr, 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( aTabIndexPropertyNameStr ) )
+ xModelProps->removePropertyChangeListener( aTabIndexPropertyNameStr, 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 = getXWeak();
+ // 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 0000000000..c65cabc8ad
--- /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 0000000000..ba954a1541
--- /dev/null
+++ b/toolkit/source/controls/dialogcontrol.cxx
@@ -0,0 +1,1245 @@
+/* -*- 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 <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& getInfoHelper() override;
+ // ::comphelper::OPropertySetHelper
+ void setFastPropertyValue_NoBroadcast( std::unique_lock<std::mutex>& rGuard, 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 ) );
+ }
+ std::unique_lock aGuard(m_aMutex);
+ setFastPropertyValue_NoBroadcast( aGuard, 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 UnoControlDialogModel::setFastPropertyValue_NoBroadcast( std::unique_lock<std::mutex>& rGuard, sal_Int32 nHandle, const css::uno::Any& rValue )
+{
+ ControlModelContainerBase::setFastPropertyValue_NoBroadcast( rGuard, nHandle, rValue );
+ try
+ {
+ if ( nHandle == BASEPROPERTY_IMAGEURL && ImplHasProperty( BASEPROPERTY_GRAPHIC ) )
+ {
+ OUString sImageURL;
+ uno::Reference<graphic::XGraphic> xGraphic;
+ if (rValue >>= sImageURL)
+ {
+ setFastPropertyValueImpl(rGuard,
+ BASEPROPERTY_GRAPHIC,
+ uno::Any(ImageHelper::getGraphicAndGraphicObjectFromURL_nothrow(
+ mxGrfObj, sImageURL)));
+ }
+ else if (rValue >>= xGraphic)
+ {
+ setFastPropertyValueImpl(rGuard, BASEPROPERTY_GRAPHIC, uno::Any(xGraphic));
+ }
+ }
+ }
+ catch( const css::uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION( "toolkit", "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 = getXWeak();
+ 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 = getXWeak();
+ 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 0000000000..1b57e984d7
--- /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 0000000000..f1b476220b
--- /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 <comphelper/diagnose_ex.hxx>
+#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 0000000000..cf3094c358
--- /dev/null
+++ b/toolkit/source/controls/formattedcontrol.cxx
@@ -0,0 +1,478 @@
+/* -*- 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 <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 <comphelper/diagnose_ex.hxx>
+#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 );
+ ImplRegisterProperty( BASEPROPERTY_HIGHLIGHT_COLOR );
+ ImplRegisterProperty( BASEPROPERTY_HIGHLIGHT_TEXT_COLOR );
+
+ Any aTreatAsNumber;
+ aTreatAsNumber <<= true;
+ ImplRegisterProperty( BASEPROPERTY_TREATASNUMBER, aTreatAsNumber );
+
+ lcl_registerDefaultFormatsClient();
+ }
+
+
+ UnoControlFormattedFieldModel::~UnoControlFormattedFieldModel()
+ {
+ }
+
+
+ OUString UnoControlFormattedFieldModel::getServiceName()
+ {
+ return "stardiv.vcl.controlmodel.FormattedField";
+ }
+
+
+ void UnoControlFormattedFieldModel::setFastPropertyValue_NoBroadcast( std::unique_lock<std::mutex>& rGuard, sal_Int32 nHandle, const Any& rValue )
+ {
+ UnoControlModel::setFastPropertyValue_NoBroadcast( rGuard, nHandle, rValue );
+
+ switch ( nHandle )
+ {
+ case BASEPROPERTY_EFFECTIVE_VALUE:
+ if ( !m_bSettingValueAndText )
+ impl_updateTextFromValue_nothrow(rGuard);
+ break;
+ case BASEPROPERTY_FORMATSSUPPLIER:
+ impl_updateCachedFormatter_nothrow(rGuard);
+ impl_updateTextFromValue_nothrow(rGuard);
+ break;
+ case BASEPROPERTY_FORMATKEY:
+ impl_updateCachedFormatKey_nothrow(rGuard);
+ impl_updateTextFromValue_nothrow(rGuard);
+ break;
+ }
+ }
+
+
+ void UnoControlFormattedFieldModel::impl_updateTextFromValue_nothrow( std::unique_lock<std::mutex>& rGuard)
+ {
+ if ( !m_xCachedFormatter.is() )
+ impl_updateCachedFormatter_nothrow(rGuard);
+ if ( !m_xCachedFormatter.is() )
+ return;
+
+ try
+ {
+ Any aEffectiveValue;
+ getFastPropertyValue( rGuard, 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 );
+ }
+ }
+
+ setFastPropertyValueImpl( rGuard, BASEPROPERTY_TEXT, Any( sStringValue ) );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+ }
+
+
+ void UnoControlFormattedFieldModel::impl_updateCachedFormatter_nothrow(std::unique_lock<std::mutex>& rGuard)
+ {
+ Any aFormatsSupplier;
+ getFastPropertyValue( rGuard, 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(std::unique_lock<std::mutex>& rGuard)
+ {
+ Any aFormatKey;
+ getFastPropertyValue( rGuard, aFormatKey, BASEPROPERTY_FORMATKEY );
+ m_aCachedFormat = aFormatKey;
+ }
+
+
+ void UnoControlFormattedFieldModel::dispose( )
+ {
+ UnoControlModel::dispose();
+
+ std::unique_lock aGuard( m_aMutex );
+ 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 );
+ }
+
+
+ bool UnoControlFormattedFieldModel::convertFastPropertyValue(
+ std::unique_lock<std::mutex>& rGuard,
+ 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( rGuard, 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( rGuard, 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 0000000000..70e8817da2
--- /dev/null
+++ b/toolkit/source/controls/geometrycontrolmodel.cxx
@@ -0,0 +1,609 @@
+/* -*- 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 <helper/property.hxx>
+#include <algorithm>
+#include <functional>
+#include <utility>
+
+
+#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(getXWeak());
+ }
+ 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(getXWeak());
+ }
+ 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, OUString _aServiceSpecifier )
+ :OGeometryControlModel_Base( _rxAgg )
+ ,m_sServiceSpecifier(std::move( _aServiceSpecifier ))
+ ,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 0000000000..5e1a085ba0
--- /dev/null
+++ b/toolkit/source/controls/grid/defaultgridcolumnmodel.cxx
@@ -0,0 +1,375 @@
+/* -*- 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/interfacecontainer4.hxx>
+#include <comphelper/compbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <o3tl/safeint.hxx>
+#include <rtl/ref.hxx>
+#include <sal/log.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+#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 ::comphelper::WeakComponentImplHelper < css::awt::grid::XGridColumnModel
+ , css::lang::XServiceInfo
+ > DefaultGridColumnModel_Base;
+
+class DefaultGridColumnModel : 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 disposing( std::unique_lock<std::mutex>& ) override;
+
+private:
+ typedef ::std::vector< rtl::Reference< GridColumn > > Columns;
+
+ ::comphelper::OInterfaceContainerHelper4<XContainerListener> m_aContainerListeners;
+ Columns m_aColumns;
+};
+
+ DefaultGridColumnModel::DefaultGridColumnModel()
+ {
+ }
+
+ DefaultGridColumnModel::DefaultGridColumnModel( DefaultGridColumnModel const & i_copySource )
+ {
+ 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
+ )
+ {
+ rtl::Reference< GridColumn > const xClone( new GridColumn(**col) );
+
+ xClone->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( )
+ {
+ std::unique_lock aGuard(m_aMutex);
+ throwIfDisposed(aGuard);
+ return new GridColumn();
+ }
+
+
+ ::sal_Int32 SAL_CALL DefaultGridColumnModel::addColumn( const Reference< XGridColumn > & i_column )
+ {
+ std::unique_lock aGuard(m_aMutex);
+ throwIfDisposed(aGuard);
+
+ GridColumn* const pGridColumn = dynamic_cast<GridColumn*>( i_column.get() );
+ if ( pGridColumn == nullptr )
+ throw css::lang::IllegalArgumentException( "invalid column implementation", *this, 1 );
+
+ m_aColumns.push_back( pGridColumn );
+ 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;
+
+ m_aContainerListeners.notifyEach( aGuard, &XContainerListener::elementInserted, aEvent );
+
+ return index;
+ }
+
+
+ void SAL_CALL DefaultGridColumnModel::removeColumn( ::sal_Int32 i_columnIndex )
+ {
+ std::unique_lock aGuard(m_aMutex);
+ throwIfDisposed(aGuard);
+
+ 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 = updatePos->get();
+ pColumnImpl->setIndex( columnIndex );
+ }
+
+ // fire removal notifications
+ ContainerEvent aEvent;
+ aEvent.Source = *this;
+ aEvent.Accessor <<= i_columnIndex;
+ aEvent.Element <<= xColumn;
+
+ m_aContainerListeners.notifyEach( aGuard, &XContainerListener::elementRemoved, aEvent );
+
+ aGuard.unlock();
+
+ // dispose the removed column
+ try
+ {
+ xColumn->dispose();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+ }
+
+
+ Sequence< Reference< XGridColumn > > SAL_CALL DefaultGridColumnModel::getColumns()
+ {
+ std::unique_lock aGuard(m_aMutex);
+ throwIfDisposed(aGuard);
+ return ::comphelper::containerToSequence<Reference<XGridColumn>>( m_aColumns );
+ }
+
+
+ Reference< XGridColumn > SAL_CALL DefaultGridColumnModel::getColumn(::sal_Int32 index)
+ {
+ std::unique_lock aGuard(m_aMutex);
+ throwIfDisposed(aGuard);
+
+ 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;
+
+ std::unique_lock aGuard(m_aMutex);
+ throwIfDisposed(aGuard);
+
+ // 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 <<= Reference<XGridColumn>(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();
+ 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 <<= Reference<XGridColumn>(pGridColumn);
+ aInsertedColumns.push_back( aEvent );
+
+ m_aColumns.push_back( pGridColumn );
+ pGridColumn->setIndex( i );
+ }
+
+ // fire removal notifications
+ for (const auto& rEvent : aRemovedColumns)
+ {
+ m_aContainerListeners.notifyEach( aGuard, &XContainerListener::elementRemoved, rEvent );
+ }
+
+ // fire insertion notifications
+ for (const auto& rEvent : aInsertedColumns)
+ {
+ m_aContainerListeners.notifyEach( aGuard, &XContainerListener::elementInserted, rEvent );
+ }
+
+ aGuard.unlock();
+
+ // dispose removed columns
+ for (const auto& rEvent : aRemovedColumns)
+ {
+ try
+ {
+ const Reference< XComponent > xColComp( rEvent.Element, UNO_QUERY );
+ if (xColComp)
+ 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 )
+ {
+ std::unique_lock aGuard(m_aMutex);
+ if ( i_listener.is() )
+ m_aContainerListeners.addInterface( aGuard, i_listener );
+ }
+
+
+ void SAL_CALL DefaultGridColumnModel::removeContainerListener( const Reference< XContainerListener >& i_listener )
+ {
+ std::unique_lock aGuard(m_aMutex);
+ if ( i_listener.is() )
+ m_aContainerListeners.removeInterface( aGuard, i_listener );
+ }
+
+
+ void DefaultGridColumnModel::disposing( std::unique_lock<std::mutex>& rGuard )
+ {
+ DefaultGridColumnModel_Base::disposing(rGuard);
+
+ EventObject aEvent( *this );
+ m_aContainerListeners.disposeAndClear( rGuard, aEvent );
+
+ // remove, dispose and clear columns
+ while ( !m_aColumns.empty() )
+ {
+ try
+ {
+ m_aColumns[ 0 ]->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( )
+ {
+ std::unique_lock aGuard(m_aMutex);
+ throwIfDisposed(aGuard);
+ 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 0000000000..3b803d4a2e
--- /dev/null
+++ b/toolkit/source/controls/grid/defaultgriddatamodel.cxx
@@ -0,0 +1,512 @@
+/* -*- 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/compbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <o3tl/safeint.hxx>
+#include <osl/diagnose.h>
+
+#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 ::comphelper::WeakComponentImplHelper < XMutableGridDataModel
+ , XServiceInfo
+ > DefaultGridDataModel_Base;
+
+class DefaultGridDataModel: 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 disposing( std::unique_lock<std::mutex>& ) 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 & ),
+ std::unique_lock<std::mutex>& i_instanceLock
+ );
+
+ void impl_insertRow( std::unique_lock<std::mutex>& rGuard, sal_Int32 const i_position, Any const & i_heading, Sequence< Any > const & i_rowData, sal_Int32 const i_assumedColCount = -1 );
+
+ ::sal_Int32 impl_getRowCount(std::unique_lock<std::mutex>&) const { return sal_Int32( m_aData.size() ); }
+
+ CellData const & impl_getCellData_throw( std::unique_lock<std::mutex>& rGuard, sal_Int32 const i_columnIndex, sal_Int32 const i_rowIndex ) const;
+ CellData& impl_getCellDataAccess_throw( std::unique_lock<std::mutex>& rGuard, sal_Int32 const i_columnIndex, sal_Int32 const i_rowIndex );
+ RowData& impl_getRowDataAccess_throw( std::unique_lock<std::mutex>& rGuard, sal_Int32 const i_rowIndex, size_t const i_requiredColumnCount );
+
+ GridData m_aData;
+ ::std::vector< css::uno::Any > m_aRowHeaders;
+ sal_Int32 m_nColumnCount;
+ comphelper::OInterfaceContainerHelper4<XGridDataListener> maGridDataListeners;
+};
+
+ DefaultGridDataModel::DefaultGridDataModel()
+ :m_nColumnCount(0)
+ {
+ }
+
+
+ DefaultGridDataModel::DefaultGridDataModel( DefaultGridDataModel const & i_copySource )
+ :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 & ), std::unique_lock<std::mutex>& i_instanceLock )
+ {
+ maGridDataListeners.notifyEach( i_instanceLock, i_listenerMethod, i_event );
+ }
+
+
+ ::sal_Int32 SAL_CALL DefaultGridDataModel::getRowCount()
+ {
+ std::unique_lock aGuard(m_aMutex);
+ throwIfDisposed(aGuard);
+ return impl_getRowCount(aGuard);
+ }
+
+
+ ::sal_Int32 SAL_CALL DefaultGridDataModel::getColumnCount()
+ {
+ std::unique_lock aGuard(m_aMutex);
+ throwIfDisposed(aGuard);
+ return m_nColumnCount;
+ }
+
+
+ DefaultGridDataModel::CellData const & DefaultGridDataModel::impl_getCellData_throw( std::unique_lock<std::mutex>& /*rGuard*/, 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( std::unique_lock<std::mutex>& /*rGuard*/, 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( std::unique_lock<std::mutex>& rGuard, 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( rGuard, i_rowIndex, size_t( i_columnIndex + 1 ) ) );
+ return rRowData[ i_columnIndex ];
+ }
+
+
+ Any SAL_CALL DefaultGridDataModel::getCellData( ::sal_Int32 i_column, ::sal_Int32 i_row )
+ {
+ std::unique_lock aGuard(m_aMutex);
+ throwIfDisposed(aGuard);
+ return impl_getCellData_throw( aGuard, i_column, i_row ).first;
+ }
+
+
+ Any SAL_CALL DefaultGridDataModel::getCellToolTip( ::sal_Int32 i_column, ::sal_Int32 i_row )
+ {
+ std::unique_lock aGuard(m_aMutex);
+ throwIfDisposed(aGuard);
+ return impl_getCellData_throw( aGuard, i_column, i_row ).second;
+ }
+
+
+ Any SAL_CALL DefaultGridDataModel::getRowHeading( ::sal_Int32 i_row )
+ {
+ std::unique_lock aGuard(m_aMutex);
+ throwIfDisposed(aGuard);
+
+ 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 )
+ {
+ std::unique_lock aGuard(m_aMutex);
+ throwIfDisposed(aGuard);
+
+ Sequence< Any > resultData( m_nColumnCount );
+ RowData& rRowData = impl_getRowDataAccess_throw( aGuard, i_rowIndex, m_nColumnCount );
+
+ ::std::transform( rRowData.begin(), rRowData.end(), resultData.getArray(),
+ [] ( const CellData& rCellData )
+ { return rCellData.first; });
+ return resultData;
+ }
+
+
+ void DefaultGridDataModel::impl_insertRow( std::unique_lock<std::mutex>& /*rGuard*/, 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 )
+ {
+ std::unique_lock aGuard(m_aMutex);
+ throwIfDisposed(aGuard);
+
+ if ( ( i_index < 0 ) || ( i_index > impl_getRowCount(aGuard) ) )
+ throw IndexOutOfBoundsException( OUString(), *this );
+
+ // actually insert the row
+ impl_insertRow( aGuard, 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 );
+
+ std::unique_lock aGuard(m_aMutex);
+ throwIfDisposed(aGuard);
+
+ if ( ( i_index < 0 ) || ( i_index > impl_getRowCount(aGuard) ) )
+ 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( aGuard, 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 )
+ {
+ std::unique_lock aGuard(m_aMutex);
+ throwIfDisposed(aGuard);
+
+ 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( )
+ {
+ std::unique_lock aGuard(m_aMutex);
+ throwIfDisposed(aGuard);
+
+ 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 )
+ {
+ std::unique_lock aGuard(m_aMutex);
+ throwIfDisposed(aGuard);
+
+ impl_getCellDataAccess_throw( aGuard, 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 )
+ {
+ std::unique_lock aGuard(m_aMutex);
+ throwIfDisposed(aGuard);
+
+ 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 )
+ {
+ std::unique_lock aGuard(m_aMutex);
+ throwIfDisposed(aGuard);
+
+ 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 )
+ {
+ std::unique_lock aGuard(m_aMutex);
+ throwIfDisposed(aGuard);
+ impl_getCellDataAccess_throw( aGuard, i_columnIndex, i_rowIndex ).second = i_value;
+ }
+
+
+ void SAL_CALL DefaultGridDataModel::updateRowToolTip( ::sal_Int32 i_rowIndex, const Any& i_value )
+ {
+ std::unique_lock aGuard(m_aMutex);
+ throwIfDisposed(aGuard);
+
+ RowData& rRowData = impl_getRowDataAccess_throw( aGuard, i_rowIndex, m_nColumnCount );
+ for ( auto& rCell : rRowData )
+ rCell.second = i_value;
+ }
+
+
+ void SAL_CALL DefaultGridDataModel::addGridDataListener( const Reference< grid::XGridDataListener >& i_listener )
+ {
+ std::unique_lock aGuard(m_aMutex);
+ maGridDataListeners.addInterface( aGuard, i_listener );
+ }
+
+
+ void SAL_CALL DefaultGridDataModel::removeGridDataListener( const Reference< grid::XGridDataListener >& i_listener )
+ {
+ std::unique_lock aGuard(m_aMutex);
+ maGridDataListeners.removeInterface( aGuard, i_listener );
+ }
+
+
+ void DefaultGridDataModel::disposing(std::unique_lock<std::mutex>& rGuard)
+ {
+ css::lang::EventObject aEvent;
+ aEvent.Source.set( *this );
+ maGridDataListeners.disposeAndClear(rGuard, aEvent);
+
+ 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 0000000000..92d28ce9c8
--- /dev/null
+++ b/toolkit/source/controls/grid/gridcolumn.cxx
@@ -0,0 +1,287 @@
+/* -*- 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( getXWeak() );
+ 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 );
+ }
+}
+
+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 0000000000..13c8792271
--- /dev/null
+++ b/toolkit/source/controls/grid/gridcolumn.hxx
@@ -0,0 +1,122 @@
+/* -*- 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/style/HorizontalAlignment.hpp>
+
+#include <comphelper/compbase.hxx>
+#include <comphelper/interfacecontainer4.hxx>
+
+namespace toolkit
+{
+
+typedef comphelper::WeakComponentImplHelper < css::awt::grid::XGridColumn
+ , css::lang::XServiceInfo
+ > 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;
+
+ // 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(), getXWeak() );
+ 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 0000000000..39f4abf531
--- /dev/null
+++ b/toolkit/source/controls/grid/gridcontrol.cxx
@@ -0,0 +1,462 @@
+/* -*- 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 <helper/property.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#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 );
+ std::unique_lock aGuard(m_aMutex);
+ UnoControlModel::setFastPropertyValue_NoBroadcast( aGuard, 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( aGuard, 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 );
+ if (xComponent)
+ 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 UnoGridModel::setFastPropertyValue_NoBroadcast( std::unique_lock<std::mutex>& rGuard, sal_Int32 nHandle, const Any& rValue )
+{
+ Any aOldSubModel;
+ if ( ( nHandle == BASEPROPERTY_GRID_COLUMNMODEL ) || ( nHandle == BASEPROPERTY_GRID_DATAMODEL ) )
+ {
+ getFastPropertyValue( rGuard, aOldSubModel, 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( rGuard, 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 = getXWeak();
+ 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 0000000000..9b7eae0eaa
--- /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/implbase2.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& 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 setFastPropertyValue_NoBroadcast( std::unique_lock<std::mutex>& rGuard, 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::AggImplInheritanceHelper2 < 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 0000000000..5baf5fdda3
--- /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 0000000000..9578e62ee0
--- /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 0000000000..5eac49f475
--- /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 <comphelper/diagnose_ex.hxx>
+#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 0000000000..e46a607ef3
--- /dev/null
+++ b/toolkit/source/controls/roadmapcontrol.cxx
@@ -0,0 +1,504 @@
+/* -*- 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 <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
+
+ // = 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( )
+ {
+ return cppu::getXWeak(new ORoadmapEntry());
+ }
+
+
+ Reference< XInterface > SAL_CALL UnoControlRoadmapModel::createInstanceWithArguments( const Sequence< Any >& /*aArguments*/ )
+ {
+ // Todo: implementation of the arguments handling
+ return cppu::getXWeak(new ORoadmapEntry());
+ }
+
+
+ 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()))
+ throw IndexOutOfBoundsException();
+ 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()) )
+ throw IndexOutOfBoundsException();
+ if ( !xRoadmapItem.is() )
+ throw IllegalArgumentException();
+ Reference< XServiceInfo > xServiceInfo( xRoadmapItem, UNO_QUERY );
+ bool bIsRoadmapItem = xServiceInfo->supportsService("com.sun.star.awt.RoadmapItem");
+ if ( !bIsRoadmapItem )
+ throw IllegalArgumentException();
+ }
+
+
+ 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))
+ throw IndexOutOfBoundsException();
+ 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()))
+ throw IndexOutOfBoundsException();
+ 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 )
+
+css::uno::Any UnoRoadmapControl::queryAggregation(css::uno::Type const & aType) {
+ auto ret = UnoControlRoadmap_Base::queryAggregation(aType);
+ if (!ret.hasValue()) {
+ ret = UnoControlRoadmap_IBase::queryInterface(aType);
+ }
+ return ret;
+}
+
+
+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 = getXWeak();
+ 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 0000000000..3de60f7071
--- /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 0000000000..851d624a3d
--- /dev/null
+++ b/toolkit/source/controls/spinningprogress.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 <com/sun/star/uno/XComponentContext.hpp>
+#include <controls/animatedimages.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#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(const SpinningProgressControlModel& rOther) : SpinningProgressControlModel_Base(rOther) {}
+
+ 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 0000000000..bac4aea585
--- /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 OUString aTabStopName = u"Tabstop"_ustr;
+
+ 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 = dynamic_cast<VCLXWindow*>( xCP.get() );
+ 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 0000000000..43fd80f170
--- /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 0000000000..1bc51155f7
--- /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::XVclWindowPeer> MultiLineEdit::GetComponentInterface(bool bCreate)
+{
+ css::uno::Reference<css::awt::XVclWindowPeer> 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/svtxgridcontrol.cxx b/toolkit/source/controls/svtxgridcontrol.cxx
new file mode 100644
index 0000000000..1ca789db9a
--- /dev/null
+++ b/toolkit/source/controls/svtxgridcontrol.cxx
@@ -0,0 +1,911 @@
+/* -*- 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 <cppuhelper/implbase.hxx>
+#include <toolkit/helper/listenermultiplexer.hxx>
+#include <com/sun/star/view/SelectionType.hpp>
+#include <controls/table/tablecontrol.hxx>
+#include <controls/table/tablecontrolinterface.hxx>
+#include <controls/table/gridtablerenderer.hxx>
+#include "unocontroltablemodel.hxx"
+#include <sal/log.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <helper/property.hxx>
+#include <com/sun/star/awt/grid/XGridColumn.hpp>
+#include <com/sun/star/awt/grid/GridInvalidDataException.hpp>
+#include <com/sun/star/awt/grid/GridInvalidModelException.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/util/Color.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+
+#include <vcl/svapp.hxx>
+
+#include <algorithm>
+
+using css::uno::Reference;
+using css::uno::Exception;
+using css::uno::UNO_QUERY;
+using css::uno::UNO_QUERY_THROW;
+using css::uno::Any;
+using css::uno::Sequence;
+using css::awt::grid::XGridSelectionListener;
+using css::style::VerticalAlignment;
+using css::style::VerticalAlignment_TOP;
+using css::view::SelectionType;
+using css::view::SelectionType_NONE;
+using css::view::SelectionType_RANGE;
+using css::view::SelectionType_SINGLE;
+using css::view::SelectionType_MULTI;
+using css::awt::grid::XGridDataModel;
+using css::awt::grid::GridInvalidDataException;
+using css::lang::EventObject;
+using css::lang::IndexOutOfBoundsException;
+using css::awt::grid::XGridColumnModel;
+using css::awt::grid::GridSelectionEvent;
+using css::awt::grid::XGridColumn;
+using css::container::ContainerEvent;
+using css::awt::grid::GridDataEvent;
+using css::awt::grid::GridInvalidModelException;
+
+namespace AccessibleEventId = css::accessibility::AccessibleEventId;
+namespace AccessibleStateType = css::accessibility::AccessibleStateType;
+
+using namespace ::svt::table;
+
+
+SVTXGridControl::SVTXGridControl()
+ :m_xTableModel( std::make_shared<UnoControlTableModel>() )
+ ,m_bTableModelInitCompleted( false )
+ ,m_aSelectionListeners( *this )
+{
+}
+
+
+SVTXGridControl::~SVTXGridControl()
+{
+}
+
+
+void SVTXGridControl::SetWindow( const VclPtr< vcl::Window > &pWindow )
+{
+ SVTXGridControl_Base::SetWindow( pWindow );
+ impl_checkTableModelInit();
+}
+
+
+void SVTXGridControl::impl_checkColumnIndex_throw( ::svt::table::TableControl const & i_table, sal_Int32 const i_columnIndex ) const
+{
+ if ( ( i_columnIndex < 0 ) || ( i_columnIndex >= i_table.GetColumnCount() ) )
+ throw IndexOutOfBoundsException( OUString(), *const_cast< SVTXGridControl* >( this ) );
+}
+
+
+void SVTXGridControl::impl_checkRowIndex_throw( ::svt::table::TableControl const & i_table, sal_Int32 const i_rowIndex ) const
+{
+ if ( ( i_rowIndex < 0 ) || ( i_rowIndex >= i_table.GetRowCount() ) )
+ throw IndexOutOfBoundsException( OUString(), *const_cast< SVTXGridControl* >( this ) );
+}
+
+
+sal_Int32 SAL_CALL SVTXGridControl::getRowAtPoint(::sal_Int32 x, ::sal_Int32 y)
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TableControl > pTable = GetAsDynamic< TableControl >();
+ ENSURE_OR_RETURN( pTable, "SVTXGridControl::getRowAtPoint: no control (anymore)!", -1 );
+
+ TableCell const tableCell = pTable->getTableControlInterface().hitTest( Point( x, y ) );
+ return ( tableCell.nRow >= 0 ) ? tableCell.nRow : -1;
+}
+
+
+sal_Int32 SAL_CALL SVTXGridControl::getColumnAtPoint(::sal_Int32 x, ::sal_Int32 y)
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TableControl > pTable = GetAsDynamic< TableControl >();
+ ENSURE_OR_RETURN( pTable, "SVTXGridControl::getColumnAtPoint: no control (anymore)!", -1 );
+
+ TableCell const tableCell = pTable->getTableControlInterface().hitTest( Point( x, y ) );
+ return ( tableCell.nColumn >= 0 ) ? tableCell.nColumn : -1;
+}
+
+
+sal_Int32 SAL_CALL SVTXGridControl::getCurrentColumn( )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TableControl > pTable = GetAsDynamic< TableControl >();
+ ENSURE_OR_RETURN( pTable, "SVTXGridControl::getCurrentColumn: no control (anymore)!", -1 );
+
+ sal_Int32 const nColumn = pTable->GetCurrentColumn();
+ return ( nColumn >= 0 ) ? nColumn : -1;
+}
+
+
+sal_Int32 SAL_CALL SVTXGridControl::getCurrentRow( )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TableControl > pTable = GetAsDynamic< TableControl >();
+ ENSURE_OR_RETURN( pTable, "SVTXGridControl::getCurrentRow: no control (anymore)!", -1 );
+
+ sal_Int32 const nRow = pTable->GetCurrentRow();
+ return ( nRow >= 0 ) ? nRow : -1;
+}
+
+
+void SAL_CALL SVTXGridControl::goToCell( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TableControl > pTable = GetAsDynamic< TableControl >();
+ ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::getCurrentRow: no control (anymore)!" );
+
+ impl_checkColumnIndex_throw( *pTable, i_columnIndex );
+ impl_checkRowIndex_throw( *pTable, i_rowIndex );
+
+ pTable->GoTo( i_columnIndex, i_rowIndex );
+}
+
+
+void SAL_CALL SVTXGridControl::addSelectionListener(const Reference< XGridSelectionListener > & listener)
+{
+ m_aSelectionListeners.addInterface(listener);
+}
+
+
+void SAL_CALL SVTXGridControl::removeSelectionListener(const Reference< XGridSelectionListener > & listener)
+{
+ m_aSelectionListeners.removeInterface(listener);
+}
+
+
+void SVTXGridControl::setProperty( const OUString& PropertyName, const Any& aValue)
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TableControl > pTable = GetAsDynamic< TableControl >();
+ ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::setProperty: no control (anymore)!" );
+
+ switch( GetPropertyId( PropertyName ) )
+ {
+ case BASEPROPERTY_ROW_HEADER_WIDTH:
+ {
+ sal_Int32 rowHeaderWidth( -1 );
+ aValue >>= rowHeaderWidth;
+ if ( rowHeaderWidth <= 0 )
+ {
+ SAL_WARN( "svtools.uno", "SVTXGridControl::setProperty: illegal row header width!" );
+ break;
+ }
+
+ m_xTableModel->setRowHeaderWidth( rowHeaderWidth );
+ // TODO: the model should broadcast this change itself, and the table should invalidate itself as needed
+ pTable->Invalidate();
+ }
+ break;
+
+ case BASEPROPERTY_COLUMN_HEADER_HEIGHT:
+ {
+ sal_Int32 columnHeaderHeight = 0;
+ if ( !aValue.hasValue() )
+ {
+ columnHeaderHeight = pTable->PixelToLogic(Size(0, pTable->GetTextHeight() + 3), MapMode(MapUnit::MapAppFont)).Height();
+ }
+ else
+ {
+ aValue >>= columnHeaderHeight;
+ }
+ if ( columnHeaderHeight <= 0 )
+ {
+ SAL_WARN( "svtools.uno", "SVTXGridControl::setProperty: illegal column header width!" );
+ break;
+ }
+
+ m_xTableModel->setColumnHeaderHeight( columnHeaderHeight );
+ // TODO: the model should broadcast this change itself, and the table should invalidate itself as needed
+ pTable->Invalidate();
+ }
+ break;
+
+ case BASEPROPERTY_USE_GRID_LINES:
+ {
+ GridTableRenderer* pGridRenderer = dynamic_cast< GridTableRenderer* >(
+ m_xTableModel->getRenderer().get() );
+ if ( !pGridRenderer )
+ {
+ SAL_WARN( "svtools.uno", "SVTXGridControl::setProperty(UseGridLines): invalid renderer!" );
+ break;
+ }
+
+ bool bUseGridLines = false;
+ OSL_VERIFY( aValue >>= bUseGridLines );
+ pGridRenderer->useGridLines( bUseGridLines );
+ pTable->Invalidate();
+ }
+ break;
+
+ case BASEPROPERTY_ROW_HEIGHT:
+ {
+ sal_Int32 rowHeight = 0;
+ if ( !aValue.hasValue() )
+ {
+ rowHeight = pTable->PixelToLogic(Size(0, pTable->GetTextHeight() + 3), MapMode(MapUnit::MapAppFont)).Height();
+ }
+ else
+ {
+ aValue >>= rowHeight;
+ }
+ m_xTableModel->setRowHeight( rowHeight );
+ if ( rowHeight <= 0 )
+ {
+ SAL_WARN( "svtools.uno", "SVTXGridControl::setProperty: illegal row height!" );
+ break;
+ }
+
+ // TODO: the model should broadcast this change itself, and the table should invalidate itself as needed
+ pTable->Invalidate();
+ }
+ break;
+
+ case BASEPROPERTY_BACKGROUNDCOLOR:
+ {
+ // let the base class handle this for the TableControl
+ VCLXWindow::setProperty( PropertyName, aValue );
+ // and forward to the grid control's data window
+ if ( pTable->IsBackground() )
+ pTable->getDataWindow().SetBackground( pTable->GetBackground() );
+ else
+ pTable->getDataWindow().SetBackground();
+ }
+ break;
+
+ case BASEPROPERTY_GRID_SELECTIONMODE:
+ {
+ 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;
+ default: eSelMode = SelectionMode::NONE; break;
+ }
+ if( pTable->getSelEngine()->GetSelectionMode() != eSelMode )
+ pTable->getSelEngine()->SetSelectionMode( eSelMode );
+ }
+ break;
+ }
+ case BASEPROPERTY_HSCROLL:
+ {
+ bool bHScroll = true;
+ if( aValue >>= bHScroll )
+ m_xTableModel->setHorizontalScrollbarVisibility( bHScroll ? ScrollbarShowAlways : ScrollbarShowSmart );
+ break;
+ }
+
+ case BASEPROPERTY_VSCROLL:
+ {
+ bool bVScroll = true;
+ if( aValue >>= bVScroll )
+ {
+ m_xTableModel->setVerticalScrollbarVisibility( bVScroll ? ScrollbarShowAlways : ScrollbarShowSmart );
+ }
+ break;
+ }
+
+ case BASEPROPERTY_GRID_SHOWROWHEADER:
+ {
+ bool rowHeader = true;
+ if( aValue >>= rowHeader )
+ {
+ m_xTableModel->setRowHeaders(rowHeader);
+ }
+ break;
+ }
+
+ case BASEPROPERTY_GRID_ROW_BACKGROUND_COLORS:
+ m_xTableModel->setRowBackgroundColors( aValue );
+ pTable->Invalidate();
+ break;
+
+ case BASEPROPERTY_GRID_LINE_COLOR:
+ m_xTableModel->setLineColor( aValue );
+ pTable->Invalidate();
+ break;
+
+ case BASEPROPERTY_GRID_HEADER_BACKGROUND:
+ m_xTableModel->setHeaderBackgroundColor( aValue );
+ pTable->Invalidate();
+ break;
+
+ case BASEPROPERTY_GRID_HEADER_TEXT_COLOR:
+ m_xTableModel->setHeaderTextColor( aValue );
+ pTable->Invalidate();
+ break;
+
+ case BASEPROPERTY_ACTIVE_SEL_BACKGROUND_COLOR:
+ m_xTableModel->setActiveSelectionBackColor( aValue );
+ pTable->Invalidate();
+ break;
+
+ case BASEPROPERTY_INACTIVE_SEL_BACKGROUND_COLOR:
+ m_xTableModel->setInactiveSelectionBackColor( aValue );
+ pTable->Invalidate();
+ break;
+
+ case BASEPROPERTY_ACTIVE_SEL_TEXT_COLOR:
+ m_xTableModel->setActiveSelectionTextColor( aValue );
+ pTable->Invalidate();
+ break;
+
+ case BASEPROPERTY_INACTIVE_SEL_TEXT_COLOR:
+ m_xTableModel->setInactiveSelectionTextColor( aValue );
+ pTable->Invalidate();
+ break;
+
+
+ case BASEPROPERTY_TEXTCOLOR:
+ m_xTableModel->setTextColor( aValue );
+ pTable->Invalidate();
+ break;
+
+ case BASEPROPERTY_TEXTLINECOLOR:
+ m_xTableModel->setTextLineColor( aValue );
+ pTable->Invalidate();
+ break;
+
+ case BASEPROPERTY_VERTICALALIGN:
+ {
+ VerticalAlignment eAlign( VerticalAlignment_TOP );
+ if ( aValue >>= eAlign )
+ m_xTableModel->setVerticalAlign( eAlign );
+ break;
+ }
+
+ case BASEPROPERTY_GRID_SHOWCOLUMNHEADER:
+ {
+ bool colHeader = true;
+ if( aValue >>= colHeader )
+ {
+ m_xTableModel->setColumnHeaders(colHeader);
+ }
+ break;
+ }
+ case BASEPROPERTY_GRID_DATAMODEL:
+ {
+ Reference< XGridDataModel > const xDataModel( aValue, UNO_QUERY );
+ if ( !xDataModel.is() )
+ throw GridInvalidDataException("Invalid data model.", *this );
+
+ m_xTableModel->setDataModel( xDataModel );
+ impl_checkTableModelInit();
+ }
+ break;
+
+ case BASEPROPERTY_GRID_COLUMNMODEL:
+ {
+ // obtain new col model
+ Reference< XGridColumnModel > const xColumnModel( aValue, UNO_QUERY );
+ if ( !xColumnModel.is() )
+ throw GridInvalidModelException("Invalid column model.", *this );
+
+ // remove all old columns
+ m_xTableModel->removeAllColumns();
+
+ // announce to the TableModel
+ m_xTableModel->setColumnModel( xColumnModel );
+ impl_checkTableModelInit();
+
+ // add new columns
+ impl_updateColumnsFromModel_nothrow();
+ break;
+ }
+ default:
+ VCLXWindow::setProperty( PropertyName, aValue );
+ break;
+ }
+}
+
+
+void SVTXGridControl::impl_checkTableModelInit()
+{
+ if ( !(!m_bTableModelInitCompleted && m_xTableModel->hasColumnModel() && m_xTableModel->hasDataModel()) )
+ return;
+
+ VclPtr< TableControl > pTable = GetAsDynamic< TableControl >();
+ if ( !pTable )
+ return;
+
+ pTable->SetModel( PTableModel( m_xTableModel ) );
+
+ m_bTableModelInitCompleted = true;
+
+ // ensure default columns exist, if they have not previously been added
+ Reference< XGridDataModel > const xDataModel( m_xTableModel->getDataModel(), css::uno::UNO_SET_THROW );
+ Reference< XGridColumnModel > const xColumnModel( m_xTableModel->getColumnModel(), css::uno::UNO_SET_THROW );
+
+ sal_Int32 const nDataColumnCount = xDataModel->getColumnCount();
+ if ( ( nDataColumnCount > 0 ) && ( xColumnModel->getColumnCount() == 0 ) )
+ xColumnModel->setDefaultColumns( nDataColumnCount );
+ // this will trigger notifications, which in turn will let us update our m_xTableModel
+}
+
+namespace
+{
+ void lcl_convertColor( ::std::optional< ::Color > const & i_color, Any & o_colorValue )
+ {
+ if ( !i_color )
+ o_colorValue.clear();
+ else
+ o_colorValue <<= sal_Int32(*i_color);
+ }
+}
+
+Any SVTXGridControl::getProperty( const OUString& PropertyName )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TableControl > pTable = GetAsDynamic< TableControl >();
+ ENSURE_OR_RETURN( pTable, "SVTXGridControl::getProperty: no control (anymore)!", Any() );
+
+ Any aPropertyValue;
+
+ const sal_uInt16 nPropId = GetPropertyId( PropertyName );
+ switch(nPropId)
+ {
+ case BASEPROPERTY_GRID_SELECTIONMODE:
+ {
+ SelectionType eSelectionType;
+
+ SelectionMode eSelMode = pTable->getSelEngine()->GetSelectionMode();
+ switch( eSelMode )
+ {
+ case SelectionMode::Single: eSelectionType = SelectionType_SINGLE; break;
+ case SelectionMode::Range: eSelectionType = SelectionType_RANGE; break;
+ case SelectionMode::Multiple:eSelectionType = SelectionType_MULTI; break;
+ default: eSelectionType = SelectionType_NONE; break;
+ }
+ aPropertyValue <<= eSelectionType;
+ break;
+ }
+
+ case BASEPROPERTY_GRID_SHOWROWHEADER:
+ aPropertyValue <<= m_xTableModel->hasRowHeaders();
+ break;
+
+ case BASEPROPERTY_GRID_SHOWCOLUMNHEADER:
+ aPropertyValue <<= m_xTableModel->hasColumnHeaders();
+ break;
+
+ case BASEPROPERTY_GRID_DATAMODEL:
+ aPropertyValue <<= m_xTableModel->getDataModel();
+ break;
+
+ case BASEPROPERTY_GRID_COLUMNMODEL:
+ aPropertyValue <<= m_xTableModel->getColumnModel();
+ break;
+
+ case BASEPROPERTY_HSCROLL:
+ {
+ bool const bHasScrollbar = ( m_xTableModel->getHorizontalScrollbarVisibility() != ScrollbarShowNever );
+ aPropertyValue <<= bHasScrollbar;
+ break;
+ }
+
+ case BASEPROPERTY_VSCROLL:
+ {
+ bool const bHasScrollbar = ( m_xTableModel->getVerticalScrollbarVisibility() != ScrollbarShowNever );
+ aPropertyValue <<= bHasScrollbar;
+ break;
+ }
+
+ case BASEPROPERTY_USE_GRID_LINES:
+ {
+ GridTableRenderer* pGridRenderer = dynamic_cast< GridTableRenderer* >(
+ m_xTableModel->getRenderer().get() );
+ if ( !pGridRenderer )
+ {
+ SAL_WARN( "svtools.uno", "SVTXGridControl::getProperty(UseGridLines): invalid renderer!" );
+ break;
+ }
+
+ aPropertyValue <<= pGridRenderer->useGridLines();
+ }
+ break;
+
+ case BASEPROPERTY_GRID_ROW_BACKGROUND_COLORS:
+ {
+ ::std::optional< ::std::vector< ::Color > > aColors( m_xTableModel->getRowBackgroundColors() );
+ if ( !aColors )
+ aPropertyValue.clear();
+ else
+ {
+ Sequence< css::util::Color > aAPIColors( aColors->size() );
+ std::transform(aColors->begin(), aColors->end(), aAPIColors.getArray(),
+ [](const auto& color) { return sal_Int32(color); });
+ aPropertyValue <<= aAPIColors;
+ }
+ }
+ break;
+
+ case BASEPROPERTY_GRID_LINE_COLOR:
+ lcl_convertColor( m_xTableModel->getLineColor(), aPropertyValue );
+ break;
+
+ case BASEPROPERTY_GRID_HEADER_BACKGROUND:
+ lcl_convertColor( m_xTableModel->getHeaderBackgroundColor(), aPropertyValue );
+ break;
+
+ case BASEPROPERTY_GRID_HEADER_TEXT_COLOR:
+ lcl_convertColor( m_xTableModel->getHeaderTextColor(), aPropertyValue );
+ break;
+
+ case BASEPROPERTY_ACTIVE_SEL_BACKGROUND_COLOR:
+ lcl_convertColor( m_xTableModel->getActiveSelectionBackColor(), aPropertyValue );
+ break;
+
+ case BASEPROPERTY_INACTIVE_SEL_BACKGROUND_COLOR:
+ lcl_convertColor( m_xTableModel->getInactiveSelectionBackColor(), aPropertyValue );
+ break;
+
+ case BASEPROPERTY_ACTIVE_SEL_TEXT_COLOR:
+ lcl_convertColor( m_xTableModel->getActiveSelectionTextColor(), aPropertyValue );
+ break;
+
+ case BASEPROPERTY_INACTIVE_SEL_TEXT_COLOR:
+ lcl_convertColor( m_xTableModel->getInactiveSelectionTextColor(), aPropertyValue );
+ break;
+
+ case BASEPROPERTY_TEXTCOLOR:
+ lcl_convertColor( m_xTableModel->getTextColor(), aPropertyValue );
+ break;
+
+ case BASEPROPERTY_TEXTLINECOLOR:
+ lcl_convertColor( m_xTableModel->getTextLineColor(), aPropertyValue );
+ break;
+
+ default:
+ aPropertyValue = VCLXWindow::getProperty( PropertyName );
+ break;
+ }
+
+ return aPropertyValue;
+}
+
+
+void SAL_CALL SVTXGridControl::rowsInserted( const GridDataEvent& i_event )
+{
+ SolarMutexGuard aGuard;
+ m_xTableModel->notifyRowsInserted( i_event );
+}
+
+
+void SAL_CALL
+ SVTXGridControl::rowsRemoved( const GridDataEvent& i_event )
+{
+ SolarMutexGuard aGuard;
+ m_xTableModel->notifyRowsRemoved( i_event );
+}
+
+
+void SAL_CALL SVTXGridControl::dataChanged( const GridDataEvent& i_event )
+{
+ SolarMutexGuard aGuard;
+
+ m_xTableModel->notifyDataChanged( i_event );
+
+ // if the data model is sortable, a dataChanged event is also fired in case the sort order changed.
+ // So, just in case, invalidate the column header area, too.
+ VclPtr< TableControl > pTable = GetAsDynamic< TableControl >();
+ ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::dataChanged: no control (anymore)!" );
+ pTable->getTableControlInterface().invalidate( TableArea::ColumnHeaders );
+}
+
+
+void SAL_CALL SVTXGridControl::rowHeadingChanged( const GridDataEvent& )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TableControl > pTable = GetAsDynamic< TableControl >();
+ ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::rowHeadingChanged: no control (anymore)!" );
+
+ // TODO: we could do better than this - invalidate the header area only
+ pTable->getTableControlInterface().invalidate( TableArea::RowHeaders );
+}
+
+
+void SAL_CALL SVTXGridControl::elementInserted( const ContainerEvent& i_event )
+{
+ SolarMutexGuard aGuard;
+
+ Reference< XGridColumn > const xGridColumn( i_event.Element, UNO_QUERY_THROW );
+
+ sal_Int32 nIndex( m_xTableModel->getColumnCount() );
+ OSL_VERIFY( i_event.Accessor >>= nIndex );
+ m_xTableModel->insertColumn( nIndex, xGridColumn );
+}
+
+
+void SAL_CALL SVTXGridControl::elementRemoved( const ContainerEvent& i_event )
+{
+ SolarMutexGuard aGuard;
+
+ sal_Int32 nIndex( -1 );
+ OSL_VERIFY( i_event.Accessor >>= nIndex );
+ m_xTableModel->removeColumn( nIndex );
+}
+
+
+void SAL_CALL SVTXGridControl::elementReplaced( const ContainerEvent& )
+{
+ OSL_ENSURE( false, "SVTXGridControl::elementReplaced: not implemented!" );
+ // at the moment, the XGridColumnModel API does not allow replacing columns
+ // TODO: replace the respective column in our table model
+}
+
+
+void SAL_CALL SVTXGridControl::disposing( const EventObject& Source )
+{
+ VCLXWindow::disposing( Source );
+}
+
+
+void SAL_CALL SVTXGridControl::selectRow( ::sal_Int32 i_rowIndex )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TableControl > pTable = GetAsDynamic< TableControl >();
+ ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::selectRow: no control (anymore)!" );
+
+ impl_checkRowIndex_throw( *pTable, i_rowIndex );
+
+ pTable->SelectRow( i_rowIndex, true );
+}
+
+
+void SAL_CALL SVTXGridControl::selectAllRows()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TableControl > pTable = GetAsDynamic< TableControl >();
+ ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::selectAllRows: no control (anymore)!" );
+
+ pTable->SelectAllRows( true );
+}
+
+
+void SAL_CALL SVTXGridControl::deselectRow( ::sal_Int32 i_rowIndex )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TableControl > pTable = GetAsDynamic< TableControl >();
+ ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::deselectRow: no control (anymore)!" );
+
+ impl_checkRowIndex_throw( *pTable, i_rowIndex );
+
+ pTable->SelectRow( i_rowIndex, false );
+}
+
+
+void SAL_CALL SVTXGridControl::deselectAllRows()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TableControl > pTable = GetAsDynamic< TableControl >();
+ ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::deselectAllRows: no control (anymore)!" );
+
+ pTable->SelectAllRows( false );
+}
+
+
+Sequence< ::sal_Int32 > SAL_CALL SVTXGridControl::getSelectedRows()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TableControl > pTable = GetAsDynamic< TableControl >();
+ ENSURE_OR_RETURN( pTable, "SVTXGridControl::getSelectedRows: no control (anymore)!", Sequence< sal_Int32 >() );
+
+ sal_Int32 selectionCount = pTable->GetSelectedRowCount();
+ Sequence< sal_Int32 > selectedRows( selectionCount );
+ auto selectedRowsRange = asNonConstRange(selectedRows);
+ for ( sal_Int32 i=0; i<selectionCount; ++i )
+ selectedRowsRange[i] = pTable->GetSelectedRowIndex(i);
+ return selectedRows;
+}
+
+
+sal_Bool SAL_CALL SVTXGridControl::hasSelectedRows()
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TableControl > pTable = GetAsDynamic< TableControl >();
+ ENSURE_OR_RETURN( pTable, "SVTXGridControl::hasSelectedRows: no control (anymore)!", true );
+
+ return pTable->GetSelectedRowCount() > 0;
+}
+
+
+sal_Bool SAL_CALL SVTXGridControl::isRowSelected( ::sal_Int32 index )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr< TableControl > pTable = GetAsDynamic< TableControl >();
+ ENSURE_OR_RETURN( pTable, "SVTXGridControl::isRowSelected: no control (anymore)!", false );
+
+ return pTable->IsRowSelected( index );
+}
+
+
+void SVTXGridControl::dispose()
+{
+ EventObject aObj;
+ aObj.Source = getXWeak();
+ m_aSelectionListeners.disposeAndClear( aObj );
+ VCLXWindow::dispose();
+}
+
+
+void SVTXGridControl::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
+{
+ SolarMutexGuard aGuard;
+
+ Reference< XWindow > xKeepAlive( this );
+
+ VclPtr< TableControl > pTable = GetAsDynamic< TableControl >();
+ ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::ProcessWindowEvent: no control (anymore)!" );
+
+ bool handled = false;
+ switch ( rVclWindowEvent.GetId() )
+ {
+ case VclEventId::TableRowSelect:
+ {
+ if ( m_aSelectionListeners.getLength() )
+ ImplCallItemListeners();
+ handled = true;
+ }
+ break;
+
+ case VclEventId::ControlGetFocus:
+ {
+ // TODO: this doesn't belong here. It belongs into the TableControl/_Impl, so A11Y also
+ // works when the control is used outside the UNO context
+ if ( pTable->GetRowCount()>0 )
+ {
+ pTable->commitCellEventIfAccessibleAlive(
+ AccessibleEventId::STATE_CHANGED,
+ Any( AccessibleStateType::FOCUSED ),
+ Any()
+ );
+ pTable->commitTableEventIfAccessibleAlive(
+ AccessibleEventId::ACTIVE_DESCENDANT_CHANGED,
+ Any(),
+ Any()
+ );
+ }
+ else
+ {
+ pTable->commitTableEventIfAccessibleAlive(
+ AccessibleEventId::STATE_CHANGED,
+ Any( AccessibleStateType::FOCUSED ),
+ Any()
+ );
+ }
+ }
+ break;
+
+ case VclEventId::ControlLoseFocus:
+ {
+ // TODO: this doesn't belong here. It belongs into the TableControl/_Impl, so A11Y also
+ // works when the control is used outside the UNO context
+ if ( pTable->GetRowCount()>0 )
+ {
+ pTable->commitCellEventIfAccessibleAlive(
+ AccessibleEventId::STATE_CHANGED,
+ Any(),
+ Any( AccessibleStateType::FOCUSED )
+ );
+ }
+ else
+ {
+ pTable->commitTableEventIfAccessibleAlive(
+ AccessibleEventId::STATE_CHANGED,
+ Any(),
+ Any( AccessibleStateType::FOCUSED )
+ );
+ }
+ }
+ break;
+
+ default: break;
+ }
+
+ if ( !handled )
+ VCLXWindow::ProcessWindowEvent( rVclWindowEvent );
+}
+
+
+void SVTXGridControl::setEnable( sal_Bool bEnable )
+{
+ SolarMutexGuard aGuard;
+
+ m_xTableModel->setEnabled( bEnable );
+ VclPtr<vcl::Window> pWindow = GetWindow();
+ if ( pWindow )
+ {
+ pWindow->Enable( bEnable );
+ pWindow->EnableInput( bEnable );
+ pWindow->Invalidate();
+ }
+}
+
+
+void SVTXGridControl::ImplCallItemListeners()
+{
+ VclPtr< TableControl > pTable = GetAsDynamic< TableControl >();
+ ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::ImplCallItemListeners: no control (anymore)!" );
+
+ if ( m_aSelectionListeners.getLength() )
+ {
+ GridSelectionEvent aEvent;
+ aEvent.Source = getXWeak();
+
+ sal_Int32 const nSelectedRowCount( pTable->GetSelectedRowCount() );
+ aEvent.SelectedRowIndexes.realloc( nSelectedRowCount );
+ auto pSelectedRowIndexes = aEvent.SelectedRowIndexes.getArray();
+ for ( sal_Int32 i=0; i<nSelectedRowCount; ++i )
+ pSelectedRowIndexes[i] = pTable->GetSelectedRowIndex( i );
+ m_aSelectionListeners.selectionChanged( aEvent );
+ }
+}
+
+
+void SVTXGridControl::impl_updateColumnsFromModel_nothrow()
+{
+ Reference< XGridColumnModel > const xColumnModel( m_xTableModel->getColumnModel() );
+ ENSURE_OR_RETURN_VOID( xColumnModel.is(), "no model!" );
+ VclPtr< TableControl > pTable = GetAsDynamic< TableControl >();
+ ENSURE_OR_RETURN_VOID( pTable, "no table!" );
+
+ try
+ {
+ const Sequence< Reference< XGridColumn > > columns = xColumnModel->getColumns();
+ for ( auto const & colRef : columns )
+ {
+ if ( !colRef.is() )
+ {
+ SAL_WARN( "svtools.uno", "illegal column!" );
+ continue;
+ }
+
+ m_xTableModel->appendColumn( colRef );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.uno");
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/table/cellvalueconversion.cxx b/toolkit/source/controls/table/cellvalueconversion.cxx
new file mode 100644
index 0000000000..e07ef35494
--- /dev/null
+++ b/toolkit/source/controls/table/cellvalueconversion.cxx
@@ -0,0 +1,376 @@
+/* -*- 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 "cellvalueconversion.hxx"
+
+#include <com/sun/star/util/NumberFormatsSupplier.hpp>
+#include <com/sun/star/util/NumberFormatter.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/util/Time.hpp>
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/util/XNumberFormatTypes.hpp>
+#include <com/sun/star/util/NumberFormat.hpp>
+#include <sal/log.hxx>
+#include <tools/date.hxx>
+#include <tools/time.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <tools/long.hxx>
+#include <unotools/syslocale.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <comphelper/processfactory.hxx>
+
+#include <limits>
+#include <memory>
+
+namespace svt
+{
+using namespace ::com::sun::star::uno;
+using ::com::sun::star::util::XNumberFormatter;
+using ::com::sun::star::util::NumberFormatter;
+using ::com::sun::star::util::XNumberFormatsSupplier;
+using ::com::sun::star::util::NumberFormatsSupplier;
+using ::com::sun::star::beans::XPropertySet;
+using ::com::sun::star::lang::Locale;
+using ::com::sun::star::util::DateTime;
+using ::com::sun::star::util::XNumberFormatTypes;
+
+namespace NumberFormat = ::com::sun::star::util::NumberFormat;
+
+//= helper
+
+namespace
+{
+double lcl_convertDateToDays(sal_uInt16 const i_day, sal_uInt16 const i_month,
+ sal_Int16 const i_year)
+{
+ tools::Long const nNullDateDays = ::Date::DateToDays(1, 1, 1900);
+ tools::Long const nValueDateDays = ::Date::DateToDays(i_day, i_month, i_year);
+
+ return nValueDateDays - nNullDateDays;
+}
+
+double lcl_convertTimeToDays(tools::Long const i_hours, tools::Long const i_minutes,
+ tools::Long const i_seconds, tools::Long const i_100thSeconds)
+{
+ return tools::Time(i_hours, i_minutes, i_seconds, i_100thSeconds).GetTimeInDays();
+}
+}
+
+//= StandardFormatNormalizer
+
+StandardFormatNormalizer::StandardFormatNormalizer(Reference<XNumberFormatter> const& i_formatter,
+ ::sal_Int32 const i_numberFormatType)
+ : m_nFormatKey(0)
+{
+ try
+ {
+ ENSURE_OR_THROW(i_formatter.is(), "StandardFormatNormalizer: no formatter!");
+ Reference<XNumberFormatsSupplier> const xSupplier(i_formatter->getNumberFormatsSupplier(),
+ UNO_SET_THROW);
+ Reference<XNumberFormatTypes> const xTypes(xSupplier->getNumberFormats(), UNO_QUERY_THROW);
+ m_nFormatKey = xTypes->getStandardFormat(i_numberFormatType,
+ SvtSysLocale().GetLanguageTag().getLocale());
+ }
+ catch (const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.table");
+ }
+}
+
+//= DoubleNormalization
+
+namespace
+{
+class DoubleNormalization : public StandardFormatNormalizer
+{
+public:
+ explicit DoubleNormalization(Reference<XNumberFormatter> const& i_formatter)
+ : StandardFormatNormalizer(i_formatter, NumberFormat::NUMBER)
+ {
+ }
+
+ virtual double convertToDouble(Any const& i_value) const override
+ {
+ double returnValue = std::numeric_limits<double>::quiet_NaN();
+ OSL_VERIFY(i_value >>= returnValue);
+ return returnValue;
+ }
+};
+
+//= IntegerNormalization
+
+class IntegerNormalization : public StandardFormatNormalizer
+{
+public:
+ explicit IntegerNormalization(Reference<XNumberFormatter> const& i_formatter)
+ : StandardFormatNormalizer(i_formatter, NumberFormat::NUMBER)
+ {
+ }
+
+ virtual double convertToDouble(Any const& i_value) const override
+ {
+ sal_Int64 value(0);
+ OSL_VERIFY(i_value >>= value);
+ return value;
+ }
+};
+
+//= BooleanNormalization
+
+class BooleanNormalization : public StandardFormatNormalizer
+{
+public:
+ explicit BooleanNormalization(Reference<XNumberFormatter> const& i_formatter)
+ : StandardFormatNormalizer(i_formatter, NumberFormat::LOGICAL)
+ {
+ }
+
+ virtual double convertToDouble(Any const& i_value) const override
+ {
+ bool value(false);
+ OSL_VERIFY(i_value >>= value);
+ return value ? 1 : 0;
+ }
+};
+
+//= DateTimeNormalization
+
+class DateTimeNormalization : public StandardFormatNormalizer
+{
+public:
+ explicit DateTimeNormalization(Reference<XNumberFormatter> const& i_formatter)
+ : StandardFormatNormalizer(i_formatter, NumberFormat::DATETIME)
+ {
+ }
+
+ virtual double convertToDouble(Any const& i_value) const override
+ {
+ double returnValue = std::numeric_limits<double>::quiet_NaN();
+
+ // extract actual UNO value
+ DateTime aDateTimeValue;
+ ENSURE_OR_RETURN(i_value >>= aDateTimeValue, "allowed for DateTime values only",
+ returnValue);
+
+ // date part
+ returnValue
+ = lcl_convertDateToDays(aDateTimeValue.Day, aDateTimeValue.Month, aDateTimeValue.Year);
+
+ // time part
+ returnValue += lcl_convertTimeToDays(aDateTimeValue.Hours, aDateTimeValue.Minutes,
+ aDateTimeValue.Seconds, aDateTimeValue.NanoSeconds);
+
+ // done
+ return returnValue;
+ }
+};
+
+//= DateNormalization
+
+class DateNormalization : public StandardFormatNormalizer
+{
+public:
+ explicit DateNormalization(Reference<XNumberFormatter> const& i_formatter)
+ : StandardFormatNormalizer(i_formatter, NumberFormat::DATE)
+ {
+ }
+
+ virtual double convertToDouble(Any const& i_value) const override
+ {
+ double returnValue = std::numeric_limits<double>::quiet_NaN();
+
+ // extract
+ css::util::Date aDateValue;
+ ENSURE_OR_RETURN(i_value >>= aDateValue, "allowed for Date values only", returnValue);
+
+ // convert
+ returnValue = lcl_convertDateToDays(aDateValue.Day, aDateValue.Month, aDateValue.Year);
+
+ // done
+ return returnValue;
+ }
+};
+
+//= TimeNormalization
+
+class TimeNormalization : public StandardFormatNormalizer
+{
+public:
+ explicit TimeNormalization(Reference<XNumberFormatter> const& i_formatter)
+ : StandardFormatNormalizer(i_formatter, NumberFormat::TIME)
+ {
+ }
+
+ virtual double convertToDouble(Any const& i_value) const override
+ {
+ double returnValue = std::numeric_limits<double>::quiet_NaN();
+
+ // extract
+ css::util::Time aTimeValue;
+ ENSURE_OR_RETURN(i_value >>= aTimeValue, "allowed for tools::Time values only",
+ returnValue);
+
+ // convert
+ returnValue += lcl_convertTimeToDays(aTimeValue.Hours, aTimeValue.Minutes,
+ aTimeValue.Seconds, aTimeValue.NanoSeconds);
+
+ // done
+ return returnValue;
+ }
+};
+}
+
+//= operations
+
+bool CellValueConversion::ensureNumberFormatter()
+{
+ if (bAttemptedFormatterCreation)
+ return xNumberFormatter.is();
+ bAttemptedFormatterCreation = true;
+
+ try
+ {
+ Reference<XComponentContext> xContext = ::comphelper::getProcessComponentContext();
+ // a number formatter
+ Reference<XNumberFormatter> const xFormatter(NumberFormatter::create(xContext),
+ UNO_QUERY_THROW);
+
+ // a supplier of number formats
+ Locale aLocale = SvtSysLocale().GetLanguageTag().getLocale();
+
+ Reference<XNumberFormatsSupplier> const xSupplier
+ = NumberFormatsSupplier::createWithLocale(xContext, aLocale);
+
+ // ensure a NullDate we will assume later on
+ css::util::Date const aNullDate(1, 1, 1900);
+ Reference<XPropertySet> const xFormatSettings(xSupplier->getNumberFormatSettings(),
+ UNO_SET_THROW);
+ xFormatSettings->setPropertyValue("NullDate", Any(aNullDate));
+
+ // knit
+ xFormatter->attachNumberFormatsSupplier(xSupplier);
+
+ // done
+ xNumberFormatter = xFormatter;
+ }
+ catch (const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.table");
+ }
+
+ return xNumberFormatter.is();
+}
+
+bool CellValueConversion::getValueNormalizer(Type const& i_valueType,
+ std::shared_ptr<StandardFormatNormalizer>& o_formatter)
+{
+ auto pos = aNormalizers.find(i_valueType.getTypeName());
+ if (pos == aNormalizers.end())
+ {
+ // never encountered this type before
+ o_formatter.reset();
+
+ OUString const sTypeName(i_valueType.getTypeName());
+ TypeClass const eTypeClass = i_valueType.getTypeClass();
+
+ if (sTypeName == ::cppu::UnoType<DateTime>::get().getTypeName())
+ {
+ o_formatter = std::make_shared<DateTimeNormalization>(xNumberFormatter);
+ }
+ else if (sTypeName == ::cppu::UnoType<css::util::Date>::get().getTypeName())
+ {
+ o_formatter = std::make_shared<DateNormalization>(xNumberFormatter);
+ }
+ else if (sTypeName == ::cppu::UnoType<css::util::Time>::get().getTypeName())
+ {
+ o_formatter = std::make_shared<TimeNormalization>(xNumberFormatter);
+ }
+ else if (sTypeName == ::cppu::UnoType<sal_Bool>::get().getTypeName())
+ {
+ o_formatter = std::make_shared<BooleanNormalization>(xNumberFormatter);
+ }
+ else if (sTypeName == ::cppu::UnoType<double>::get().getTypeName()
+ || sTypeName == ::cppu::UnoType<float>::get().getTypeName())
+ {
+ o_formatter = std::make_shared<DoubleNormalization>(xNumberFormatter);
+ }
+ else if ((eTypeClass == TypeClass_BYTE) || (eTypeClass == TypeClass_SHORT)
+ || (eTypeClass == TypeClass_UNSIGNED_SHORT) || (eTypeClass == TypeClass_LONG)
+ || (eTypeClass == TypeClass_UNSIGNED_LONG) || (eTypeClass == TypeClass_HYPER))
+ {
+ o_formatter = std::make_shared<IntegerNormalization>(xNumberFormatter);
+ }
+ else
+ {
+ SAL_WARN("svtools.table", "unsupported type '" << sTypeName << "'!");
+ }
+ aNormalizers[sTypeName] = o_formatter;
+ }
+ else
+ o_formatter = pos->second;
+
+ return bool(o_formatter);
+}
+
+//= CellValueConversion
+
+CellValueConversion::CellValueConversion()
+ : xNumberFormatter()
+ , bAttemptedFormatterCreation(false)
+ , aNormalizers()
+{
+}
+
+CellValueConversion::~CellValueConversion() {}
+
+OUString CellValueConversion::convertToString(const Any& i_value)
+{
+ OUString sStringValue;
+ if (!i_value.hasValue())
+ return sStringValue;
+
+ if (!(i_value >>= sStringValue))
+ {
+ if (ensureNumberFormatter())
+ {
+ std::shared_ptr<StandardFormatNormalizer> pNormalizer;
+ if (getValueNormalizer(i_value.getValueType(), pNormalizer))
+ {
+ try
+ {
+ double const formatterCompliantValue = pNormalizer->convertToDouble(i_value);
+ sal_Int32 const formatKey = pNormalizer->getFormatKey();
+ sStringValue = xNumberFormatter->convertNumberToString(formatKey,
+ formatterCompliantValue);
+ }
+ catch (const Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.table");
+ }
+ }
+ }
+ }
+
+ return sStringValue;
+}
+
+} // namespace svt
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/table/cellvalueconversion.hxx b/toolkit/source/controls/table/cellvalueconversion.hxx
new file mode 100644
index 0000000000..2e05707e5b
--- /dev/null
+++ b/toolkit/source/controls/table/cellvalueconversion.hxx
@@ -0,0 +1,72 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/util/XNumberFormatter.hpp>
+#include <com/sun/star/uno/Any.hxx>
+#include <unordered_map>
+#include <memory>
+
+namespace svt
+{
+class StandardFormatNormalizer
+{
+public:
+ /** converts the given <code>Any</code> into a <code>double</code> value to be fed into a number formatter
+ */
+ virtual double convertToDouble(css::uno::Any const& i_value) const = 0;
+
+ /** returns the format key to be used for formatting values
+ */
+ sal_Int32 getFormatKey() const { return m_nFormatKey; }
+
+protected:
+ StandardFormatNormalizer(css::uno::Reference<css::util::XNumberFormatter> const& i_formatter,
+ ::sal_Int32 const i_numberFormatType);
+
+ virtual ~StandardFormatNormalizer() {}
+
+private:
+ ::sal_Int32 m_nFormatKey;
+};
+
+class CellValueConversion
+{
+public:
+ CellValueConversion();
+ ~CellValueConversion();
+
+ OUString convertToString(const css::uno::Any& i_cellValue);
+
+private:
+ bool ensureNumberFormatter();
+ bool getValueNormalizer(css::uno::Type const& i_valueType,
+ std::shared_ptr<StandardFormatNormalizer>& o_formatter);
+
+ typedef std::unordered_map<OUString, std::shared_ptr<StandardFormatNormalizer>> NormalizerCache;
+
+ css::uno::Reference<css::util::XNumberFormatter> xNumberFormatter;
+ bool bAttemptedFormatterCreation;
+ NormalizerCache aNormalizers;
+};
+
+} // namespace svt
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/table/defaultinputhandler.cxx b/toolkit/source/controls/table/defaultinputhandler.cxx
new file mode 100644
index 0000000000..171458ef7a
--- /dev/null
+++ b/toolkit/source/controls/table/defaultinputhandler.cxx
@@ -0,0 +1,180 @@
+/* -*- 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/table/defaultinputhandler.hxx>
+#include <controls/table/tablecontrolinterface.hxx>
+
+#include <vcl/event.hxx>
+#include <osl/diagnose.h>
+
+namespace svt::table
+{
+
+
+ //= DefaultInputHandler
+
+
+ DefaultInputHandler::DefaultInputHandler()
+ {
+ aMouseFunctions.push_back( new ColumnResize );
+ aMouseFunctions.push_back( new RowSelection );
+ aMouseFunctions.push_back( new ColumnSortHandler );
+ }
+
+
+ DefaultInputHandler::~DefaultInputHandler()
+ {
+ }
+
+
+ bool DefaultInputHandler::delegateMouseEvent( ITableControl& i_control, const MouseEvent& i_event,
+ FunctionResult ( MouseFunction::*i_handlerMethod )( ITableControl&, const MouseEvent& ) )
+ {
+ if ( pActiveFunction.is() )
+ {
+ bool furtherHandler = false;
+ switch ( (pActiveFunction.get()->*i_handlerMethod)( i_control, i_event ) )
+ {
+ case ActivateFunction:
+ OSL_ENSURE( false, "lcl_delegateMouseEvent: unexpected - function already *is* active!" );
+ break;
+ case ContinueFunction:
+ break;
+ case DeactivateFunction:
+ pActiveFunction.clear();
+ break;
+ case SkipFunction:
+ furtherHandler = true;
+ break;
+ }
+ if ( !furtherHandler )
+ // handled the event
+ return true;
+ }
+
+ // ask all other handlers
+ bool handled = false;
+ for (auto const& mouseFunction : aMouseFunctions)
+ {
+ if (handled)
+ break;
+ if (mouseFunction == pActiveFunction)
+ // we already invoked this function
+ continue;
+
+ switch ( (mouseFunction.get()->*i_handlerMethod)( i_control, i_event ) )
+ {
+ case ActivateFunction:
+ pActiveFunction = mouseFunction;
+ handled = true;
+ break;
+ case ContinueFunction:
+ case DeactivateFunction:
+ OSL_ENSURE( false, "lcl_delegateMouseEvent: unexpected: inactive handler cannot be continued or deactivated!" );
+ break;
+ case SkipFunction:
+ handled = false;
+ break;
+ }
+ }
+ return handled;
+ }
+
+
+ bool DefaultInputHandler::MouseMove( ITableControl& i_tableControl, const MouseEvent& i_event )
+ {
+ return delegateMouseEvent( i_tableControl, i_event, &MouseFunction::handleMouseMove );
+ }
+
+
+ bool DefaultInputHandler::MouseButtonDown( ITableControl& i_tableControl, const MouseEvent& i_event )
+ {
+ return delegateMouseEvent( i_tableControl, i_event, &MouseFunction::handleMouseDown );
+ }
+
+
+ bool DefaultInputHandler::MouseButtonUp( ITableControl& i_tableControl, const MouseEvent& i_event )
+ {
+ return delegateMouseEvent( i_tableControl, i_event, &MouseFunction::handleMouseUp );
+ }
+
+
+ bool DefaultInputHandler::KeyInput( ITableControl& _rControl, const KeyEvent& rKEvt )
+ {
+ bool bHandled = false;
+
+ const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
+ sal_uInt16 nKeyCode = rKeyCode.GetCode();
+
+ struct ActionMapEntry
+ {
+ sal_uInt16 nKeyCode;
+ sal_uInt16 nKeyModifier;
+ TableControlAction eAction;
+ }
+ static const aKnownActions[] = {
+ { KEY_DOWN, 0, cursorDown },
+ { KEY_UP, 0, cursorUp },
+ { KEY_LEFT, 0, cursorLeft },
+ { KEY_RIGHT, 0, cursorRight },
+ { KEY_HOME, 0, cursorToLineStart },
+ { KEY_END, 0, cursorToLineEnd },
+ { KEY_PAGEUP, 0, cursorPageUp },
+ { KEY_PAGEDOWN, 0, cursorPageDown },
+ { KEY_PAGEUP, KEY_MOD1, cursorToFirstLine },
+ { KEY_PAGEDOWN, KEY_MOD1, cursorToLastLine },
+ { KEY_HOME, KEY_MOD1, cursorTopLeft },
+ { KEY_END, KEY_MOD1, cursorBottomRight },
+ { KEY_SPACE, KEY_MOD1, cursorSelectRow },
+ { KEY_UP, KEY_SHIFT, cursorSelectRowUp },
+ { KEY_DOWN, KEY_SHIFT, cursorSelectRowDown },
+ { KEY_END, KEY_SHIFT, cursorSelectRowAreaBottom },
+ { KEY_HOME, KEY_SHIFT, cursorSelectRowAreaTop }
+ };
+ for (const ActionMapEntry& rAction : aKnownActions)
+ {
+ if ( ( rAction.nKeyCode == nKeyCode ) && ( rAction.nKeyModifier == rKeyCode.GetModifier() ) )
+ {
+ bHandled = _rControl.dispatchAction( rAction.eAction );
+ break;
+ }
+ }
+
+ return bHandled;
+ }
+
+
+ bool DefaultInputHandler::GetFocus( ITableControl& _rControl )
+ {
+ _rControl.showCursor();
+ return false; // continue processing
+ }
+
+
+ bool DefaultInputHandler::LoseFocus( ITableControl& _rControl )
+ {
+ _rControl.hideCursor();
+ return false; // continue processing
+ }
+
+
+} // namespace svt::table
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/table/gridtablerenderer.cxx b/toolkit/source/controls/table/gridtablerenderer.cxx
new file mode 100644
index 0000000000..aa49f4afdd
--- /dev/null
+++ b/toolkit/source/controls/table/gridtablerenderer.cxx
@@ -0,0 +1,597 @@
+/* -*- 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 "cellvalueconversion.hxx"
+#include <controls/table/gridtablerenderer.hxx>
+#include <controls/table/tablesort.hxx>
+
+#include <com/sun/star/graphic/XGraphic.hpp>
+
+#include <tools/debug.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <vcl/window.hxx>
+#include <vcl/image.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/decoview.hxx>
+#include <vcl/settings.hxx>
+
+
+namespace svt::table
+{
+ using ::css::uno::Any;
+ using ::css::uno::Reference;
+ using ::css::uno::UNO_QUERY;
+ using ::css::uno::XInterface;
+ using ::css::uno::TypeClass_INTERFACE;
+ using ::css::graphic::XGraphic;
+ using ::css::style::HorizontalAlignment;
+ using ::css::style::HorizontalAlignment_CENTER;
+ using ::css::style::HorizontalAlignment_RIGHT;
+ using ::css::style::VerticalAlignment;
+ using ::css::style::VerticalAlignment_MIDDLE;
+ using ::css::style::VerticalAlignment_BOTTOM;
+
+
+ //= CachedSortIndicator
+
+ namespace {
+
+ class CachedSortIndicator
+ {
+ public:
+ CachedSortIndicator()
+ : m_lastHeaderHeight( 0 )
+ , m_lastArrowColor( COL_TRANSPARENT )
+ {
+ }
+
+ BitmapEx const & getBitmapFor(vcl::RenderContext const & i_device, tools::Long const i_headerHeight,
+ StyleSettings const & i_style, bool const i_sortAscending);
+
+ private:
+ tools::Long m_lastHeaderHeight;
+ Color m_lastArrowColor;
+ BitmapEx m_sortAscending;
+ BitmapEx m_sortDescending;
+ };
+
+ }
+
+ BitmapEx const & CachedSortIndicator::getBitmapFor(vcl::RenderContext const& i_device, tools::Long const i_headerHeight,
+ StyleSettings const & i_style, bool const i_sortAscending )
+ {
+ BitmapEx& rBitmap(i_sortAscending ? m_sortAscending : m_sortDescending);
+ if (rBitmap.IsEmpty() || (i_headerHeight != m_lastHeaderHeight) || (i_style.GetActiveColor() != m_lastArrowColor))
+ {
+ tools::Long const nSortIndicatorWidth = 2 * i_headerHeight / 3;
+ tools::Long const nSortIndicatorHeight = 2 * nSortIndicatorWidth / 3;
+
+ Point const aBitmapPos( 0, 0 );
+ Size const aBitmapSize( nSortIndicatorWidth, nSortIndicatorHeight );
+ ScopedVclPtrInstance< VirtualDevice > aDevice(i_device, DeviceFormat::WITH_ALPHA);
+ aDevice->SetOutputSizePixel( aBitmapSize );
+
+ DecorationView aDecoView(aDevice.get());
+ aDecoView.DrawSymbol(tools::Rectangle(aBitmapPos, aBitmapSize),
+ i_sortAscending ? SymbolType::SPIN_UP : SymbolType::SPIN_DOWN,
+ i_style.GetActiveColor());
+
+ rBitmap = aDevice->GetBitmapEx(aBitmapPos, aBitmapSize);
+ m_lastHeaderHeight = i_headerHeight;
+ m_lastArrowColor = i_style.GetActiveColor();
+ }
+ return rBitmap;
+ }
+
+
+ //= GridTableRenderer_Impl
+
+ struct GridTableRenderer_Impl
+ {
+ ITableModel& rModel;
+ RowPos nCurrentRow;
+ bool bUseGridLines;
+ CachedSortIndicator aSortIndicator;
+ CellValueConversion aStringConverter;
+
+ explicit GridTableRenderer_Impl( ITableModel& _rModel )
+ : rModel( _rModel )
+ , nCurrentRow( ROW_INVALID )
+ , bUseGridLines( true )
+ , aSortIndicator( )
+ , aStringConverter()
+ {
+ }
+ };
+
+
+ //= helper
+
+ namespace
+ {
+ tools::Rectangle lcl_getContentArea( GridTableRenderer_Impl const & i_impl, tools::Rectangle const & i_cellArea )
+ {
+ tools::Rectangle aContentArea( i_cellArea );
+ if ( i_impl.bUseGridLines )
+ {
+ aContentArea.AdjustRight( -1 );
+ aContentArea.AdjustBottom( -1 );
+ }
+ return aContentArea;
+ }
+ tools::Rectangle lcl_getTextRenderingArea( tools::Rectangle const & i_contentArea )
+ {
+ tools::Rectangle aTextArea( i_contentArea );
+ aTextArea.AdjustLeft(2 ); aTextArea.AdjustRight( -2 );
+ aTextArea.AdjustTop( 1 ); aTextArea.AdjustBottom( -1 );
+ return aTextArea;
+ }
+
+ DrawTextFlags lcl_getAlignmentTextDrawFlags( GridTableRenderer_Impl const & i_impl, ColPos const i_columnPos )
+ {
+ DrawTextFlags nVertFlag = DrawTextFlags::Top;
+ VerticalAlignment const eVertAlign = i_impl.rModel.getVerticalAlign();
+ switch ( eVertAlign )
+ {
+ case VerticalAlignment_MIDDLE: nVertFlag = DrawTextFlags::VCenter; break;
+ case VerticalAlignment_BOTTOM: nVertFlag = DrawTextFlags::Bottom; break;
+ default:
+ break;
+ }
+
+ DrawTextFlags nHorzFlag = DrawTextFlags::Left;
+ HorizontalAlignment const eHorzAlign = i_impl.rModel.getColumnCount() > 0
+ ? i_impl.rModel.getColumnModel( i_columnPos )->getHorizontalAlign()
+ : HorizontalAlignment_CENTER;
+ switch ( eHorzAlign )
+ {
+ case HorizontalAlignment_CENTER: nHorzFlag = DrawTextFlags::Center; break;
+ case HorizontalAlignment_RIGHT: nHorzFlag = DrawTextFlags::Right; break;
+ default:
+ break;
+ }
+
+ return nVertFlag | nHorzFlag;
+ }
+
+ }
+
+
+ //= GridTableRenderer
+
+
+ GridTableRenderer::GridTableRenderer( ITableModel& _rModel )
+ :m_pImpl( new GridTableRenderer_Impl( _rModel ) )
+ {
+ }
+
+
+ GridTableRenderer::~GridTableRenderer()
+ {
+ }
+
+
+ bool GridTableRenderer::useGridLines() const
+ {
+ return m_pImpl->bUseGridLines;
+ }
+
+
+ void GridTableRenderer::useGridLines( bool const i_use )
+ {
+ m_pImpl->bUseGridLines = i_use;
+ }
+
+
+ namespace
+ {
+ Color lcl_getEffectiveColor(std::optional<Color> const& i_modelColor,
+ StyleSettings const& i_styleSettings,
+ Color const& (StyleSettings::*i_getDefaultColor) () const)
+ {
+ if (!!i_modelColor)
+ return *i_modelColor;
+ return (i_styleSettings.*i_getDefaultColor)();
+ }
+ }
+
+
+ void GridTableRenderer::PaintHeaderArea(vcl::RenderContext& rRenderContext, const tools::Rectangle& _rArea,
+ bool _bIsColHeaderArea, bool _bIsRowHeaderArea, const StyleSettings& _rStyle)
+ {
+ OSL_PRECOND(_bIsColHeaderArea || _bIsRowHeaderArea, "GridTableRenderer::PaintHeaderArea: invalid area flags!");
+
+ rRenderContext.Push(vcl::PushFlags::FILLCOLOR | vcl::PushFlags::LINECOLOR);
+
+ Color const background = lcl_getEffectiveColor(m_pImpl->rModel.getHeaderBackgroundColor(),
+ _rStyle, &StyleSettings::GetDialogColor);
+ rRenderContext.SetFillColor(background);
+
+ rRenderContext.SetLineColor();
+ rRenderContext.DrawRect(_rArea);
+
+ // delimiter lines at bottom/right
+ std::optional<Color> aLineColor(m_pImpl->rModel.getLineColor());
+ Color const lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor;
+ rRenderContext.SetLineColor(lineColor);
+ rRenderContext.DrawLine(_rArea.BottomLeft(), _rArea.BottomRight());
+ rRenderContext.DrawLine(_rArea.BottomRight(), _rArea.TopRight());
+
+ rRenderContext.Pop();
+ }
+
+
+ void GridTableRenderer::PaintColumnHeader(
+ ColPos _nCol,
+ vcl::RenderContext& rRenderContext,
+ const tools::Rectangle& _rArea, const StyleSettings& _rStyle)
+ {
+ rRenderContext.Push(vcl::PushFlags::LINECOLOR);
+
+ OUString sHeaderText;
+ PColumnModel const pColumn = m_pImpl->rModel.getColumnModel( _nCol );
+ DBG_ASSERT( pColumn, "GridTableRenderer::PaintColumnHeader: invalid column model object!" );
+ if ( pColumn )
+ sHeaderText = pColumn->getName();
+
+ Color const textColor = lcl_getEffectiveColor( m_pImpl->rModel.getTextColor(), _rStyle, &StyleSettings::GetFieldTextColor );
+ rRenderContext.SetTextColor(textColor);
+
+ tools::Rectangle const aTextRect( lcl_getTextRenderingArea( lcl_getContentArea( *m_pImpl, _rArea ) ) );
+ DrawTextFlags nDrawTextFlags = lcl_getAlignmentTextDrawFlags( *m_pImpl, _nCol ) | DrawTextFlags::Clip;
+ if (!m_pImpl->rModel.isEnabled())
+ nDrawTextFlags |= DrawTextFlags::Disable;
+ rRenderContext.DrawText( aTextRect, sHeaderText, nDrawTextFlags );
+
+ std::optional<Color> const aLineColor( m_pImpl->rModel.getLineColor() );
+ Color const lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor;
+ rRenderContext.SetLineColor( lineColor );
+ rRenderContext.DrawLine( _rArea.BottomRight(), _rArea.TopRight());
+ rRenderContext.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() );
+
+ // draw sort indicator if the model data is sorted by the given column
+ ITableDataSort const * pSortAdapter = m_pImpl->rModel.getSortAdapter();
+ ColumnSort aCurrentSortOrder;
+ if ( pSortAdapter != nullptr )
+ aCurrentSortOrder = pSortAdapter->getCurrentSortOrder();
+ if ( aCurrentSortOrder.nColumnPos == _nCol )
+ {
+ tools::Long const nHeaderHeight( _rArea.GetHeight() );
+ BitmapEx const aIndicatorBitmap = m_pImpl->aSortIndicator.getBitmapFor(rRenderContext, nHeaderHeight, _rStyle,
+ aCurrentSortOrder.eSortDirection == ColumnSortAscending);
+ Size const aBitmapSize( aIndicatorBitmap.GetSizePixel() );
+ tools::Long const nSortIndicatorPaddingX = 2;
+ tools::Long const nSortIndicatorPaddingY = ( nHeaderHeight - aBitmapSize.Height() ) / 2;
+
+ if ( nDrawTextFlags & DrawTextFlags::Right )
+ {
+ // text is right aligned => draw the sort indicator at the left hand side
+ rRenderContext.DrawBitmapEx(Point(_rArea.Left() + nSortIndicatorPaddingX, _rArea.Top() + nSortIndicatorPaddingY),
+ aIndicatorBitmap);
+ }
+ else
+ {
+ // text is left-aligned or centered => draw the sort indicator at the right hand side
+ rRenderContext.DrawBitmapEx(Point(_rArea.Right() - nSortIndicatorPaddingX - aBitmapSize.Width(), nSortIndicatorPaddingY),
+ aIndicatorBitmap);
+ }
+ }
+
+ rRenderContext.Pop();
+ }
+
+
+ void GridTableRenderer::PrepareRow(RowPos _nRow, bool i_hasControlFocus, bool _bSelected, vcl::RenderContext& rRenderContext,
+ const tools::Rectangle& _rRowArea, const StyleSettings& _rStyle)
+ {
+ // remember the row for subsequent calls to the other ->ITableRenderer methods
+ m_pImpl->nCurrentRow = _nRow;
+
+ rRenderContext.Push(vcl::PushFlags::FILLCOLOR | vcl::PushFlags::LINECOLOR);
+
+ Color backgroundColor = _rStyle.GetFieldColor();
+
+ Color const activeSelectionBackColor = lcl_getEffectiveColor(m_pImpl->rModel.getActiveSelectionBackColor(),
+ _rStyle, &StyleSettings::GetHighlightColor);
+ if (_bSelected)
+ {
+ // selected rows use the background color from the style
+ backgroundColor = i_hasControlFocus
+ ? activeSelectionBackColor
+ : lcl_getEffectiveColor(m_pImpl->rModel.getInactiveSelectionBackColor(), _rStyle, &StyleSettings::GetDeactiveColor);
+ }
+ else
+ {
+ std::optional< std::vector<Color> > aRowColors = m_pImpl->rModel.getRowBackgroundColors();
+ if (!aRowColors)
+ {
+ // use alternating default colors
+ Color const fieldColor = _rStyle.GetFieldColor();
+ if (_rStyle.GetHighContrastMode() || ((m_pImpl->nCurrentRow % 2) == 0))
+ {
+ backgroundColor = fieldColor;
+ }
+ else
+ {
+ Color hilightColor = activeSelectionBackColor;
+ hilightColor.SetRed( 9 * ( fieldColor.GetRed() - hilightColor.GetRed() ) / 10 + hilightColor.GetRed() );
+ hilightColor.SetGreen( 9 * ( fieldColor.GetGreen() - hilightColor.GetGreen() ) / 10 + hilightColor.GetGreen() );
+ hilightColor.SetBlue( 9 * ( fieldColor.GetBlue() - hilightColor.GetBlue() ) / 10 + hilightColor.GetBlue() );
+ backgroundColor = hilightColor;
+ }
+ }
+ else
+ {
+ if (aRowColors->empty())
+ {
+ // all colors have the same background color
+ backgroundColor = _rStyle.GetFieldColor();
+ }
+ else
+ {
+ backgroundColor = aRowColors->at(m_pImpl->nCurrentRow % aRowColors->size());
+ }
+ }
+ }
+
+ rRenderContext.SetLineColor();
+ rRenderContext.SetFillColor(backgroundColor);
+ rRenderContext.DrawRect(_rRowArea);
+
+ rRenderContext.Pop();
+ }
+
+
+ void GridTableRenderer::PaintRowHeader(vcl::RenderContext& rRenderContext,
+ const tools::Rectangle& _rArea, const StyleSettings& _rStyle)
+ {
+ rRenderContext.Push( vcl::PushFlags::LINECOLOR | vcl::PushFlags::TEXTCOLOR );
+
+ std::optional<Color> const aLineColor( m_pImpl->rModel.getLineColor() );
+ Color const lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor;
+ rRenderContext.SetLineColor(lineColor);
+ rRenderContext.DrawLine(_rArea.BottomLeft(), _rArea.BottomRight());
+
+ Any const rowHeading( m_pImpl->rModel.getRowHeading( m_pImpl->nCurrentRow ) );
+ OUString const rowTitle( m_pImpl->aStringConverter.convertToString( rowHeading ) );
+ if (!rowTitle.isEmpty())
+ {
+ Color const textColor = lcl_getEffectiveColor(m_pImpl->rModel.getHeaderTextColor(),
+ _rStyle, &StyleSettings::GetFieldTextColor);
+ rRenderContext.SetTextColor(textColor);
+
+ tools::Rectangle const aTextRect(lcl_getTextRenderingArea(lcl_getContentArea(*m_pImpl, _rArea)));
+ DrawTextFlags nDrawTextFlags = lcl_getAlignmentTextDrawFlags(*m_pImpl, 0) | DrawTextFlags::Clip;
+ if (!m_pImpl->rModel.isEnabled())
+ nDrawTextFlags |= DrawTextFlags::Disable;
+ // TODO: is using the horizontal alignment of the 0'th column a good idea here? This is pretty ... arbitrary ..
+ rRenderContext.DrawText(aTextRect, rowTitle, nDrawTextFlags);
+ }
+
+ rRenderContext.Pop();
+ }
+
+
+ struct GridTableRenderer::CellRenderContext
+ {
+ OutputDevice& rDevice;
+ tools::Rectangle const aContentArea;
+ StyleSettings const & rStyle;
+ ColPos const nColumn;
+ bool const bSelected;
+ bool const bHasControlFocus;
+
+ CellRenderContext( OutputDevice& i_device, tools::Rectangle const & i_contentArea,
+ StyleSettings const & i_style, ColPos const i_column, bool const i_selected, bool const i_hasControlFocus )
+ :rDevice( i_device )
+ ,aContentArea( i_contentArea )
+ ,rStyle( i_style )
+ ,nColumn( i_column )
+ ,bSelected( i_selected )
+ ,bHasControlFocus( i_hasControlFocus )
+ {
+ }
+ };
+
+
+ void GridTableRenderer::PaintCell(ColPos const i_column, bool _bSelected, bool i_hasControlFocus,
+ vcl::RenderContext& rRenderContext, const tools::Rectangle& _rArea, const StyleSettings& _rStyle)
+ {
+ rRenderContext.Push(vcl::PushFlags::LINECOLOR | vcl::PushFlags::FILLCOLOR);
+
+ tools::Rectangle const aContentArea(lcl_getContentArea(*m_pImpl, _rArea));
+ CellRenderContext const aCellRenderContext(rRenderContext, aContentArea, _rStyle, i_column, _bSelected, i_hasControlFocus);
+ impl_paintCellContent(aCellRenderContext);
+
+ if ( m_pImpl->bUseGridLines )
+ {
+ ::std::optional< ::Color > aLineColor( m_pImpl->rModel.getLineColor() );
+ ::Color lineColor = !aLineColor ? _rStyle.GetSeparatorColor() : *aLineColor;
+
+ if ( _bSelected && !aLineColor )
+ {
+ // if no line color is specified by the model, use the usual selection color for lines in selected cells
+ lineColor = i_hasControlFocus
+ ? lcl_getEffectiveColor( m_pImpl->rModel.getActiveSelectionBackColor(), _rStyle, &StyleSettings::GetHighlightColor )
+ : lcl_getEffectiveColor( m_pImpl->rModel.getInactiveSelectionBackColor(), _rStyle, &StyleSettings::GetDeactiveColor );
+ }
+
+ rRenderContext.SetLineColor( lineColor );
+ rRenderContext.DrawLine( _rArea.BottomLeft(), _rArea.BottomRight() );
+ rRenderContext.DrawLine( _rArea.BottomRight(), _rArea.TopRight() );
+ }
+
+ rRenderContext.Pop();
+ }
+
+
+ void GridTableRenderer::impl_paintCellImage( CellRenderContext const & i_context, Image const & i_image )
+ {
+ Point imagePos( i_context.aContentArea.Left(), i_context.aContentArea.Top() );
+ Size imageSize = i_image.GetSizePixel();
+ if ( i_context.aContentArea.GetWidth() > imageSize.Width() )
+ {
+ const HorizontalAlignment eHorzAlign = m_pImpl->rModel.getColumnModel( i_context.nColumn )->getHorizontalAlign();
+ switch ( eHorzAlign )
+ {
+ case HorizontalAlignment_CENTER:
+ imagePos.AdjustX(( i_context.aContentArea.GetWidth() - imageSize.Width() ) / 2 );
+ break;
+ case HorizontalAlignment_RIGHT:
+ imagePos.setX( i_context.aContentArea.Right() - imageSize.Width() );
+ break;
+ default:
+ break;
+ }
+
+ }
+ else
+ imageSize.setWidth( i_context.aContentArea.GetWidth() );
+
+ if ( i_context.aContentArea.GetHeight() > imageSize.Height() )
+ {
+ const VerticalAlignment eVertAlign = m_pImpl->rModel.getVerticalAlign();
+ switch ( eVertAlign )
+ {
+ case VerticalAlignment_MIDDLE:
+ imagePos.AdjustY(( i_context.aContentArea.GetHeight() - imageSize.Height() ) / 2 );
+ break;
+ case VerticalAlignment_BOTTOM:
+ imagePos.setY( i_context.aContentArea.Bottom() - imageSize.Height() );
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ imageSize.setHeight( i_context.aContentArea.GetHeight() - 1 );
+ DrawImageFlags const nStyle = m_pImpl->rModel.isEnabled() ? DrawImageFlags::NONE : DrawImageFlags::Disable;
+ i_context.rDevice.DrawImage( imagePos, imageSize, i_image, nStyle );
+ }
+
+
+ void GridTableRenderer::impl_paintCellContent( CellRenderContext const & i_context )
+ {
+ Any aCellContent;
+ m_pImpl->rModel.getCellContent( i_context.nColumn, m_pImpl->nCurrentRow, aCellContent );
+
+ if ( aCellContent.getValueTypeClass() == TypeClass_INTERFACE )
+ {
+ Reference< XInterface > const xContentInterface( aCellContent, UNO_QUERY );
+ if ( !xContentInterface.is() )
+ // allowed. kind of.
+ return;
+
+ Reference< XGraphic > const xGraphic( aCellContent, UNO_QUERY );
+ ENSURE_OR_RETURN_VOID( xGraphic.is(), "GridTableRenderer::impl_paintCellContent: only XGraphic interfaces (or NULL) are supported for painting." );
+
+ const Image aImage( xGraphic );
+ impl_paintCellImage( i_context, aImage );
+ return;
+ }
+
+ const OUString sText( m_pImpl->aStringConverter.convertToString( aCellContent ) );
+ impl_paintCellText( i_context, sText );
+ }
+
+
+ void GridTableRenderer::impl_paintCellText( CellRenderContext const & i_context, OUString const & i_text )
+ {
+ if ( i_context.bSelected )
+ {
+ ::Color const textColor = i_context.bHasControlFocus
+ ? lcl_getEffectiveColor( m_pImpl->rModel.getActiveSelectionTextColor(), i_context.rStyle, &StyleSettings::GetHighlightTextColor )
+ : lcl_getEffectiveColor( m_pImpl->rModel.getInactiveSelectionTextColor(), i_context.rStyle, &StyleSettings::GetDeactiveTextColor );
+ i_context.rDevice.SetTextColor( textColor );
+ }
+ else
+ {
+ ::Color const textColor = lcl_getEffectiveColor( m_pImpl->rModel.getTextColor(), i_context.rStyle, &StyleSettings::GetFieldTextColor );
+ i_context.rDevice.SetTextColor( textColor );
+ }
+
+ tools::Rectangle const textRect( lcl_getTextRenderingArea( i_context.aContentArea ) );
+ DrawTextFlags nDrawTextFlags = lcl_getAlignmentTextDrawFlags( *m_pImpl, i_context.nColumn ) | DrawTextFlags::Clip;
+ if ( !m_pImpl->rModel.isEnabled() )
+ nDrawTextFlags |= DrawTextFlags::Disable;
+ i_context.rDevice.DrawText( textRect, i_text, nDrawTextFlags );
+ }
+
+
+ void GridTableRenderer::ShowCellCursor( vcl::Window& _rView, const tools::Rectangle& _rCursorRect)
+ {
+ _rView.ShowFocus( _rCursorRect );
+ }
+
+
+ void GridTableRenderer::HideCellCursor( vcl::Window& _rView )
+ {
+ _rView.HideFocus();
+ }
+
+
+ bool GridTableRenderer::FitsIntoCell( Any const & i_cellContent,
+ OutputDevice& i_targetDevice, tools::Rectangle const & i_targetArea ) const
+ {
+ if ( !i_cellContent.hasValue() )
+ return true;
+
+ if ( i_cellContent.getValueTypeClass() == TypeClass_INTERFACE )
+ {
+ Reference< XInterface > const xContentInterface( i_cellContent, UNO_QUERY );
+ if ( !xContentInterface.is() )
+ return true;
+
+ Reference< XGraphic > const xGraphic( i_cellContent, UNO_QUERY );
+ if ( xGraphic.is() )
+ // for the moment, assume it fits. We can always scale it down during painting ...
+ return true;
+
+ OSL_ENSURE( false, "GridTableRenderer::FitsIntoCell: only XGraphic interfaces (or NULL) are supported for painting." );
+ return true;
+ }
+
+ OUString const sText( m_pImpl->aStringConverter.convertToString( i_cellContent ) );
+ if ( sText.isEmpty() )
+ return true;
+
+ tools::Rectangle const aTargetArea( lcl_getTextRenderingArea( lcl_getContentArea( *m_pImpl, i_targetArea ) ) );
+
+ tools::Long const nTextHeight = i_targetDevice.GetTextHeight();
+ if ( nTextHeight > aTargetArea.GetHeight() )
+ return false;
+
+ tools::Long const nTextWidth = i_targetDevice.GetTextWidth( sText );
+ return nTextWidth <= aTargetArea.GetWidth();
+ }
+
+
+ bool GridTableRenderer::GetFormattedCellString( Any const & i_cellValue, OUString & o_cellString ) const
+ {
+ o_cellString = m_pImpl->aStringConverter.convertToString( i_cellValue );
+
+ return true;
+ }
+
+
+} // namespace svt::table
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/table/mousefunction.cxx b/toolkit/source/controls/table/mousefunction.cxx
new file mode 100644
index 0000000000..d0a784fdf1
--- /dev/null
+++ b/toolkit/source/controls/table/mousefunction.cxx
@@ -0,0 +1,273 @@
+/* -*- 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/table/mousefunction.hxx>
+#include <controls/table/tablecontrolinterface.hxx>
+#include <controls/table/tablesort.hxx>
+
+#include <comphelper/diagnose_ex.hxx>
+#include <vcl/ptrstyle.hxx>
+
+namespace svt::table
+{
+
+
+ //= ColumnResize
+
+
+ FunctionResult ColumnResize::handleMouseMove( ITableControl& i_tableControl, MouseEvent const & i_event )
+ {
+ Point const aPoint = i_event.GetPosPixel();
+
+ if ( m_nResizingColumn == COL_INVALID )
+ {
+ // if we hit a column divider, change the mouse pointer accordingly
+ PointerStyle aNewPointer( PointerStyle::Arrow );
+ TableCell const tableCell = i_tableControl.hitTest( aPoint );
+ if ( ( tableCell.nRow == ROW_COL_HEADERS ) && ( tableCell.eArea == ColumnDivider ) )
+ {
+ aNewPointer = PointerStyle::HSplit;
+ }
+ i_tableControl.setPointer( aNewPointer );
+
+ return SkipFunction; // TODO: is this correct?
+ }
+
+ ::Size const tableSize = i_tableControl.getTableSizePixel();
+
+ // set proper pointer
+ PointerStyle aNewPointer( PointerStyle::Arrow );
+ ColumnMetrics const & columnMetrics( i_tableControl.getColumnMetrics( m_nResizingColumn ) );
+ if ( ( aPoint.X() > tableSize.Width() )
+ || ( aPoint.X() < columnMetrics.nStartPixel )
+ )
+ {
+ aNewPointer = PointerStyle::NotAllowed;
+ }
+ else
+ {
+ aNewPointer = PointerStyle::HSplit;
+ }
+ i_tableControl.setPointer( aNewPointer );
+
+ // show tracking line
+ i_tableControl.hideTracking();
+ i_tableControl.showTracking(
+ tools::Rectangle(
+ Point( aPoint.X(), 0 ),
+ Size( 1, tableSize.Height() )
+ ),
+ ShowTrackFlags::Split | ShowTrackFlags::TrackWindow
+ );
+
+ return ContinueFunction;
+ }
+
+
+ FunctionResult ColumnResize::handleMouseDown( ITableControl& i_tableControl, MouseEvent const & i_event )
+ {
+ if ( m_nResizingColumn != COL_INVALID )
+ {
+ OSL_ENSURE( false, "ColumnResize::handleMouseDown: suspicious: MouseButtonDown while still tracking?" );
+ return ContinueFunction;
+ }
+
+ TableCell const tableCell( i_tableControl.hitTest( i_event.GetPosPixel() ) );
+ if ( tableCell.nRow == ROW_COL_HEADERS )
+ {
+ if ( ( tableCell.nColumn != COL_INVALID )
+ && ( tableCell.eArea == ColumnDivider )
+ )
+ {
+ m_nResizingColumn = tableCell.nColumn;
+ i_tableControl.captureMouse();
+ return ActivateFunction;
+ }
+ }
+
+ return SkipFunction;
+ }
+
+
+ FunctionResult ColumnResize::handleMouseUp( ITableControl& i_tableControl, MouseEvent const & i_event )
+ {
+ if ( m_nResizingColumn == COL_INVALID )
+ return SkipFunction;
+
+ Point const aPoint = i_event.GetPosPixel();
+
+ i_tableControl.hideTracking();
+ PColumnModel const pColumn = i_tableControl.getModel()->getColumnModel( m_nResizingColumn );
+ tools::Long const maxWidthLogical = pColumn->getMaxWidth();
+ tools::Long const minWidthLogical = pColumn->getMinWidth();
+
+ // new position of mouse
+ tools::Long const requestedEnd = aPoint.X();
+
+ // old position of right border
+ tools::Long const oldEnd = i_tableControl.getColumnMetrics( m_nResizingColumn ).nEndPixel;
+
+ // position of left border if cursor in the to-be-resized column
+ tools::Long const columnStart = i_tableControl.getColumnMetrics( m_nResizingColumn ).nStartPixel;
+ tools::Long const requestedWidth = requestedEnd - columnStart;
+ // TODO: this is not correct, strictly: It assumes that the mouse was pressed exactly on the "end" pos,
+ // but for a while now, we have relaxed this, and allow clicking a few pixels aside, too
+
+ if ( requestedEnd >= columnStart )
+ {
+ tools::Long requestedWidthLogical = i_tableControl.pixelWidthToAppFont( requestedWidth );
+ // respect column width limits
+ if ( oldEnd > requestedEnd )
+ {
+ // column has become smaller, check against minimum width
+ if ( ( minWidthLogical != 0 ) && ( requestedWidthLogical < minWidthLogical ) )
+ requestedWidthLogical = minWidthLogical;
+ }
+ else if ( oldEnd < requestedEnd )
+ {
+ // column has become larger, check against max width
+ if ( ( maxWidthLogical != 0 ) && ( requestedWidthLogical >= maxWidthLogical ) )
+ requestedWidthLogical = maxWidthLogical;
+ }
+ pColumn->setWidth( requestedWidthLogical );
+ i_tableControl.invalidate( TableArea::All );
+ }
+
+ i_tableControl.setPointer( PointerStyle::Arrow );
+ i_tableControl.releaseMouse();
+
+ m_nResizingColumn = COL_INVALID;
+ return DeactivateFunction;
+ }
+
+
+ //= RowSelection
+
+
+ FunctionResult RowSelection::handleMouseMove( ITableControl&, MouseEvent const & )
+ {
+ return SkipFunction;
+ }
+
+
+ FunctionResult RowSelection::handleMouseDown( ITableControl& i_tableControl, MouseEvent const & i_event )
+ {
+ bool handled = false;
+
+ TableCell const tableCell( i_tableControl.hitTest( i_event.GetPosPixel() ) );
+ if ( tableCell.nRow >= 0 )
+ {
+ if ( i_tableControl.getSelEngine()->GetSelectionMode() == SelectionMode::NONE )
+ {
+ i_tableControl.activateCell( tableCell.nColumn, tableCell.nRow );
+ handled = true;
+ }
+ else
+ {
+ handled = i_tableControl.getSelEngine()->SelMouseButtonDown( i_event );
+ }
+ }
+
+ if ( handled )
+ m_bActive = true;
+ return handled ? ActivateFunction : SkipFunction;
+ }
+
+
+ FunctionResult RowSelection::handleMouseUp( ITableControl& i_tableControl, MouseEvent const & i_event )
+ {
+ TableCell const tableCell = i_tableControl.hitTest( i_event.GetPosPixel() );
+ if ( tableCell.nRow >= 0 )
+ {
+ if ( i_tableControl.getSelEngine()->GetSelectionMode() != SelectionMode::NONE )
+ {
+ i_tableControl.getSelEngine()->SelMouseButtonUp( i_event );
+ }
+ }
+ if ( m_bActive )
+ {
+ m_bActive = false;
+ return DeactivateFunction;
+ }
+ return SkipFunction;
+ }
+
+
+ //= ColumnSortHandler
+
+
+ FunctionResult ColumnSortHandler::handleMouseMove( ITableControl&, MouseEvent const & )
+ {
+ return SkipFunction;
+ }
+
+
+ FunctionResult ColumnSortHandler::handleMouseDown( ITableControl& i_tableControl, MouseEvent const & i_event )
+ {
+ if ( m_nActiveColumn != COL_INVALID )
+ {
+ OSL_ENSURE( false, "ColumnSortHandler::handleMouseDown: called while already active - suspicious!" );
+ return ContinueFunction;
+ }
+
+ if ( i_tableControl.getModel()->getSortAdapter() == nullptr )
+ // no sorting support at the model
+ return SkipFunction;
+
+ TableCell const tableCell( i_tableControl.hitTest( i_event.GetPosPixel() ) );
+ if ( ( tableCell.nRow != ROW_COL_HEADERS ) || ( tableCell.nColumn < 0 ) )
+ return SkipFunction;
+
+ // TODO: ensure the column header is rendered in some special way, indicating its current state
+
+ m_nActiveColumn = tableCell.nColumn;
+ return ActivateFunction;
+ }
+
+
+ FunctionResult ColumnSortHandler::handleMouseUp( ITableControl& i_tableControl, MouseEvent const & i_event )
+ {
+ if ( m_nActiveColumn == COL_INVALID )
+ return SkipFunction;
+
+ TableCell const tableCell( i_tableControl.hitTest( i_event.GetPosPixel() ) );
+ if ( ( tableCell.nRow == ROW_COL_HEADERS ) && ( tableCell.nColumn == m_nActiveColumn ) )
+ {
+ ITableDataSort* pSort = i_tableControl.getModel()->getSortAdapter();
+ ENSURE_OR_RETURN( pSort != nullptr, "ColumnSortHandler::handleMouseUp: somebody is mocking with us!", DeactivateFunction );
+ // in handleMousButtonDown, the model claimed to have sort support ...
+
+ ColumnSortDirection eSortDirection = ColumnSortAscending;
+ ColumnSort const aCurrentSort = pSort->getCurrentSortOrder();
+ if ( aCurrentSort.nColumnPos == m_nActiveColumn )
+ // invert existing sort order
+ eSortDirection = ( aCurrentSort.eSortDirection == ColumnSortAscending ) ? ColumnSortDescending : ColumnSortAscending;
+
+ pSort->sortByColumn( m_nActiveColumn, eSortDirection );
+ }
+
+ m_nActiveColumn = COL_INVALID;
+ return DeactivateFunction;
+ }
+
+
+} // namespace svt::table
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/table/tablecontrol.cxx b/toolkit/source/controls/table/tablecontrol.cxx
new file mode 100644
index 0000000000..42b314569e
--- /dev/null
+++ b/toolkit/source/controls/table/tablecontrol.cxx
@@ -0,0 +1,642 @@
+/* -*- 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/table/tablecontrol.hxx>
+
+#include "tablecontrol_impl.hxx"
+#include "tabledatawindow.hxx"
+
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+
+#include <sal/log.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/vclevent.hxx>
+
+using namespace ::com::sun::star::uno;
+using ::com::sun::star::accessibility::XAccessible;
+using namespace ::com::sun::star::accessibility;
+using namespace ::com::sun::star::lang;
+
+namespace svt::table
+{
+
+
+ namespace AccessibleEventId = ::com::sun::star::accessibility::AccessibleEventId;
+
+
+ //= TableControl
+
+
+ TableControl::TableControl( vcl::Window* _pParent, WinBits _nStyle )
+ :Control( _pParent, _nStyle )
+ ,m_pImpl( std::make_shared<TableControl_Impl>( *this ) )
+ {
+ TableDataWindow& rDataWindow = m_pImpl->getDataWindow();
+ rDataWindow.SetSelectHdl( LINK( this, TableControl, ImplSelectHdl ) );
+
+ // by default, use the background as determined by the style settings
+ const Color aWindowColor( GetSettings().GetStyleSettings().GetFieldColor() );
+ SetBackground( Wallpaper( aWindowColor ) );
+ GetOutDev()->SetFillColor( aWindowColor );
+
+ SetCompoundControl( true );
+ }
+
+
+ TableControl::~TableControl()
+ {
+ disposeOnce();
+ }
+
+ void TableControl::dispose()
+ {
+ CallEventListeners( VclEventId::ObjectDying );
+
+ m_pImpl->setModel( PTableModel() );
+ m_pImpl->disposeAccessible();
+ m_pImpl.reset();
+ Control::dispose();
+ }
+
+
+ void TableControl::GetFocus()
+ {
+ if ( !m_pImpl || !m_pImpl->getInputHandler()->GetFocus( *m_pImpl ) )
+ Control::GetFocus();
+ }
+
+
+ void TableControl::LoseFocus()
+ {
+ if ( !m_pImpl || !m_pImpl->getInputHandler()->LoseFocus( *m_pImpl ) )
+ Control::LoseFocus();
+ }
+
+
+ void TableControl::KeyInput( const KeyEvent& rKEvt )
+ {
+ if ( !m_pImpl->getInputHandler()->KeyInput( *m_pImpl, rKEvt ) )
+ Control::KeyInput( rKEvt );
+ else
+ {
+ if ( m_pImpl->isAccessibleAlive() )
+ {
+ m_pImpl->commitCellEvent( AccessibleEventId::STATE_CHANGED,
+ Any( AccessibleStateType::FOCUSED ),
+ Any()
+ );
+ // Huh? What the heck? Why do we unconditionally notify a STATE_CHANGE/FOCUSED after each and every
+ // (handled) key stroke?
+
+ m_pImpl->commitTableEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED,
+ Any(),
+ Any()
+ );
+ // ditto: Why do we notify this unconditionally? We should find the right place to notify the
+ // ACTIVE_DESCENDANT_CHANGED event.
+ // Also, we should check if STATE_CHANGED/FOCUSED is really necessary: finally, the children are
+ // transient, aren't they?
+ }
+ }
+ }
+
+
+ void TableControl::StateChanged( StateChangedType i_nStateChange )
+ {
+ Control::StateChanged( i_nStateChange );
+
+ // forward certain settings to the data window
+ switch ( i_nStateChange )
+ {
+ case StateChangedType::ControlFocus:
+ m_pImpl->invalidateSelectedRows();
+ break;
+
+ case StateChangedType::ControlBackground:
+ if ( IsControlBackground() )
+ getDataWindow().SetControlBackground( GetControlBackground() );
+ else
+ getDataWindow().SetControlBackground();
+ break;
+
+ case StateChangedType::ControlForeground:
+ if ( IsControlForeground() )
+ getDataWindow().SetControlForeground( GetControlForeground() );
+ else
+ getDataWindow().SetControlForeground();
+ break;
+
+ case StateChangedType::ControlFont:
+ if ( IsControlFont() )
+ getDataWindow().SetControlFont( GetControlFont() );
+ else
+ getDataWindow().SetControlFont();
+ break;
+ default:;
+ }
+ }
+
+
+ void TableControl::Resize()
+ {
+ Control::Resize();
+ m_pImpl->onResize();
+ }
+
+
+ void TableControl::SetModel( const PTableModel& _pModel )
+ {
+ m_pImpl->setModel( _pModel );
+ }
+
+
+ PTableModel TableControl::GetModel() const
+ {
+ return m_pImpl->getModel();
+ }
+
+
+ sal_Int32 TableControl::GetCurrentRow() const
+ {
+ return m_pImpl->getCurrentRow();
+ }
+
+
+ sal_Int32 TableControl::GetCurrentColumn() const
+ {
+ return m_pImpl->getCurrentColumn();
+ }
+
+
+ void TableControl::GoTo( ColPos _nColumn, RowPos _nRow )
+ {
+ m_pImpl->goTo( _nColumn, _nRow );
+ }
+
+
+ void TableControl::GoToCell(sal_Int32 _nColPos, sal_Int32 _nRowPos)
+ {
+ m_pImpl->goTo( _nColPos, _nRowPos );
+ }
+
+
+ sal_Int32 TableControl::GetSelectedRowCount() const
+ {
+ return sal_Int32( m_pImpl->getSelectedRowCount() );
+ }
+
+
+ sal_Int32 TableControl::GetSelectedRowIndex( sal_Int32 const i_selectionIndex ) const
+ {
+ return m_pImpl->getSelectedRowIndex( i_selectionIndex );
+ }
+
+
+ bool TableControl::IsRowSelected( sal_Int32 const i_rowIndex ) const
+ {
+ return m_pImpl->isRowSelected( i_rowIndex );
+ }
+
+
+ void TableControl::SelectRow( sal_Int32 const i_rowIndex, bool const i_select )
+ {
+ ENSURE_OR_RETURN_VOID( ( i_rowIndex >= 0 ) && ( i_rowIndex < m_pImpl->getModel()->getRowCount() ),
+ "TableControl::SelectRow: invalid row index!" );
+
+ if ( i_select )
+ {
+ if ( !m_pImpl->markRowAsSelected( i_rowIndex ) )
+ // nothing to do
+ return;
+ }
+ else
+ {
+ m_pImpl->markRowAsDeselected( i_rowIndex );
+ }
+
+ m_pImpl->invalidateRowRange( i_rowIndex, i_rowIndex );
+ Select();
+ }
+
+
+ void TableControl::SelectAllRows( bool const i_select )
+ {
+ if ( i_select )
+ {
+ if ( !m_pImpl->markAllRowsAsSelected() )
+ // nothing to do
+ return;
+ }
+ else
+ {
+ if ( !m_pImpl->markAllRowsAsDeselected() )
+ // nothing to do
+ return;
+ }
+
+
+ Invalidate();
+ // TODO: can't we do better than this, and invalidate only the rows which changed?
+ Select();
+ }
+
+
+ ITableControl& TableControl::getTableControlInterface()
+ {
+ return *m_pImpl;
+ }
+
+
+ SelectionEngine* TableControl::getSelEngine()
+ {
+ return m_pImpl->getSelEngine();
+ }
+
+
+ vcl::Window& TableControl::getDataWindow()
+ {
+ return m_pImpl->getDataWindow();
+ }
+
+
+ Reference< XAccessible > TableControl::CreateAccessible()
+ {
+ vcl::Window* pParent = GetAccessibleParentWindow();
+ ENSURE_OR_RETURN( pParent, "TableControl::CreateAccessible - parent not found", nullptr );
+
+ return m_pImpl->getAccessible( *pParent );
+ }
+
+
+ Reference<XAccessible> TableControl::CreateAccessibleControl( sal_Int32 )
+ {
+ SAL_WARN( "svtools", "TableControl::CreateAccessibleControl: to be overwritten!" );
+ return nullptr;
+ }
+
+
+ OUString TableControl::GetAccessibleObjectName( vcl::table::AccessibleTableControlObjType eObjType, sal_Int32 _nRow, sal_Int32 _nCol) const
+ {
+ OUString aRetText;
+ //Window* pWin;
+ switch( eObjType )
+ {
+ case vcl::table::AccessibleTableControlObjType::GRIDCONTROL:
+ aRetText = "Grid control";
+ break;
+ case vcl::table::AccessibleTableControlObjType::TABLE:
+ aRetText = "Grid control";
+ break;
+ case vcl::table::AccessibleTableControlObjType::ROWHEADERBAR:
+ aRetText = "RowHeaderBar";
+ break;
+ case vcl::table::AccessibleTableControlObjType::COLUMNHEADERBAR:
+ aRetText = "ColumnHeaderBar";
+ break;
+ case vcl::table::AccessibleTableControlObjType::TABLECELL:
+ //the name of the cell consists of column name and row name if defined
+ //if the name is equal to cell content, it'll be read twice
+ if(GetModel()->hasColumnHeaders())
+ {
+ aRetText = GetColumnName(_nCol) + " , ";
+ }
+ if(GetModel()->hasRowHeaders())
+ {
+ aRetText += GetRowName(_nRow) + " , ";
+ }
+ //aRetText = GetAccessibleCellText(_nRow, _nCol);
+ break;
+ case vcl::table::AccessibleTableControlObjType::ROWHEADERCELL:
+ aRetText = GetRowName(_nRow);
+ break;
+ case vcl::table::AccessibleTableControlObjType::COLUMNHEADERCELL:
+ aRetText = GetColumnName(_nCol);
+ break;
+ default:
+ OSL_FAIL("GridControl::GetAccessibleName: invalid enum!");
+ }
+ return aRetText;
+ }
+
+
+ OUString TableControl::GetAccessibleObjectDescription( vcl::table::AccessibleTableControlObjType eObjType ) const
+ {
+ OUString aRetText;
+ switch( eObjType )
+ {
+ case vcl::table::AccessibleTableControlObjType::GRIDCONTROL:
+ aRetText = "Grid control description";
+ break;
+ case vcl::table::AccessibleTableControlObjType::TABLE:
+ aRetText = "TABLE description";
+ break;
+ case vcl::table::AccessibleTableControlObjType::ROWHEADERBAR:
+ aRetText = "ROWHEADERBAR description";
+ break;
+ case vcl::table::AccessibleTableControlObjType::COLUMNHEADERBAR:
+ aRetText = "COLUMNHEADERBAR description";
+ break;
+ case vcl::table::AccessibleTableControlObjType::TABLECELL:
+ // the description of the cell consists of column name and row name if defined
+ // if the name is equal to cell content, it'll be read twice
+ if ( GetModel()->hasColumnHeaders() )
+ {
+ aRetText = GetColumnName( GetCurrentColumn() ) + " , ";
+ }
+ if ( GetModel()->hasRowHeaders() )
+ {
+ aRetText += GetRowName( GetCurrentRow() );
+ }
+ break;
+ case vcl::table::AccessibleTableControlObjType::ROWHEADERCELL:
+ aRetText = "ROWHEADERCELL description";
+ break;
+ case vcl::table::AccessibleTableControlObjType::COLUMNHEADERCELL:
+ aRetText = "COLUMNHEADERCELL description";
+ break;
+ }
+ return aRetText;
+ }
+
+
+ OUString TableControl::GetRowName( sal_Int32 _nIndex) const
+ {
+ OUString sRowName;
+ GetModel()->getRowHeading( _nIndex ) >>= sRowName;
+ return sRowName;
+ }
+
+
+ OUString TableControl::GetColumnName( sal_Int32 _nIndex) const
+ {
+ return GetModel()->getColumnModel(_nIndex)->getName();
+ }
+
+
+ OUString TableControl::GetAccessibleCellText( sal_Int32 _nRowPos, sal_Int32 _nColPos) const
+ {
+ return m_pImpl->getCellContentAsString( _nRowPos, _nColPos );
+ }
+
+
+ void TableControl::FillAccessibleStateSet(
+ sal_Int64& rStateSet,
+ vcl::table::AccessibleTableControlObjType eObjType ) const
+ {
+ switch( eObjType )
+ {
+ case vcl::table::AccessibleTableControlObjType::GRIDCONTROL:
+ case vcl::table::AccessibleTableControlObjType::TABLE:
+
+ rStateSet |= AccessibleStateType::FOCUSABLE;
+
+ if ( m_pImpl->getSelEngine()->GetSelectionMode() == SelectionMode::Multiple )
+ rStateSet |= AccessibleStateType::MULTI_SELECTABLE;
+
+ if ( HasChildPathFocus() )
+ rStateSet |= AccessibleStateType::FOCUSED;
+
+ if ( IsActive() )
+ rStateSet |= AccessibleStateType::ACTIVE;
+
+ if ( m_pImpl->getDataWindow().IsEnabled() )
+ {
+ rStateSet |= AccessibleStateType::ENABLED;
+ rStateSet |= AccessibleStateType::SENSITIVE;
+ }
+
+ if ( IsReallyVisible() )
+ rStateSet |= AccessibleStateType::VISIBLE;
+
+ if ( eObjType == vcl::table::AccessibleTableControlObjType::TABLE )
+ rStateSet |= AccessibleStateType::MANAGES_DESCENDANTS;
+ break;
+
+ case vcl::table::AccessibleTableControlObjType::ROWHEADERBAR:
+ rStateSet |= AccessibleStateType::VISIBLE;
+ rStateSet |= AccessibleStateType::MANAGES_DESCENDANTS;
+ break;
+
+ case vcl::table::AccessibleTableControlObjType::COLUMNHEADERBAR:
+ rStateSet |= AccessibleStateType::VISIBLE;
+ rStateSet |= AccessibleStateType::MANAGES_DESCENDANTS;
+ break;
+
+ case vcl::table::AccessibleTableControlObjType::TABLECELL:
+ {
+ rStateSet |= AccessibleStateType::FOCUSABLE;
+ if ( HasChildPathFocus() )
+ rStateSet |= AccessibleStateType::FOCUSED;
+ rStateSet |= AccessibleStateType::ACTIVE;
+ rStateSet |= AccessibleStateType::TRANSIENT;
+ rStateSet |= AccessibleStateType::SELECTABLE;
+ rStateSet |= AccessibleStateType::VISIBLE;
+ rStateSet |= AccessibleStateType::SHOWING;
+ if ( IsRowSelected( GetCurrentRow() ) )
+ // Hmm? Wouldn't we expect the affected row to be a parameter to this function?
+ rStateSet |= AccessibleStateType::SELECTED;
+ }
+ break;
+
+ case vcl::table::AccessibleTableControlObjType::ROWHEADERCELL:
+ rStateSet |= AccessibleStateType::VISIBLE;
+ rStateSet |= AccessibleStateType::TRANSIENT;
+ break;
+
+ case vcl::table::AccessibleTableControlObjType::COLUMNHEADERCELL:
+ rStateSet |= AccessibleStateType::VISIBLE;
+ break;
+ }
+ }
+
+ void TableControl::commitCellEventIfAccessibleAlive( sal_Int16 const i_eventID, const Any& i_newValue, const Any& i_oldValue )
+ {
+ if ( m_pImpl->isAccessibleAlive() )
+ m_pImpl->commitCellEvent( i_eventID, i_newValue, i_oldValue );
+ }
+
+ void TableControl::commitTableEventIfAccessibleAlive( sal_Int16 const i_eventID, const Any& i_newValue, const Any& i_oldValue )
+ {
+ if ( m_pImpl->isAccessibleAlive() )
+ m_pImpl->commitTableEvent( i_eventID, i_newValue, i_oldValue );
+ }
+
+ AbsoluteScreenPixelRectangle TableControl::GetWindowExtentsAbsolute() const
+ {
+ return Control::GetWindowExtentsAbsolute();
+ }
+
+ tools::Rectangle TableControl::GetWindowExtentsRelative(const vcl::Window& rRelativeWindow) const
+ {
+ return Control::GetWindowExtentsRelative( rRelativeWindow );
+ }
+
+ void TableControl::GrabFocus()
+ {
+ Control::GrabFocus();
+ }
+
+ Reference< XAccessible > TableControl::GetAccessible()
+ {
+ return Control::GetAccessible();
+ }
+
+ vcl::Window* TableControl::GetAccessibleParentWindow() const
+ {
+ return Control::GetAccessibleParentWindow();
+ }
+
+ vcl::Window* TableControl::GetWindowInstance()
+ {
+ return this;
+ }
+
+
+ bool TableControl::HasRowHeader()
+ {
+ return GetModel()->hasRowHeaders();
+ }
+
+
+ bool TableControl::HasColHeader()
+ {
+ return GetModel()->hasColumnHeaders();
+ }
+
+
+ sal_Int32 TableControl::GetAccessibleControlCount() const
+ {
+ // TC_TABLE is always defined, no matter whether empty or not
+ sal_Int32 count = 1;
+ if ( GetModel()->hasRowHeaders() )
+ ++count;
+ if ( GetModel()->hasColumnHeaders() )
+ ++count;
+ return count;
+ }
+
+
+ bool TableControl::ConvertPointToControlIndex( sal_Int32& _rnIndex, const Point& _rPoint )
+ {
+ sal_Int32 nRow = m_pImpl->getRowAtPoint( _rPoint );
+ sal_Int32 nCol = m_pImpl->getColAtPoint( _rPoint );
+ _rnIndex = nRow * GetColumnCount() + nCol;
+ return nRow >= 0;
+ }
+
+
+ sal_Int32 TableControl::GetRowCount() const
+ {
+ return GetModel()->getRowCount();
+ }
+
+
+ sal_Int32 TableControl::GetColumnCount() const
+ {
+ return GetModel()->getColumnCount();
+ }
+
+
+ bool TableControl::ConvertPointToCellAddress( sal_Int32& _rnRow, sal_Int32& _rnColPos, const Point& _rPoint )
+ {
+ _rnRow = m_pImpl->getRowAtPoint( _rPoint );
+ _rnColPos = m_pImpl->getColAtPoint( _rPoint );
+ return _rnRow >= 0;
+ }
+
+
+ void TableControl::FillAccessibleStateSetForCell( sal_Int64& _rStateSet, sal_Int32 _nRow, sal_uInt16 ) const
+ {
+ if ( IsRowSelected( _nRow ) )
+ _rStateSet |= AccessibleStateType::SELECTED;
+ if ( HasChildPathFocus() )
+ _rStateSet |= AccessibleStateType::FOCUSED;
+ else // only transient when column is not focused
+ _rStateSet |= AccessibleStateType::TRANSIENT;
+
+ _rStateSet |= AccessibleStateType::VISIBLE;
+ _rStateSet |= AccessibleStateType::SHOWING;
+ _rStateSet |= AccessibleStateType::ENABLED;
+ _rStateSet |= AccessibleStateType::SENSITIVE;
+ _rStateSet |= AccessibleStateType::ACTIVE;
+ }
+
+
+ tools::Rectangle TableControl::GetFieldCharacterBounds(sal_Int32,sal_Int32,sal_Int32 nIndex)
+ {
+ return GetCharacterBounds(nIndex);
+ }
+
+
+ sal_Int32 TableControl::GetFieldIndexAtPoint(sal_Int32,sal_Int32,const Point& _rPoint)
+ {
+ return GetIndexForPoint(_rPoint);
+ }
+
+
+ tools::Rectangle TableControl::calcHeaderRect(bool _bIsColumnBar )
+ {
+ return m_pImpl->calcHeaderRect( !_bIsColumnBar );
+ }
+
+
+ tools::Rectangle TableControl::calcHeaderCellRect( bool _bIsColumnBar, sal_Int32 nPos )
+ {
+ return m_pImpl->calcHeaderCellRect( _bIsColumnBar, nPos );
+ }
+
+
+ tools::Rectangle TableControl::calcTableRect()
+ {
+ return m_pImpl->calcTableRect();
+ }
+
+
+ tools::Rectangle TableControl::calcCellRect( sal_Int32 _nRowPos, sal_Int32 _nColPos )
+ {
+ return m_pImpl->calcCellRect( _nRowPos, _nColPos );
+ }
+
+
+ IMPL_LINK_NOARG(TableControl, ImplSelectHdl, LinkParamNone*, void)
+ {
+ Select();
+ }
+
+
+ void TableControl::Select()
+ {
+ ImplCallEventListenersAndHandler( VclEventId::TableRowSelect, nullptr );
+
+ if ( m_pImpl->isAccessibleAlive() )
+ {
+ m_pImpl->commitAccessibleEvent( AccessibleEventId::SELECTION_CHANGED );
+
+ m_pImpl->commitTableEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, Any(), Any() );
+ // TODO: why do we notify this when the *selection* changed? Shouldn't we find a better place for this,
+ // actually, when the active descendant, i.e. the current cell, *really* changed?
+ }
+ }
+
+} // namespace svt::table
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/table/tablecontrol_impl.cxx b/toolkit/source/controls/table/tablecontrol_impl.cxx
new file mode 100644
index 0000000000..99c7b815ca
--- /dev/null
+++ b/toolkit/source/controls/table/tablecontrol_impl.cxx
@@ -0,0 +1,2551 @@
+/* -*- 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/table/tablecontrol.hxx>
+#include <controls/table/defaultinputhandler.hxx>
+#include <controls/table/tablemodel.hxx>
+
+#include "tabledatawindow.hxx"
+#include "tablecontrol_impl.hxx"
+#include "tablegeometry.hxx"
+
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/AccessibleTableModelChange.hpp>
+#include <com/sun/star/accessibility/AccessibleEventId.hpp>
+#include <com/sun/star/accessibility/AccessibleTableModelChangeType.hpp>
+
+#include <comphelper/flagguard.hxx>
+#include <vcl/accessiblefactory.hxx>
+#include <vcl/toolkit/scrbar.hxx>
+#include <vcl/seleng.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/image.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <tools/debug.hxx>
+
+#include <cstdlib>
+#include <numeric>
+
+#define MIN_COLUMN_WIDTH_PIXEL 4
+
+
+namespace svt::table
+{
+
+
+ using ::com::sun::star::accessibility::AccessibleTableModelChange;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::accessibility::XAccessible;
+ using ::com::sun::star::uno::Reference;
+
+ namespace AccessibleEventId = ::com::sun::star::accessibility::AccessibleEventId;
+ namespace AccessibleTableModelChangeType = ::com::sun::star::accessibility::AccessibleTableModelChangeType;
+
+
+ //= SuppressCursor
+
+ namespace {
+
+ class SuppressCursor
+ {
+ private:
+ ITableControl& m_rTable;
+
+ public:
+ explicit SuppressCursor( ITableControl& _rTable )
+ :m_rTable( _rTable )
+ {
+ m_rTable.hideCursor();
+ }
+ ~SuppressCursor()
+ {
+ m_rTable.showCursor();
+ }
+ };
+
+
+ //= EmptyTableModel
+
+ /** default implementation of an ->ITableModel, used as fallback when no
+ real model is present
+
+ Instances of this class are static in any way, and provide the least
+ necessary default functionality for a table model.
+ */
+ class EmptyTableModel : public ITableModel
+ {
+ public:
+ EmptyTableModel()
+ {
+ }
+
+ // ITableModel overridables
+ virtual TableSize getColumnCount() const override
+ {
+ return 0;
+ }
+ virtual TableSize getRowCount() const override
+ {
+ return 0;
+ }
+ virtual bool hasColumnHeaders() const override
+ {
+ return false;
+ }
+ virtual bool hasRowHeaders() const override
+ {
+ return false;
+ }
+ virtual PColumnModel getColumnModel( ColPos ) override
+ {
+ OSL_FAIL( "EmptyTableModel::getColumnModel: invalid call!" );
+ return PColumnModel();
+ }
+ virtual PTableRenderer getRenderer() const override
+ {
+ return PTableRenderer();
+ }
+ virtual PTableInputHandler getInputHandler() const override
+ {
+ return PTableInputHandler();
+ }
+ virtual TableMetrics getRowHeight() const override
+ {
+ return 5 * 100;
+ }
+ virtual TableMetrics getColumnHeaderHeight() const override
+ {
+ return 0;
+ }
+ virtual TableMetrics getRowHeaderWidth() const override
+ {
+ return 0;
+ }
+ virtual ScrollbarVisibility getVerticalScrollbarVisibility() const override
+ {
+ return ScrollbarShowNever;
+ }
+ virtual ScrollbarVisibility getHorizontalScrollbarVisibility() const override
+ {
+ return ScrollbarShowNever;
+ }
+ virtual void addTableModelListener( const PTableModelListener& ) override {}
+ virtual void removeTableModelListener( const PTableModelListener& ) override {}
+ virtual ::std::optional< ::Color > getLineColor() const override
+ {
+ return ::std::optional< ::Color >();
+ }
+ virtual ::std::optional< ::Color > getHeaderBackgroundColor() const override
+ {
+ return ::std::optional< ::Color >();
+ }
+ virtual ::std::optional< ::Color > getHeaderTextColor() const override
+ {
+ return ::std::optional< ::Color >();
+ }
+ virtual ::std::optional< ::Color > getActiveSelectionBackColor() const override
+ {
+ return ::std::optional< ::Color >();
+ }
+ virtual ::std::optional< ::Color > getInactiveSelectionBackColor() const override
+ {
+ return ::std::optional< ::Color >();
+ }
+ virtual ::std::optional< ::Color > getActiveSelectionTextColor() const override
+ {
+ return ::std::optional< ::Color >();
+ }
+ virtual ::std::optional< ::Color > getInactiveSelectionTextColor() const override
+ {
+ return ::std::optional< ::Color >();
+ }
+ virtual ::std::optional< ::Color > getTextColor() const override
+ {
+ return ::std::optional< ::Color >();
+ }
+ virtual ::std::optional< ::Color > getTextLineColor() const override
+ {
+ return ::std::optional< ::Color >();
+ }
+ virtual ::std::optional< ::std::vector< ::Color > > getRowBackgroundColors() const override
+ {
+ return ::std::optional< ::std::vector< ::Color > >();
+ }
+ virtual css::style::VerticalAlignment getVerticalAlign() const override
+ {
+ return css::style::VerticalAlignment(0);
+ }
+ virtual ITableDataSort* getSortAdapter() override
+ {
+ return nullptr;
+ }
+ virtual bool isEnabled() const override
+ {
+ return true;
+ }
+ virtual void getCellContent( ColPos const, RowPos const, css::uno::Any& o_cellContent ) override
+ {
+ o_cellContent.clear();
+ }
+ virtual void getCellToolTip( ColPos const, RowPos const, css::uno::Any& ) override
+ {
+ }
+ virtual Any getRowHeading( RowPos const ) const override
+ {
+ return Any();
+ }
+ };
+
+ }
+
+ TableControl_Impl::TableControl_Impl( TableControl& _rAntiImpl )
+ :m_rAntiImpl ( _rAntiImpl )
+ ,m_pModel ( std::make_shared<EmptyTableModel>() )
+ ,m_pInputHandler ( )
+ ,m_nRowHeightPixel ( 15 )
+ ,m_nColHeaderHeightPixel( 0 )
+ ,m_nRowHeaderWidthPixel ( 0 )
+ ,m_nColumnCount ( 0 )
+ ,m_nRowCount ( 0 )
+ ,m_nCurColumn ( COL_INVALID )
+ ,m_nCurRow ( ROW_INVALID )
+ ,m_nLeftColumn ( 0 )
+ ,m_nTopRow ( 0 )
+ ,m_nCursorHidden ( 1 )
+ ,m_pDataWindow ( VclPtr<TableDataWindow>::Create( *this ) )
+ ,m_pVScroll ( nullptr )
+ ,m_pHScroll ( nullptr )
+ ,m_pScrollCorner ( nullptr )
+ ,m_aSelectedRows ( )
+ ,m_pTableFunctionSet ( new TableFunctionSet( this ) )
+ ,m_nAnchor ( -1 )
+ ,m_bUpdatingColWidths ( false )
+ {
+ m_pSelEngine.reset( new SelectionEngine( m_pDataWindow.get(), m_pTableFunctionSet.get() ) );
+ m_pSelEngine->SetSelectionMode(SelectionMode::Single);
+ m_pDataWindow->SetPosPixel( Point( 0, 0 ) );
+ m_pDataWindow->Show();
+ }
+
+ TableControl_Impl::~TableControl_Impl()
+ {
+ m_pVScroll.disposeAndClear();
+ m_pHScroll.disposeAndClear();
+ m_pScrollCorner.disposeAndClear();
+ m_pDataWindow.disposeAndClear();
+ m_pTableFunctionSet.reset();
+ m_pSelEngine.reset();
+ }
+
+ void TableControl_Impl::setModel( const PTableModel& _pModel )
+ {
+ SuppressCursor aHideCursor( *this );
+
+ if ( m_pModel )
+ m_pModel->removeTableModelListener( shared_from_this() );
+
+ m_pModel = _pModel;
+ if ( !m_pModel)
+ m_pModel = std::make_shared<EmptyTableModel>();
+
+ m_pModel->addTableModelListener( shared_from_this() );
+
+ m_nCurRow = ROW_INVALID;
+ m_nCurColumn = COL_INVALID;
+
+ // recalc some model-dependent cached info
+ impl_ni_updateCachedModelValues();
+ impl_ni_relayout();
+
+ // completely invalidate
+ m_rAntiImpl.Invalidate();
+
+ // reset cursor to (0,0)
+ if ( m_nRowCount ) m_nCurRow = 0;
+ if ( m_nColumnCount ) m_nCurColumn = 0;
+ }
+
+
+ namespace
+ {
+ bool lcl_adjustSelectedRows( ::std::vector< RowPos >& io_selectionIndexes, RowPos const i_firstAffectedRowIndex, TableSize const i_offset )
+ {
+ bool didChanges = false;
+ for (auto & selectionIndex : io_selectionIndexes)
+ {
+ if ( selectionIndex < i_firstAffectedRowIndex )
+ continue;
+ selectionIndex += i_offset;
+ didChanges = true;
+ }
+ return didChanges;
+ }
+ }
+
+
+ void TableControl_Impl::rowsInserted( RowPos i_first, RowPos i_last )
+ {
+ OSL_PRECOND( i_last >= i_first, "TableControl_Impl::rowsInserted: invalid row indexes!" );
+
+ TableSize const insertedRows = i_last - i_first + 1;
+
+ // adjust selection, if necessary
+ bool const selectionChanged = lcl_adjustSelectedRows( m_aSelectedRows, i_first, insertedRows );
+
+ // adjust our cached row count
+ m_nRowCount = m_pModel->getRowCount();
+
+ // if the rows have been inserted before the current row, adjust this
+ if ( i_first <= m_nCurRow )
+ goTo( m_nCurColumn, m_nCurRow + insertedRows );
+
+ // relayout, since the scrollbar need might have changed
+ impl_ni_relayout();
+
+ // notify A1YY events
+ if ( impl_isAccessibleAlive() )
+ {
+ impl_commitAccessibleEvent( AccessibleEventId::TABLE_MODEL_CHANGED,
+ Any( AccessibleTableModelChange( AccessibleTableModelChangeType::ROWS_INSERTED, i_first, i_last, -1, -1 ) )
+ );
+ }
+
+ // schedule repaint
+ invalidateRowRange( i_first, ROW_INVALID );
+
+ // call selection handlers, if necessary
+ if ( selectionChanged )
+ m_rAntiImpl.Select();
+ }
+
+
+ void TableControl_Impl::rowsRemoved( RowPos i_first, RowPos i_last )
+ {
+ sal_Int32 firstRemovedRow = i_first;
+ sal_Int32 lastRemovedRow = i_last;
+
+ // adjust selection, if necessary
+ bool selectionChanged = false;
+ if ( i_first == -1 )
+ {
+ selectionChanged = markAllRowsAsDeselected();
+
+ firstRemovedRow = 0;
+ lastRemovedRow = m_nRowCount - 1;
+ }
+ else
+ {
+ ENSURE_OR_RETURN_VOID( i_last >= i_first, "TableControl_Impl::rowsRemoved: illegal indexes!" );
+
+ for ( sal_Int32 row = i_first; row <= i_last; ++row )
+ {
+ if ( markRowAsDeselected( row ) )
+ selectionChanged = true;
+ }
+
+ if ( lcl_adjustSelectedRows( m_aSelectedRows, i_last + 1, i_first - i_last - 1 ) )
+ selectionChanged = true;
+ }
+
+ // adjust cached row count
+ m_nRowCount = m_pModel->getRowCount();
+
+ // adjust the current row, if it is larger than the row count now
+ if ( m_nCurRow >= m_nRowCount )
+ {
+ if ( m_nRowCount > 0 )
+ goTo( m_nCurColumn, m_nRowCount - 1 );
+ else
+ {
+ m_nCurRow = ROW_INVALID;
+ m_nTopRow = 0;
+ }
+ }
+ else if ( m_nRowCount == 0 )
+ {
+ m_nTopRow = 0;
+ }
+
+
+ // relayout, since the scrollbar need might have changed
+ impl_ni_relayout();
+
+ // notify A11Y events
+ if ( impl_isAccessibleAlive() )
+ {
+ commitTableEvent(
+ AccessibleEventId::TABLE_MODEL_CHANGED,
+ Any( AccessibleTableModelChange(
+ AccessibleTableModelChangeType::ROWS_REMOVED,
+ firstRemovedRow,
+ lastRemovedRow,
+ -1,
+ -1
+ ) ),
+ Any()
+ );
+ }
+
+ // schedule a repaint
+ invalidateRowRange( firstRemovedRow, ROW_INVALID );
+
+ // call selection handlers, if necessary
+ if ( selectionChanged )
+ m_rAntiImpl.Select();
+ }
+
+
+ void TableControl_Impl::columnInserted()
+ {
+ m_nColumnCount = m_pModel->getColumnCount();
+ impl_ni_relayout();
+
+ m_rAntiImpl.Invalidate();
+ }
+
+
+ void TableControl_Impl::columnRemoved()
+ {
+ m_nColumnCount = m_pModel->getColumnCount();
+
+ // adjust the current column, if it is larger than the column count now
+ if ( m_nCurColumn >= m_nColumnCount )
+ {
+ if ( m_nColumnCount > 0 )
+ goTo( m_nCurColumn - 1, m_nCurRow );
+ else
+ m_nCurColumn = COL_INVALID;
+ }
+
+ impl_ni_relayout();
+
+ m_rAntiImpl.Invalidate();
+ }
+
+
+ void TableControl_Impl::allColumnsRemoved()
+ {
+ m_nColumnCount = m_pModel->getColumnCount();
+ impl_ni_relayout();
+
+ m_rAntiImpl.Invalidate();
+ }
+
+
+ void TableControl_Impl::cellsUpdated( RowPos const i_firstRow, RowPos const i_lastRow )
+ {
+ invalidateRowRange( i_firstRow, i_lastRow );
+ }
+
+
+ void TableControl_Impl::tableMetricsChanged()
+ {
+ impl_ni_updateCachedTableMetrics();
+ impl_ni_relayout();
+ m_rAntiImpl.Invalidate();
+ }
+
+
+ void TableControl_Impl::impl_invalidateColumn( ColPos const i_column )
+ {
+ tools::Rectangle const aAllCellsArea( impl_getAllVisibleCellsArea() );
+
+ const TableColumnGeometry aColumn( *this, aAllCellsArea, i_column );
+ if ( aColumn.isValid() )
+ m_rAntiImpl.Invalidate( aColumn.getRect() );
+ }
+
+
+ void TableControl_Impl::columnChanged( ColPos const i_column, ColumnAttributeGroup const i_attributeGroup )
+ {
+ ColumnAttributeGroup nGroup( i_attributeGroup );
+ if ( nGroup & ColumnAttributeGroup::APPEARANCE )
+ {
+ impl_invalidateColumn( i_column );
+ nGroup &= ~ColumnAttributeGroup::APPEARANCE;
+ }
+
+ if ( nGroup & ColumnAttributeGroup::WIDTH )
+ {
+ if ( !m_bUpdatingColWidths )
+ {
+ impl_ni_relayout( i_column );
+ invalidate( TableArea::All );
+ }
+
+ nGroup &= ~ColumnAttributeGroup::WIDTH;
+ }
+
+ OSL_ENSURE( ( nGroup == ColumnAttributeGroup::NONE ) || ( i_attributeGroup == ColumnAttributeGroup::ALL ),
+ "TableControl_Impl::columnChanged: don't know how to handle this change!" );
+ }
+
+
+ tools::Rectangle TableControl_Impl::impl_getAllVisibleCellsArea() const
+ {
+ tools::Rectangle aArea( Point( 0, 0 ), Size( 0, 0 ) );
+
+ // determine the right-most border of the last column which is
+ // at least partially visible
+ aArea.SetRight( m_nRowHeaderWidthPixel );
+ if ( !m_aColumnWidths.empty() )
+ {
+ // the number of pixels which are scrolled out of the left hand
+ // side of the window
+ const tools::Long nScrolledOutLeft = m_nLeftColumn == 0 ? 0 : m_aColumnWidths[ m_nLeftColumn - 1 ].getEnd();
+
+ ColumnPositions::const_reverse_iterator loop = m_aColumnWidths.rbegin();
+ do
+ {
+ aArea.SetRight(loop->getEnd() - nScrolledOutLeft);
+ ++loop;
+ }
+ while ( ( loop != m_aColumnWidths.rend() )
+ && ( loop->getEnd() - nScrolledOutLeft >= aArea.Right() )
+ );
+ }
+ // so far, aArea.Right() denotes the first pixel *after* the cell area
+ aArea.AdjustRight( -1 );
+
+ // determine the last row which is at least partially visible
+ aArea.SetBottom(
+ m_nColHeaderHeightPixel
+ + impl_getVisibleRows( true ) * m_nRowHeightPixel
+ - 1 );
+
+ return aArea;
+ }
+
+
+ tools::Rectangle TableControl_Impl::impl_getAllVisibleDataCellArea() const
+ {
+ tools::Rectangle aArea( impl_getAllVisibleCellsArea() );
+ aArea.SetLeft( m_nRowHeaderWidthPixel );
+ aArea.SetTop( m_nColHeaderHeightPixel );
+ return aArea;
+ }
+
+
+ void TableControl_Impl::impl_ni_updateCachedTableMetrics()
+ {
+ m_nRowHeightPixel = m_rAntiImpl.LogicToPixel(Size(0, m_pModel->getRowHeight()), MapMode(MapUnit::MapAppFont)).Height();
+
+ m_nColHeaderHeightPixel = 0;
+ if ( m_pModel->hasColumnHeaders() )
+ m_nColHeaderHeightPixel = m_rAntiImpl.LogicToPixel(Size(0, m_pModel->getColumnHeaderHeight()), MapMode(MapUnit::MapAppFont)).Height();
+
+ m_nRowHeaderWidthPixel = 0;
+ if ( m_pModel->hasRowHeaders() )
+ m_nRowHeaderWidthPixel = m_rAntiImpl.LogicToPixel(Size(m_pModel->getRowHeaderWidth(), 0), MapMode(MapUnit::MapAppFont)).Width();
+ }
+
+
+ void TableControl_Impl::impl_ni_updateCachedModelValues()
+ {
+ m_pInputHandler = m_pModel->getInputHandler();
+ if ( !m_pInputHandler )
+ m_pInputHandler = std::make_shared<DefaultInputHandler>();
+
+ m_nColumnCount = m_pModel->getColumnCount();
+ if ( m_nLeftColumn >= m_nColumnCount )
+ m_nLeftColumn = ( m_nColumnCount > 0 ) ? m_nColumnCount - 1 : 0;
+
+ m_nRowCount = m_pModel->getRowCount();
+ if ( m_nTopRow >= m_nRowCount )
+ m_nTopRow = ( m_nRowCount > 0 ) ? m_nRowCount - 1 : 0;
+
+ impl_ni_updateCachedTableMetrics();
+ }
+
+
+ namespace
+ {
+
+ /// determines whether a scrollbar is needed for the given values
+ bool lcl_determineScrollbarNeed( tools::Long const i_position, ScrollbarVisibility const i_visibility,
+ tools::Long const i_availableSpace, tools::Long const i_neededSpace )
+ {
+ if ( i_visibility == ScrollbarShowNever )
+ return false;
+ if ( i_visibility == ScrollbarShowAlways )
+ return true;
+ if ( i_position > 0 )
+ return true;
+ if ( i_availableSpace >= i_neededSpace )
+ return false;
+ return true;
+ }
+
+
+ void lcl_setButtonRepeat( vcl::Window& _rWindow )
+ {
+ AllSettings aSettings = _rWindow.GetSettings();
+ MouseSettings aMouseSettings = aSettings.GetMouseSettings();
+
+ aMouseSettings.SetButtonRepeat( 0 );
+ aSettings.SetMouseSettings( aMouseSettings );
+
+ _rWindow.SetSettings( aSettings, true );
+ }
+
+
+ bool lcl_updateScrollbar( vcl::Window& _rParent, VclPtr<ScrollBar>& _rpBar,
+ bool const i_needBar, tools::Long _nVisibleUnits,
+ tools::Long _nPosition, tools::Long _nRange,
+ bool _bHorizontal, const Link<ScrollBar*,void>& _rScrollHandler )
+ {
+ // do we currently have the scrollbar?
+ bool bHaveBar = _rpBar != nullptr;
+
+ // do we need to correct the scrollbar visibility?
+ if ( bHaveBar && !i_needBar )
+ {
+ if ( _rpBar->IsTracking() )
+ _rpBar->EndTracking();
+ _rpBar.disposeAndClear();
+ }
+ else if ( !bHaveBar && i_needBar )
+ {
+ _rpBar = VclPtr<ScrollBar>::Create(
+
+ &_rParent,
+ WB_DRAG | ( _bHorizontal ? WB_HSCROLL : WB_VSCROLL )
+ );
+ _rpBar->SetScrollHdl( _rScrollHandler );
+ // get some speed into the scrolling...
+ lcl_setButtonRepeat( *_rpBar );
+ }
+
+ if ( _rpBar )
+ {
+ _rpBar->SetRange( Range( 0, _nRange ) );
+ _rpBar->SetVisibleSize( _nVisibleUnits );
+ _rpBar->SetPageSize( _nVisibleUnits );
+ _rpBar->SetLineSize( 1 );
+ _rpBar->SetThumbPos( _nPosition );
+ _rpBar->Show();
+ }
+
+ return ( bHaveBar != i_needBar );
+ }
+
+
+ /** returns the number of rows fitting into the given range,
+ for the given row height. Partially fitting rows are counted, too, if the
+ respective parameter says so.
+ */
+ TableSize lcl_getRowsFittingInto( tools::Long _nOverallHeight, tools::Long _nRowHeightPixel, bool _bAcceptPartialRow )
+ {
+ return _bAcceptPartialRow
+ ? ( _nOverallHeight + ( _nRowHeightPixel - 1 ) ) / _nRowHeightPixel
+ : _nOverallHeight / _nRowHeightPixel;
+ }
+
+
+ /** returns the number of columns fitting into the given area,
+ with the first visible column as given. Partially fitting columns are counted, too,
+ if the respective parameter says so.
+ */
+ TableSize lcl_getColumnsVisibleWithin( const tools::Rectangle& _rArea, ColPos _nFirstVisibleColumn,
+ const TableControl_Impl& _rControl, bool _bAcceptPartialRow )
+ {
+ TableSize visibleColumns = 0;
+ TableColumnGeometry aColumn( _rControl, _rArea, _nFirstVisibleColumn );
+ while ( aColumn.isValid() )
+ {
+ if ( !_bAcceptPartialRow )
+ if ( aColumn.getRect().Right() > _rArea.Right() )
+ // this column is only partially visible, and this is not allowed
+ break;
+
+ aColumn.moveRight();
+ ++visibleColumns;
+ }
+ return visibleColumns;
+ }
+
+ }
+
+
+ tools::Long TableControl_Impl::impl_ni_calculateColumnWidths( ColPos const i_assumeInflexibleColumnsUpToIncluding,
+ bool const i_assumeVerticalScrollbar, ::std::vector< tools::Long >& o_newColWidthsPixel ) const
+ {
+ // the available horizontal space
+ tools::Long gridWidthPixel = m_rAntiImpl.GetOutputSizePixel().Width();
+ ENSURE_OR_RETURN( !!m_pModel, "TableControl_Impl::impl_ni_calculateColumnWidths: not allowed without a model!", gridWidthPixel );
+ if ( m_pModel->hasRowHeaders() && ( gridWidthPixel != 0 ) )
+ {
+ gridWidthPixel -= m_nRowHeaderWidthPixel;
+ }
+
+ if ( i_assumeVerticalScrollbar && ( m_pModel->getVerticalScrollbarVisibility() != ScrollbarShowNever ) )
+ {
+ tools::Long nScrollbarMetrics = m_rAntiImpl.GetSettings().GetStyleSettings().GetScrollBarSize();
+ gridWidthPixel -= nScrollbarMetrics;
+ }
+
+ // no need to do anything without columns
+ TableSize const colCount = m_pModel->getColumnCount();
+ if ( colCount == 0 )
+ return gridWidthPixel;
+
+ // collect some meta data for our columns:
+ // - their current (pixel) metrics
+ tools::Long accumulatedCurrentWidth = 0;
+ ::std::vector< tools::Long > currentColWidths;
+ currentColWidths.reserve( colCount );
+ typedef ::std::vector< ::std::pair< tools::Long, long > > ColumnLimits;
+ ColumnLimits effectiveColumnLimits;
+ effectiveColumnLimits.reserve( colCount );
+ tools::Long accumulatedMinWidth = 0;
+ tools::Long accumulatedMaxWidth = 0;
+ // - their relative flexibility
+ ::std::vector< ::sal_Int32 > columnFlexibilities;
+ columnFlexibilities.reserve( colCount );
+ tools::Long flexibilityDenominator = 0;
+ size_t flexibleColumnCount = 0;
+ for ( ColPos col = 0; col < colCount; ++col )
+ {
+ PColumnModel const pColumn = m_pModel->getColumnModel( col );
+ ENSURE_OR_THROW( !!pColumn, "invalid column returned by the model!" );
+
+ // current width
+ tools::Long const currentWidth = appFontWidthToPixel( pColumn->getWidth() );
+ currentColWidths.push_back( currentWidth );
+
+ // accumulated width
+ accumulatedCurrentWidth += currentWidth;
+
+ // flexibility
+ ::sal_Int32 flexibility = pColumn->getFlexibility();
+ OSL_ENSURE( flexibility >= 0, "TableControl_Impl::impl_ni_calculateColumnWidths: a column's flexibility should be non-negative." );
+ if ( ( flexibility < 0 ) // normalization
+ || ( !pColumn->isResizable() ) // column not resizable => no auto-resize
+ || ( col <= i_assumeInflexibleColumnsUpToIncluding ) // column shall be treated as inflexible => respect this
+ )
+ flexibility = 0;
+
+ // min/max width
+ tools::Long effectiveMin = currentWidth, effectiveMax = currentWidth;
+ // if the column is not flexible, it will not be asked for min/max, but we assume the current width as limit then
+ if ( flexibility > 0 )
+ {
+ tools::Long const minWidth = appFontWidthToPixel( pColumn->getMinWidth() );
+ if ( minWidth > 0 )
+ effectiveMin = minWidth;
+ else
+ effectiveMin = MIN_COLUMN_WIDTH_PIXEL;
+
+ tools::Long const maxWidth = appFontWidthToPixel( pColumn->getMaxWidth() );
+ OSL_ENSURE( minWidth <= maxWidth, "TableControl_Impl::impl_ni_calculateColumnWidths: pretty undecided 'bout its width limits, this column!" );
+ if ( ( maxWidth > 0 ) && ( maxWidth >= minWidth ) )
+ effectiveMax = maxWidth;
+ else
+ effectiveMax = gridWidthPixel; // TODO: any better guess here?
+
+ if ( effectiveMin == effectiveMax )
+ // if the min and the max are identical, this implies no flexibility at all
+ flexibility = 0;
+ }
+
+ columnFlexibilities.push_back( flexibility );
+ flexibilityDenominator += flexibility;
+ if ( flexibility > 0 )
+ ++flexibleColumnCount;
+
+ effectiveColumnLimits.emplace_back( effectiveMin, effectiveMax );
+ accumulatedMinWidth += effectiveMin;
+ accumulatedMaxWidth += effectiveMax;
+ }
+
+ o_newColWidthsPixel = currentColWidths;
+ if ( flexibilityDenominator == 0 )
+ {
+ // no column is flexible => don't adjust anything
+ }
+ else if ( gridWidthPixel > accumulatedCurrentWidth )
+ { // we have space to give away ...
+ tools::Long distributePixel = gridWidthPixel - accumulatedCurrentWidth;
+ if ( gridWidthPixel > accumulatedMaxWidth )
+ {
+ // ... but the column's maximal widths are still less than we have
+ // => set them all to max
+ for ( svt::table::TableSize i = 0; i < colCount; ++i )
+ {
+ o_newColWidthsPixel[i] = effectiveColumnLimits[i].second;
+ }
+ }
+ else
+ {
+ bool startOver = false;
+ do
+ {
+ startOver = false;
+ // distribute the remaining space amongst all columns with a positive flexibility
+ for ( size_t i=0; i<o_newColWidthsPixel.size() && !startOver; ++i )
+ {
+ tools::Long const columnFlexibility = columnFlexibilities[i];
+ if ( columnFlexibility == 0 )
+ continue;
+
+ tools::Long newColWidth = currentColWidths[i] + columnFlexibility * distributePixel / flexibilityDenominator;
+
+ if ( newColWidth > effectiveColumnLimits[i].second )
+ { // that was too much, we hit the col's maximum
+ // set the new width to exactly this maximum
+ newColWidth = effectiveColumnLimits[i].second;
+ // adjust the flexibility denominator ...
+ flexibilityDenominator -= columnFlexibility;
+ columnFlexibilities[i] = 0;
+ --flexibleColumnCount;
+ // ... and the remaining width ...
+ tools::Long const difference = newColWidth - currentColWidths[i];
+ distributePixel -= difference;
+ // ... this way, we ensure that the width not taken up by this column is consumed by the other
+ // flexible ones (if there are some)
+
+ // and start over with the first column, since there might be earlier columns which need
+ // to be recalculated now
+ startOver = true;
+ }
+
+ o_newColWidthsPixel[i] = newColWidth;
+ }
+ }
+ while ( startOver );
+
+ // are there pixels left (might be caused by rounding errors)?
+ distributePixel = gridWidthPixel - ::std::accumulate( o_newColWidthsPixel.begin(), o_newColWidthsPixel.end(), 0 );
+ while ( ( distributePixel > 0 ) && ( flexibleColumnCount > 0 ) )
+ {
+ // yes => ignore relative flexibilities, and subsequently distribute single pixels to all flexible
+ // columns which did not yet reach their maximum.
+ for ( size_t i=0; ( i < o_newColWidthsPixel.size() ) && ( distributePixel > 0 ); ++i )
+ {
+ if ( columnFlexibilities[i] == 0 )
+ continue;
+
+ OSL_ENSURE( o_newColWidthsPixel[i] <= effectiveColumnLimits[i].second,
+ "TableControl_Impl::impl_ni_calculateColumnWidths: inconsistency!" );
+ if ( o_newColWidthsPixel[i] >= effectiveColumnLimits[i].first )
+ {
+ columnFlexibilities[i] = 0;
+ --flexibleColumnCount;
+ continue;
+ }
+
+ ++o_newColWidthsPixel[i];
+ --distributePixel;
+ }
+ }
+ }
+ }
+ else if ( gridWidthPixel < accumulatedCurrentWidth )
+ { // we need to take away some space from the columns which allow it ...
+ tools::Long takeAwayPixel = accumulatedCurrentWidth - gridWidthPixel;
+ if ( gridWidthPixel < accumulatedMinWidth )
+ {
+ // ... but the column's minimal widths are still more than we have
+ // => set them all to min
+ for ( svt::table::TableSize i = 0; i < colCount; ++i )
+ {
+ o_newColWidthsPixel[i] = effectiveColumnLimits[i].first;
+ }
+ }
+ else
+ {
+ bool startOver = false;
+ do
+ {
+ startOver = false;
+ // take away the space we need from the columns with a positive flexibility
+ for ( size_t i=0; i<o_newColWidthsPixel.size() && !startOver; ++i )
+ {
+ tools::Long const columnFlexibility = columnFlexibilities[i];
+ if ( columnFlexibility == 0 )
+ continue;
+
+ tools::Long newColWidth = currentColWidths[i] - columnFlexibility * takeAwayPixel / flexibilityDenominator;
+
+ if ( newColWidth < effectiveColumnLimits[i].first )
+ { // that was too much, we hit the col's minimum
+ // set the new width to exactly this minimum
+ newColWidth = effectiveColumnLimits[i].first;
+ // adjust the flexibility denominator ...
+ flexibilityDenominator -= columnFlexibility;
+ columnFlexibilities[i] = 0;
+ --flexibleColumnCount;
+ // ... and the remaining width ...
+ tools::Long const difference = currentColWidths[i] - newColWidth;
+ takeAwayPixel -= difference;
+
+ // and start over with the first column, since there might be earlier columns which need
+ // to be recalculated now
+ startOver = true;
+ }
+
+ o_newColWidthsPixel[i] = newColWidth;
+ }
+ }
+ while ( startOver );
+
+ // are there pixels left (might be caused by rounding errors)?
+ takeAwayPixel = ::std::accumulate( o_newColWidthsPixel.begin(), o_newColWidthsPixel.end(), 0 ) - gridWidthPixel;
+ while ( ( takeAwayPixel > 0 ) && ( flexibleColumnCount > 0 ) )
+ {
+ // yes => ignore relative flexibilities, and subsequently take away pixels from all flexible
+ // columns which did not yet reach their minimum.
+ for ( size_t i=0; ( i < o_newColWidthsPixel.size() ) && ( takeAwayPixel > 0 ); ++i )
+ {
+ if ( columnFlexibilities[i] == 0 )
+ continue;
+
+ OSL_ENSURE( o_newColWidthsPixel[i] >= effectiveColumnLimits[i].first,
+ "TableControl_Impl::impl_ni_calculateColumnWidths: inconsistency!" );
+ if ( o_newColWidthsPixel[i] <= effectiveColumnLimits[i].first )
+ {
+ columnFlexibilities[i] = 0;
+ --flexibleColumnCount;
+ continue;
+ }
+
+ --o_newColWidthsPixel[i];
+ --takeAwayPixel;
+ }
+ }
+ }
+ }
+
+ return gridWidthPixel;
+ }
+
+
+ void TableControl_Impl::impl_ni_relayout( ColPos const i_assumeInflexibleColumnsUpToIncluding )
+ {
+ ENSURE_OR_RETURN_VOID( !m_bUpdatingColWidths, "TableControl_Impl::impl_ni_relayout: recursive call detected!" );
+
+ m_aColumnWidths.resize( 0 );
+ if ( !m_pModel )
+ return;
+
+ ::comphelper::FlagRestorationGuard const aWidthUpdateFlag( m_bUpdatingColWidths, true );
+ SuppressCursor aHideCursor( *this );
+
+ // layouting steps:
+
+ // 1. adjust column widths, leaving space for a vertical scrollbar
+ // 2. determine need for a vertical scrollbar
+ // - V-YES: all fine, result from 1. is still valid
+ // - V-NO: result from 1. is still under consideration
+
+ // 3. determine need for a horizontal scrollbar
+ // - H-NO: all fine, result from 2. is still valid
+ // - H-YES: reconsider need for a vertical scrollbar, if result of 2. was V-NO
+ // - V-YES: all fine, result from 1. is still valid
+ // - V-NO: redistribute the remaining space (if any) amongst all columns which allow it
+
+ ::std::vector< tools::Long > newWidthsPixel;
+ tools::Long gridWidthPixel = impl_ni_calculateColumnWidths( i_assumeInflexibleColumnsUpToIncluding, true, newWidthsPixel );
+
+ // the width/height of a scrollbar, needed several times below
+ tools::Long const nScrollbarMetrics = m_rAntiImpl.GetSettings().GetStyleSettings().GetScrollBarSize();
+
+ // determine the playground for the data cells (excluding headers)
+ // TODO: what if the control is smaller than needed for the headers/scrollbars?
+ tools::Rectangle aDataCellPlayground( Point( 0, 0 ), m_rAntiImpl.GetOutputSizePixel() );
+ aDataCellPlayground.SetLeft( m_nRowHeaderWidthPixel );
+ aDataCellPlayground.SetTop( m_nColHeaderHeightPixel );
+
+ OSL_ENSURE( ( m_nRowCount == m_pModel->getRowCount() ) && ( m_nColumnCount == m_pModel->getColumnCount() ),
+ "TableControl_Impl::impl_ni_relayout: how is this expected to work with invalid data?" );
+ tools::Long const nAllColumnsWidth = ::std::accumulate( newWidthsPixel.begin(), newWidthsPixel.end(), 0 );
+
+ ScrollbarVisibility const eVertScrollbar = m_pModel->getVerticalScrollbarVisibility();
+ ScrollbarVisibility const eHorzScrollbar = m_pModel->getHorizontalScrollbarVisibility();
+
+ // do we need a vertical scrollbar?
+ bool bNeedVerticalScrollbar = lcl_determineScrollbarNeed(
+ m_nTopRow, eVertScrollbar, aDataCellPlayground.GetHeight(), m_nRowHeightPixel * m_nRowCount );
+ bool bFirstRoundVScrollNeed = false;
+ if ( bNeedVerticalScrollbar )
+ {
+ aDataCellPlayground.AdjustRight( -nScrollbarMetrics );
+ bFirstRoundVScrollNeed = true;
+ }
+
+ // do we need a horizontal scrollbar?
+ bool const bNeedHorizontalScrollbar = lcl_determineScrollbarNeed(
+ m_nLeftColumn, eHorzScrollbar, aDataCellPlayground.GetWidth(), nAllColumnsWidth );
+ if ( bNeedHorizontalScrollbar )
+ {
+ aDataCellPlayground.AdjustBottom( -nScrollbarMetrics );
+
+ // now that we just found that we need a horizontal scrollbar,
+ // the need for a vertical one may have changed, since the horizontal
+ // SB might just occupy enough space so that not all rows do fit
+ // anymore
+ if ( !bFirstRoundVScrollNeed )
+ {
+ bNeedVerticalScrollbar = lcl_determineScrollbarNeed(
+ m_nTopRow, eVertScrollbar, aDataCellPlayground.GetHeight(), m_nRowHeightPixel * m_nRowCount );
+ if ( bNeedVerticalScrollbar )
+ {
+ aDataCellPlayground.AdjustRight( -nScrollbarMetrics );
+ }
+ }
+ }
+
+ // the initial call to impl_ni_calculateColumnWidths assumed that we need a vertical scrollbar. If, by now,
+ // we know that this is not the case, re-calculate the column widths.
+ if ( !bNeedVerticalScrollbar )
+ gridWidthPixel = impl_ni_calculateColumnWidths( i_assumeInflexibleColumnsUpToIncluding, false, newWidthsPixel );
+
+ // update the column objects with the new widths we finally calculated
+ TableSize const colCount = m_pModel->getColumnCount();
+ m_aColumnWidths.reserve( colCount );
+ tools::Long accumulatedWidthPixel = m_nRowHeaderWidthPixel;
+ bool anyColumnWidthChanged = false;
+ for ( ColPos col = 0; col < colCount; ++col )
+ {
+ const tools::Long columnStart = accumulatedWidthPixel;
+ const tools::Long columnEnd = columnStart + newWidthsPixel[col];
+ m_aColumnWidths.emplace_back( columnStart, columnEnd );
+ accumulatedWidthPixel = columnEnd;
+
+ // and don't forget to forward this to the column models
+ PColumnModel const pColumn = m_pModel->getColumnModel( col );
+ ENSURE_OR_THROW( !!pColumn, "invalid column returned by the model!" );
+
+ tools::Long const oldColumnWidthAppFont = pColumn->getWidth();
+ tools::Long const newColumnWidthAppFont = pixelWidthToAppFont( newWidthsPixel[col] );
+ pColumn->setWidth( newColumnWidthAppFont );
+
+ anyColumnWidthChanged |= ( oldColumnWidthAppFont != newColumnWidthAppFont );
+ }
+
+ // if the column widths changed, ensure everything is repainted
+ if ( anyColumnWidthChanged )
+ invalidate( TableArea::All );
+
+ // if the column resizing happened to leave some space at the right, but there are columns
+ // scrolled out to the left, scroll them in
+ while ( ( m_nLeftColumn > 0 )
+ && ( accumulatedWidthPixel - m_aColumnWidths[ m_nLeftColumn - 1 ].getStart() <= gridWidthPixel )
+ )
+ {
+ --m_nLeftColumn;
+ }
+
+ // now adjust the column metrics, since they currently ignore the horizontal scroll position
+ if ( m_nLeftColumn > 0 )
+ {
+ const tools::Long offsetPixel = m_aColumnWidths[ 0 ].getStart() - m_aColumnWidths[ m_nLeftColumn ].getStart();
+ for (auto & columnWidth : m_aColumnWidths)
+ {
+ columnWidth.move( offsetPixel );
+ }
+ }
+
+ // show or hide the scrollbars as needed, and position the data window
+ impl_ni_positionChildWindows( aDataCellPlayground, bNeedVerticalScrollbar, bNeedHorizontalScrollbar );
+ }
+
+
+ void TableControl_Impl::impl_ni_positionChildWindows( tools::Rectangle const & i_dataCellPlayground,
+ bool const i_verticalScrollbar, bool const i_horizontalScrollbar )
+ {
+ tools::Long const nScrollbarMetrics = m_rAntiImpl.GetSettings().GetStyleSettings().GetScrollBarSize();
+
+ // create or destroy the vertical scrollbar, as needed
+ lcl_updateScrollbar(
+ m_rAntiImpl,
+ m_pVScroll,
+ i_verticalScrollbar,
+ lcl_getRowsFittingInto( i_dataCellPlayground.GetHeight(), m_nRowHeightPixel, false ),
+ // visible units
+ m_nTopRow, // current position
+ m_nRowCount, // range
+ false, // vertical
+ LINK( this, TableControl_Impl, OnScroll ) // scroll handler
+ );
+
+ // position it
+ if ( m_pVScroll )
+ {
+ tools::Rectangle aScrollbarArea(
+ Point( i_dataCellPlayground.Right() + 1, 0 ),
+ Size( nScrollbarMetrics, i_dataCellPlayground.Bottom() + 1 )
+ );
+ m_pVScroll->SetPosSizePixel(
+ aScrollbarArea.TopLeft(), aScrollbarArea.GetSize() );
+ }
+
+ // create or destroy the horizontal scrollbar, as needed
+ lcl_updateScrollbar(
+ m_rAntiImpl,
+ m_pHScroll,
+ i_horizontalScrollbar,
+ lcl_getColumnsVisibleWithin( i_dataCellPlayground, m_nLeftColumn, *this, false ),
+ // visible units
+ m_nLeftColumn, // current position
+ m_nColumnCount, // range
+ true, // horizontal
+ LINK( this, TableControl_Impl, OnScroll ) // scroll handler
+ );
+
+ // position it
+ if ( m_pHScroll )
+ {
+ TableSize const nVisibleUnits = lcl_getColumnsVisibleWithin( i_dataCellPlayground, m_nLeftColumn, *this, false );
+ TableMetrics const nRange = m_nColumnCount;
+ if( m_nLeftColumn + nVisibleUnits == nRange - 1 )
+ {
+ if ( m_aColumnWidths[ nRange - 1 ].getStart() - m_aColumnWidths[ m_nLeftColumn ].getEnd() + m_aColumnWidths[ nRange-1 ].getWidth() > i_dataCellPlayground.GetWidth() )
+ {
+ m_pHScroll->SetVisibleSize( nVisibleUnits -1 );
+ m_pHScroll->SetPageSize( nVisibleUnits - 1 );
+ }
+ }
+ tools::Rectangle aScrollbarArea(
+ Point( 0, i_dataCellPlayground.Bottom() + 1 ),
+ Size( i_dataCellPlayground.Right() + 1, nScrollbarMetrics )
+ );
+ m_pHScroll->SetPosSizePixel(
+ aScrollbarArea.TopLeft(), aScrollbarArea.GetSize() );
+ }
+
+ // the corner window connecting the two scrollbars in the lower right corner
+ bool bHaveScrollCorner = nullptr != m_pScrollCorner;
+ bool bNeedScrollCorner = ( nullptr != m_pHScroll ) && ( nullptr != m_pVScroll );
+ if ( bHaveScrollCorner && !bNeedScrollCorner )
+ {
+ m_pScrollCorner.disposeAndClear();
+ }
+ else if ( !bHaveScrollCorner && bNeedScrollCorner )
+ {
+ m_pScrollCorner = VclPtr<ScrollBarBox>::Create( &m_rAntiImpl );
+ m_pScrollCorner->SetSizePixel( Size( nScrollbarMetrics, nScrollbarMetrics ) );
+ m_pScrollCorner->SetPosPixel( Point( i_dataCellPlayground.Right() + 1, i_dataCellPlayground.Bottom() + 1 ) );
+ m_pScrollCorner->Show();
+ }
+ else if(bHaveScrollCorner && bNeedScrollCorner)
+ {
+ m_pScrollCorner->SetPosPixel( Point( i_dataCellPlayground.Right() + 1, i_dataCellPlayground.Bottom() + 1 ) );
+ m_pScrollCorner->Show();
+ }
+
+ // resize the data window
+ m_pDataWindow->SetSizePixel( Size(
+ i_dataCellPlayground.GetWidth() + m_nRowHeaderWidthPixel,
+ i_dataCellPlayground.GetHeight() + m_nColHeaderHeightPixel
+ ) );
+ }
+
+
+ void TableControl_Impl::onResize()
+ {
+ impl_ni_relayout();
+ checkCursorPosition();
+ }
+
+
+ void TableControl_Impl::doPaintContent(vcl::RenderContext& rRenderContext, const tools::Rectangle& _rUpdateRect)
+ {
+ if (!getModel())
+ return;
+ PTableRenderer pRenderer = getModel()->getRenderer();
+ DBG_ASSERT(!!pRenderer, "TableDataWindow::doPaintContent: invalid renderer!");
+ if (!pRenderer)
+ return;
+
+ // our current style settings, to be passed to the renderer
+ const StyleSettings& rStyle = rRenderContext.GetSettings().GetStyleSettings();
+ m_nRowCount = m_pModel->getRowCount();
+ // the area occupied by all (at least partially) visible cells, including
+ // headers
+ tools::Rectangle const aAllCellsWithHeaders( impl_getAllVisibleCellsArea() );
+
+ // draw the header column area
+ if (m_pModel->hasColumnHeaders())
+ {
+ TableRowGeometry const aHeaderRow(*this, tools::Rectangle(Point(0, 0), aAllCellsWithHeaders.BottomRight()), ROW_COL_HEADERS);
+ tools::Rectangle const aColRect(aHeaderRow.getRect());
+ pRenderer->PaintHeaderArea(rRenderContext, aColRect, true, false, rStyle);
+ // Note that strictly, aHeaderRow.getRect() also contains the intersection between column
+ // and row header area. However, below we go to paint this intersection, again,
+ // so this hopefully doesn't hurt if we already paint it here.
+
+ for (TableCellGeometry aCell(aHeaderRow, m_nLeftColumn); aCell.isValid(); aCell.moveRight())
+ {
+ if (_rUpdateRect.GetIntersection(aCell.getRect()).IsEmpty())
+ continue;
+
+ pRenderer->PaintColumnHeader(aCell.getColumn(), rRenderContext, aCell.getRect(), rStyle);
+ }
+ }
+ // the area occupied by the row header, if any
+ tools::Rectangle aRowHeaderArea;
+ if (m_pModel->hasRowHeaders())
+ {
+ aRowHeaderArea = aAllCellsWithHeaders;
+ aRowHeaderArea.SetRight( m_nRowHeaderWidthPixel - 1 );
+
+ TableSize const nVisibleRows = impl_getVisibleRows(true);
+ TableSize nActualRows = nVisibleRows;
+ if (m_nTopRow + nActualRows > m_nRowCount)
+ nActualRows = m_nRowCount - m_nTopRow;
+ aRowHeaderArea.SetBottom( m_nColHeaderHeightPixel + m_nRowHeightPixel * nActualRows - 1 );
+
+ pRenderer->PaintHeaderArea(rRenderContext, aRowHeaderArea, false, true, rStyle);
+ // Note that strictly, aRowHeaderArea also contains the intersection between column
+ // and row header area. However, below we go to paint this intersection, again,
+ // so this hopefully doesn't hurt if we already paint it here.
+
+ if (m_pModel->hasColumnHeaders())
+ {
+ TableCellGeometry const aIntersection(*this, tools::Rectangle(Point(0, 0), aAllCellsWithHeaders.BottomRight()),
+ COL_ROW_HEADERS, ROW_COL_HEADERS);
+ tools::Rectangle const aInters(aIntersection.getRect());
+ pRenderer->PaintHeaderArea(rRenderContext, aInters, true, true, rStyle);
+ }
+ }
+
+ // draw the table content row by row
+ TableSize colCount = getModel()->getColumnCount();
+
+ // paint all rows
+ tools::Rectangle const aAllDataCellsArea(impl_getAllVisibleDataCellArea());
+ for (TableRowGeometry aRowIterator(*this, aAllCellsWithHeaders, getTopRow()); aRowIterator.isValid(); aRowIterator.moveDown())
+ {
+ if (_rUpdateRect.GetIntersection(aRowIterator.getRect() ).IsEmpty())
+ continue;
+
+ bool const isControlFocused = m_rAntiImpl.HasControlFocus();
+ bool const isSelectedRow = isRowSelected(aRowIterator.getRow());
+
+ tools::Rectangle const aRect = aRowIterator.getRect().GetIntersection(aAllDataCellsArea);
+
+ // give the renderer a chance to prepare the row
+ pRenderer->PrepareRow(aRowIterator.getRow(), isControlFocused, isSelectedRow, rRenderContext, aRect, rStyle);
+
+ // paint the row header
+ if (m_pModel->hasRowHeaders())
+ {
+ const tools::Rectangle aCurrentRowHeader(aRowHeaderArea.GetIntersection(aRowIterator.getRect()));
+ pRenderer->PaintRowHeader(rRenderContext, aCurrentRowHeader, rStyle);
+ }
+
+ if (!colCount)
+ continue;
+
+ // paint all cells in this row
+ for (TableCellGeometry aCell(aRowIterator, m_nLeftColumn); aCell.isValid(); aCell.moveRight())
+ {
+ pRenderer->PaintCell(aCell.getColumn(), isSelectedRow, isControlFocused,
+ rRenderContext, aCell.getRect(), rStyle);
+ }
+ }
+ }
+
+ void TableControl_Impl::hideCursor()
+ {
+ if ( ++m_nCursorHidden == 1 )
+ impl_ni_doSwitchCursor( false );
+ }
+
+
+ void TableControl_Impl::showCursor()
+ {
+ DBG_ASSERT( m_nCursorHidden > 0, "TableControl_Impl::showCursor: cursor not hidden!" );
+ if ( --m_nCursorHidden == 0 )
+ impl_ni_doSwitchCursor( true );
+ }
+
+
+ bool TableControl_Impl::dispatchAction( TableControlAction _eAction )
+ {
+ bool bSuccess = false;
+ bool selectionChanged = false;
+
+ switch ( _eAction )
+ {
+ case cursorDown:
+ if ( m_pSelEngine->GetSelectionMode() == SelectionMode::Single )
+ {
+ //if other rows already selected, deselect them
+ if(!m_aSelectedRows.empty())
+ {
+ invalidateSelectedRows();
+ m_aSelectedRows.clear();
+ }
+ if ( m_nCurRow < m_nRowCount-1 )
+ {
+ ++m_nCurRow;
+ m_aSelectedRows.push_back(m_nCurRow);
+ }
+ else
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateRow( m_nCurRow );
+ ensureVisible(m_nCurColumn,m_nCurRow);
+ selectionChanged = true;
+ bSuccess = true;
+ }
+ else
+ {
+ if ( m_nCurRow < m_nRowCount - 1 )
+ bSuccess = goTo( m_nCurColumn, m_nCurRow + 1 );
+ }
+ break;
+
+ case cursorUp:
+ if(m_pSelEngine->GetSelectionMode() == SelectionMode::Single)
+ {
+ if(!m_aSelectedRows.empty())
+ {
+ invalidateSelectedRows();
+ m_aSelectedRows.clear();
+ }
+ if(m_nCurRow>0)
+ {
+ --m_nCurRow;
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateRow( m_nCurRow );
+ }
+ else
+ {
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateRow( m_nCurRow );
+ }
+ ensureVisible(m_nCurColumn,m_nCurRow);
+ selectionChanged = true;
+ bSuccess = true;
+ }
+ else
+ {
+ if ( m_nCurRow > 0 )
+ bSuccess = goTo( m_nCurColumn, m_nCurRow - 1 );
+ }
+ break;
+ case cursorLeft:
+ if ( m_nCurColumn > 0 )
+ bSuccess = goTo( m_nCurColumn - 1, m_nCurRow );
+ else
+ if ( ( m_nCurColumn == 0) && ( m_nCurRow > 0 ) )
+ bSuccess = goTo( m_nColumnCount - 1, m_nCurRow - 1 );
+ break;
+
+ case cursorRight:
+ if ( m_nCurColumn < m_nColumnCount - 1 )
+ bSuccess = goTo( m_nCurColumn + 1, m_nCurRow );
+ else
+ if ( ( m_nCurColumn == m_nColumnCount - 1 ) && ( m_nCurRow < m_nRowCount - 1 ) )
+ bSuccess = goTo( 0, m_nCurRow + 1 );
+ break;
+
+ case cursorToLineStart:
+ bSuccess = goTo( 0, m_nCurRow );
+ break;
+
+ case cursorToLineEnd:
+ bSuccess = goTo( m_nColumnCount - 1, m_nCurRow );
+ break;
+
+ case cursorToFirstLine:
+ bSuccess = goTo( m_nCurColumn, 0 );
+ break;
+
+ case cursorToLastLine:
+ bSuccess = goTo( m_nCurColumn, m_nRowCount - 1 );
+ break;
+
+ case cursorPageUp:
+ {
+ RowPos nNewRow = ::std::max( RowPos(0), m_nCurRow - impl_getVisibleRows( false ) );
+ bSuccess = goTo( m_nCurColumn, nNewRow );
+ }
+ break;
+
+ case cursorPageDown:
+ {
+ RowPos nNewRow = ::std::min( m_nRowCount - 1, m_nCurRow + impl_getVisibleRows( false ) );
+ bSuccess = goTo( m_nCurColumn, nNewRow );
+ }
+ break;
+
+ case cursorTopLeft:
+ bSuccess = goTo( 0, 0 );
+ break;
+
+ case cursorBottomRight:
+ bSuccess = goTo( m_nColumnCount - 1, m_nRowCount - 1 );
+ break;
+
+ case cursorSelectRow:
+ {
+ if(m_pSelEngine->GetSelectionMode() == SelectionMode::NONE)
+ return false;
+ //pos is the position of the current row in the vector of selected rows, if current row is selected
+ int pos = getRowSelectedNumber(m_aSelectedRows, m_nCurRow);
+ //if current row is selected, it should be deselected, when ALT+SPACE are pressed
+ if(pos>-1)
+ {
+ m_aSelectedRows.erase(m_aSelectedRows.begin()+pos);
+ if(m_aSelectedRows.empty() && m_nAnchor != -1)
+ m_nAnchor = -1;
+ }
+ //else select the row->put it in the vector
+ else
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateRow( m_nCurRow );
+ selectionChanged = true;
+ bSuccess = true;
+ }
+ break;
+ case cursorSelectRowUp:
+ {
+ if(m_pSelEngine->GetSelectionMode() == SelectionMode::NONE)
+ return false;
+ else if(m_pSelEngine->GetSelectionMode() == SelectionMode::Single)
+ {
+ //if there are other selected rows, deselect them
+ return false;
+ }
+ else
+ {
+ //there are other selected rows
+ if(!m_aSelectedRows.empty())
+ {
+ //the anchor wasn't set -> a region is not selected, that's why clear all selection
+ //and select the current row
+ if(m_nAnchor==-1)
+ {
+ invalidateSelectedRows();
+ m_aSelectedRows.clear();
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateRow( m_nCurRow );
+ }
+ else
+ {
+ //a region is already selected, prevRow is last selected row and the row above - nextRow - should be selected
+ int prevRow = getRowSelectedNumber(m_aSelectedRows, m_nCurRow);
+ int nextRow = getRowSelectedNumber(m_aSelectedRows, m_nCurRow-1);
+ if(prevRow>-1)
+ {
+ //if m_nCurRow isn't the upper one, can move up, otherwise not
+ if(m_nCurRow>0)
+ m_nCurRow--;
+ else
+ return true;
+ //if nextRow already selected, deselect it, otherwise select it
+ if(nextRow>-1 && m_aSelectedRows[nextRow] == m_nCurRow)
+ {
+ m_aSelectedRows.erase(m_aSelectedRows.begin()+prevRow);
+ invalidateRow( m_nCurRow + 1 );
+ }
+ else
+ {
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateRow( m_nCurRow );
+ }
+ }
+ else
+ {
+ if(m_nCurRow>0)
+ {
+ m_aSelectedRows.push_back(m_nCurRow);
+ m_nCurRow--;
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateSelectedRegion( m_nCurRow+1, m_nCurRow );
+ }
+ }
+ }
+ }
+ else
+ {
+ //if nothing is selected and the current row isn't the upper one
+ //select the current and one row above
+ //otherwise select only the upper row
+ if(m_nCurRow>0)
+ {
+ m_aSelectedRows.push_back(m_nCurRow);
+ m_nCurRow--;
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateSelectedRegion( m_nCurRow+1, m_nCurRow );
+ }
+ else
+ {
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateRow( m_nCurRow );
+ }
+ }
+ m_pSelEngine->SetAnchor(true);
+ m_nAnchor = m_nCurRow;
+ ensureVisible(m_nCurColumn, m_nCurRow);
+ selectionChanged = true;
+ bSuccess = true;
+ }
+ }
+ break;
+ case cursorSelectRowDown:
+ {
+ if(m_pSelEngine->GetSelectionMode() == SelectionMode::NONE)
+ bSuccess = false;
+ else if(m_pSelEngine->GetSelectionMode() == SelectionMode::Single)
+ {
+ bSuccess = false;
+ }
+ else
+ {
+ if(!m_aSelectedRows.empty())
+ {
+ //the anchor wasn't set -> a region is not selected, that's why clear all selection
+ //and select the current row
+ if(m_nAnchor==-1)
+ {
+ invalidateSelectedRows();
+ m_aSelectedRows.clear();
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateRow( m_nCurRow );
+ }
+ else
+ {
+ //a region is already selected, prevRow is last selected row and the row beneath - nextRow - should be selected
+ int prevRow = getRowSelectedNumber(m_aSelectedRows, m_nCurRow);
+ int nextRow = getRowSelectedNumber(m_aSelectedRows, m_nCurRow+1);
+ if(prevRow>-1)
+ {
+ //if m_nCurRow isn't the last one, can move down, otherwise not
+ if(m_nCurRow<m_nRowCount-1)
+ m_nCurRow++;
+ else
+ return true;
+ //if next row already selected, deselect it, otherwise select it
+ if(nextRow>-1 && m_aSelectedRows[nextRow] == m_nCurRow)
+ {
+ m_aSelectedRows.erase(m_aSelectedRows.begin()+prevRow);
+ invalidateRow( m_nCurRow - 1 );
+ }
+ else
+ {
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateRow( m_nCurRow );
+ }
+ }
+ else
+ {
+ if(m_nCurRow<m_nRowCount-1)
+ {
+ m_aSelectedRows.push_back(m_nCurRow);
+ m_nCurRow++;
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateSelectedRegion( m_nCurRow-1, m_nCurRow );
+ }
+ }
+ }
+ }
+ else
+ {
+ //there wasn't any selection, select current and row beneath, otherwise only row beneath
+ if(m_nCurRow<m_nRowCount-1)
+ {
+ m_aSelectedRows.push_back(m_nCurRow);
+ m_nCurRow++;
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateSelectedRegion( m_nCurRow-1, m_nCurRow );
+ }
+ else
+ {
+ m_aSelectedRows.push_back(m_nCurRow);
+ invalidateRow( m_nCurRow );
+ }
+ }
+ m_pSelEngine->SetAnchor(true);
+ m_nAnchor = m_nCurRow;
+ ensureVisible(m_nCurColumn, m_nCurRow);
+ selectionChanged = true;
+ bSuccess = true;
+ }
+ }
+ break;
+
+ case cursorSelectRowAreaTop:
+ {
+ if(m_pSelEngine->GetSelectionMode() == SelectionMode::NONE)
+ bSuccess = false;
+ else if(m_pSelEngine->GetSelectionMode() == SelectionMode::Single)
+ bSuccess = false;
+ else
+ {
+ //select the region between the current and the upper row
+ RowPos iter = m_nCurRow;
+ invalidateSelectedRegion( m_nCurRow, 0 );
+ //put the rows in vector
+ while(iter>=0)
+ {
+ if ( !isRowSelected( iter ) )
+ m_aSelectedRows.push_back(iter);
+ --iter;
+ }
+ m_nCurRow = 0;
+ m_nAnchor = m_nCurRow;
+ m_pSelEngine->SetAnchor(true);
+ ensureVisible(m_nCurColumn, 0);
+ selectionChanged = true;
+ bSuccess = true;
+ }
+ }
+ break;
+
+ case cursorSelectRowAreaBottom:
+ {
+ if(m_pSelEngine->GetSelectionMode() == SelectionMode::NONE)
+ return false;
+ else if(m_pSelEngine->GetSelectionMode() == SelectionMode::Single)
+ return false;
+ //select the region between the current and the last row
+ RowPos iter = m_nCurRow;
+ invalidateSelectedRegion( m_nCurRow, m_nRowCount-1 );
+ //put the rows in the vector
+ while(iter<=m_nRowCount)
+ {
+ if ( !isRowSelected( iter ) )
+ m_aSelectedRows.push_back(iter);
+ ++iter;
+ }
+ m_nCurRow = m_nRowCount-1;
+ m_nAnchor = m_nCurRow;
+ m_pSelEngine->SetAnchor(true);
+ ensureVisible(m_nCurColumn, m_nRowCount-1);
+ selectionChanged = true;
+ bSuccess = true;
+ }
+ break;
+ default:
+ OSL_FAIL( "TableControl_Impl::dispatchAction: unsupported action!" );
+ break;
+ }
+
+ if ( bSuccess && selectionChanged )
+ {
+ m_rAntiImpl.Select();
+ }
+
+ return bSuccess;
+ }
+
+
+ void TableControl_Impl::impl_ni_doSwitchCursor( bool _bShow )
+ {
+ PTableRenderer pRenderer = m_pModel ? m_pModel->getRenderer() : PTableRenderer();
+ if ( pRenderer )
+ {
+ tools::Rectangle aCellRect;
+ impl_getCellRect( m_nCurColumn, m_nCurRow, aCellRect );
+ if ( _bShow )
+ pRenderer->ShowCellCursor( *m_pDataWindow, aCellRect );
+ else
+ pRenderer->HideCellCursor( *m_pDataWindow );
+ }
+ }
+
+
+ void TableControl_Impl::impl_getCellRect( ColPos _nColumn, RowPos _nRow, tools::Rectangle& _rCellRect ) const
+ {
+ if ( !m_pModel
+ || ( COL_INVALID == _nColumn )
+ || ( ROW_INVALID == _nRow )
+ )
+ {
+ _rCellRect.SetEmpty();
+ return;
+ }
+
+ TableCellGeometry aCell( *this, impl_getAllVisibleCellsArea(), _nColumn, _nRow );
+ _rCellRect = aCell.getRect();
+ }
+
+
+ RowPos TableControl_Impl::getRowAtPoint( const Point& rPoint ) const
+ {
+ return impl_getRowForAbscissa( rPoint.Y() );
+ }
+
+
+ ColPos TableControl_Impl::getColAtPoint( const Point& rPoint ) const
+ {
+ return impl_getColumnForOrdinate( rPoint.X() );
+ }
+
+
+ TableCell TableControl_Impl::hitTest( Point const & i_point ) const
+ {
+ TableCell aCell( getColAtPoint( i_point ), getRowAtPoint( i_point ) );
+ if ( aCell.nColumn > COL_ROW_HEADERS )
+ {
+ PColumnModel const pColumn = m_pModel->getColumnModel( aCell.nColumn );
+ MutableColumnMetrics const & rColInfo( m_aColumnWidths[ aCell.nColumn ] );
+ if ( ( rColInfo.getEnd() - 3 <= i_point.X() )
+ && ( rColInfo.getEnd() >= i_point.X() )
+ && pColumn->isResizable()
+ )
+ {
+ aCell.eArea = ColumnDivider;
+ }
+ }
+ return aCell;
+ }
+
+
+ ColumnMetrics TableControl_Impl::getColumnMetrics( ColPos const i_column ) const
+ {
+ ENSURE_OR_RETURN( ( i_column >= 0 ) && ( i_column < m_pModel->getColumnCount() ),
+ "TableControl_Impl::getColumnMetrics: illegal column index!", ColumnMetrics() );
+ return m_aColumnWidths[ i_column ];
+ }
+
+
+ PTableModel TableControl_Impl::getModel() const
+ {
+ return m_pModel;
+ }
+
+
+ ColPos TableControl_Impl::getCurrentColumn() const
+ {
+ return m_nCurColumn;
+ }
+
+
+ RowPos TableControl_Impl::getCurrentRow() const
+ {
+ return m_nCurRow;
+ }
+
+
+ ::Size TableControl_Impl::getTableSizePixel() const
+ {
+ return m_pDataWindow->GetOutputSizePixel();
+ }
+
+
+ void TableControl_Impl::setPointer( PointerStyle i_pointer )
+ {
+ m_pDataWindow->SetPointer( i_pointer );
+ }
+
+
+ void TableControl_Impl::captureMouse()
+ {
+ m_pDataWindow->CaptureMouse();
+ }
+
+
+ void TableControl_Impl::releaseMouse()
+ {
+ m_pDataWindow->ReleaseMouse();
+ }
+
+
+ void TableControl_Impl::invalidate( TableArea const i_what )
+ {
+ switch ( i_what )
+ {
+ case TableArea::ColumnHeaders:
+ m_pDataWindow->Invalidate( calcHeaderRect( true ) );
+ break;
+
+ case TableArea::RowHeaders:
+ m_pDataWindow->Invalidate( calcHeaderRect( false ) );
+ break;
+
+ case TableArea::All:
+ m_pDataWindow->Invalidate();
+ m_pDataWindow->GetParent()->Invalidate( InvalidateFlags::Transparent );
+ break;
+ }
+ }
+
+
+ tools::Long TableControl_Impl::pixelWidthToAppFont( tools::Long const i_pixels ) const
+ {
+ return m_pDataWindow->PixelToLogic(Size(i_pixels, 0), MapMode(MapUnit::MapAppFont)).Width();
+ }
+
+
+ tools::Long TableControl_Impl::appFontWidthToPixel( tools::Long const i_appFontUnits ) const
+ {
+ return m_pDataWindow->LogicToPixel(Size(i_appFontUnits, 0), MapMode(MapUnit::MapAppFont)).Width();
+ }
+
+
+ void TableControl_Impl::hideTracking()
+ {
+ m_pDataWindow->HideTracking();
+ }
+
+
+ void TableControl_Impl::showTracking( tools::Rectangle const & i_location, ShowTrackFlags const i_flags )
+ {
+ m_pDataWindow->ShowTracking( i_location, i_flags );
+ }
+
+
+ void TableControl_Impl::activateCell( ColPos const i_col, RowPos const i_row )
+ {
+ goTo( i_col, i_row );
+ }
+
+
+ void TableControl_Impl::invalidateSelectedRegion( RowPos _nPrevRow, RowPos _nCurRow )
+ {
+ // get the visible area of the table control and set the Left and right border of the region to be repainted
+ tools::Rectangle const aAllCells( impl_getAllVisibleCellsArea() );
+
+ tools::Rectangle aInvalidateRect;
+ aInvalidateRect.SetLeft( aAllCells.Left() );
+ aInvalidateRect.SetRight( aAllCells.Right() );
+ // if only one row is selected
+ if ( _nPrevRow == _nCurRow )
+ {
+ tools::Rectangle aCellRect;
+ impl_getCellRect( m_nCurColumn, _nCurRow, aCellRect );
+ aInvalidateRect.SetTop( aCellRect.Top() );
+ aInvalidateRect.SetBottom( aCellRect.Bottom() );
+ }
+ //if the region is above the current row
+ else if(_nPrevRow < _nCurRow )
+ {
+ tools::Rectangle aCellRect;
+ impl_getCellRect( m_nCurColumn, _nPrevRow, aCellRect );
+ aInvalidateRect.SetTop( aCellRect.Top() );
+ impl_getCellRect( m_nCurColumn, _nCurRow, aCellRect );
+ aInvalidateRect.SetBottom( aCellRect.Bottom() );
+ }
+ //if the region is beneath the current row
+ else
+ {
+ tools::Rectangle aCellRect;
+ impl_getCellRect( m_nCurColumn, _nCurRow, aCellRect );
+ aInvalidateRect.SetTop( aCellRect.Top() );
+ impl_getCellRect( m_nCurColumn, _nPrevRow, aCellRect );
+ aInvalidateRect.SetBottom( aCellRect.Bottom() );
+ }
+
+ invalidateRect(aInvalidateRect);
+ }
+
+ void TableControl_Impl::invalidateRect(const tools::Rectangle &rInvalidateRect)
+ {
+ m_pDataWindow->Invalidate( rInvalidateRect,
+ m_pDataWindow->GetControlBackground().IsTransparent() ? InvalidateFlags::Transparent : InvalidateFlags::NONE );
+ }
+
+
+ void TableControl_Impl::invalidateSelectedRows()
+ {
+ for (auto const& selectedRow : m_aSelectedRows)
+ {
+ invalidateRow(selectedRow);
+ }
+ }
+
+
+ void TableControl_Impl::invalidateRowRange( RowPos const i_firstRow, RowPos const i_lastRow )
+ {
+ RowPos const firstRow = i_firstRow < m_nTopRow ? m_nTopRow : i_firstRow;
+ RowPos const lastVisibleRow = m_nTopRow + impl_getVisibleRows( true ) - 1;
+ RowPos const lastRow = ( ( i_lastRow == ROW_INVALID ) || ( i_lastRow > lastVisibleRow ) ) ? lastVisibleRow : i_lastRow;
+
+ tools::Rectangle aInvalidateRect;
+
+ tools::Rectangle const aVisibleCellsArea( impl_getAllVisibleCellsArea() );
+ TableRowGeometry aRow( *this, aVisibleCellsArea, firstRow, true );
+ while ( aRow.isValid() && ( aRow.getRow() <= lastRow ) )
+ {
+ aInvalidateRect.Union( aRow.getRect() );
+ aRow.moveDown();
+ }
+
+ if ( i_lastRow == ROW_INVALID )
+ aInvalidateRect.SetBottom( m_pDataWindow->GetOutputSizePixel().Height() );
+
+ invalidateRect(aInvalidateRect);
+ }
+
+
+ void TableControl_Impl::checkCursorPosition()
+ {
+
+ TableSize nVisibleRows = impl_getVisibleRows(true);
+ TableSize nVisibleCols = impl_getVisibleColumns(true);
+ if ( ( m_nTopRow + nVisibleRows > m_nRowCount )
+ && ( m_nRowCount >= nVisibleRows )
+ )
+ {
+ --m_nTopRow;
+ }
+ else
+ {
+ m_nTopRow = 0;
+ }
+
+ if ( ( m_nLeftColumn + nVisibleCols > m_nColumnCount )
+ && ( m_nColumnCount >= nVisibleCols )
+ )
+ {
+ --m_nLeftColumn;
+ }
+ else
+ {
+ m_nLeftColumn = 0;
+ }
+
+ m_pDataWindow->Invalidate();
+ }
+
+
+ TableSize TableControl_Impl::impl_getVisibleRows( bool _bAcceptPartialRow ) const
+ {
+ DBG_ASSERT( m_pDataWindow, "TableControl_Impl::impl_getVisibleRows: no data window!" );
+
+ return lcl_getRowsFittingInto(
+ m_pDataWindow->GetOutputSizePixel().Height() - m_nColHeaderHeightPixel,
+ m_nRowHeightPixel,
+ _bAcceptPartialRow
+ );
+ }
+
+
+ TableSize TableControl_Impl::impl_getVisibleColumns( bool _bAcceptPartialCol ) const
+ {
+ DBG_ASSERT( m_pDataWindow, "TableControl_Impl::impl_getVisibleColumns: no data window!" );
+
+ return lcl_getColumnsVisibleWithin(
+ tools::Rectangle( Point( 0, 0 ), m_pDataWindow->GetOutputSizePixel() ),
+ m_nLeftColumn,
+ *this,
+ _bAcceptPartialCol
+ );
+ }
+
+
+ bool TableControl_Impl::goTo( ColPos _nColumn, RowPos _nRow )
+ {
+ // TODO: give veto listeners a chance
+
+ if ( ( _nColumn < 0 ) || ( _nColumn >= m_nColumnCount )
+ || ( _nRow < 0 ) || ( _nRow >= m_nRowCount )
+ )
+ {
+ OSL_ENSURE( false, "TableControl_Impl::goTo: invalid row or column index!" );
+ return false;
+ }
+
+ SuppressCursor aHideCursor( *this );
+ m_nCurColumn = _nColumn;
+ m_nCurRow = _nRow;
+
+ // ensure that the new cell is visible
+ ensureVisible( m_nCurColumn, m_nCurRow );
+ return true;
+ }
+
+
+ void TableControl_Impl::ensureVisible( ColPos _nColumn, RowPos _nRow )
+ {
+ DBG_ASSERT( ( _nColumn >= 0 ) && ( _nColumn < m_nColumnCount )
+ && ( _nRow >= 0 ) && ( _nRow < m_nRowCount ),
+ "TableControl_Impl::ensureVisible: invalid coordinates!" );
+
+ SuppressCursor aHideCursor( *this );
+
+ if ( _nColumn < m_nLeftColumn )
+ impl_scrollColumns( _nColumn - m_nLeftColumn );
+ else
+ {
+ TableSize nVisibleColumns = impl_getVisibleColumns( false/*bAcceptPartialVisibility*/ );
+ if ( _nColumn > m_nLeftColumn + nVisibleColumns - 1 )
+ {
+ impl_scrollColumns( _nColumn - ( m_nLeftColumn + nVisibleColumns - 1 ) );
+ // TODO: since not all columns have the same width, this might in theory result
+ // in the column still not being visible.
+ }
+ }
+
+ if ( _nRow < m_nTopRow )
+ impl_scrollRows( _nRow - m_nTopRow );
+ else
+ {
+ TableSize nVisibleRows = impl_getVisibleRows( false/*_bAcceptPartialVisibility*/ );
+ if ( _nRow > m_nTopRow + nVisibleRows - 1 )
+ impl_scrollRows( _nRow - ( m_nTopRow + nVisibleRows - 1 ) );
+ }
+ }
+
+
+ OUString TableControl_Impl::getCellContentAsString( RowPos const i_row, ColPos const i_col )
+ {
+ Any aCellValue;
+ m_pModel->getCellContent( i_col, i_row, aCellValue );
+
+ OUString sCellStringContent;
+ m_pModel->getRenderer()->GetFormattedCellString( aCellValue, sCellStringContent );
+
+ return sCellStringContent;
+ }
+
+
+ TableSize TableControl_Impl::impl_ni_ScrollRows( TableSize _nRowDelta )
+ {
+ // compute new top row
+ RowPos nNewTopRow =
+ ::std::max(
+ ::std::min( static_cast<RowPos>( m_nTopRow + _nRowDelta ), static_cast<RowPos>( m_nRowCount - 1 ) ),
+ RowPos(0)
+ );
+
+ RowPos nOldTopRow = m_nTopRow;
+ m_nTopRow = nNewTopRow;
+
+ // if updates are enabled currently, scroll the viewport
+ if ( m_nTopRow != nOldTopRow )
+ {
+ SuppressCursor aHideCursor( *this );
+ // TODO: call an onStartScroll at our listener (or better an own onStartScroll,
+ // which hides the cursor and then calls the listener)
+ // Same for onEndScroll
+
+ // scroll the view port, if possible
+ tools::Long nPixelDelta = m_nRowHeightPixel * ( m_nTopRow - nOldTopRow );
+
+ tools::Rectangle aDataArea( Point( 0, m_nColHeaderHeightPixel ), m_pDataWindow->GetOutputSizePixel() );
+
+ if ( m_pDataWindow->GetBackground().IsScrollable()
+ && std::abs( nPixelDelta ) < aDataArea.GetHeight()
+ )
+ {
+ m_pDataWindow->Scroll( 0, static_cast<tools::Long>(-nPixelDelta), aDataArea, ScrollFlags::Clip | ScrollFlags::Update | ScrollFlags::Children);
+ }
+ else
+ {
+ m_pDataWindow->Invalidate( InvalidateFlags::Update );
+ m_pDataWindow->GetParent()->Invalidate( InvalidateFlags::Transparent );
+ }
+
+ // update the position at the vertical scrollbar
+ if ( m_pVScroll != nullptr )
+ m_pVScroll->SetThumbPos( m_nTopRow );
+ }
+
+ // The scroll bar availability might change when we scrolled.
+ // For instance, imagine a view with 10 rows, if which 5 fit into the window, numbered 1 to 10.
+ // Now let
+ // - the user scroll to row number 6, so the last 5 rows are visible
+ // - somebody remove the last 4 rows
+ // - the user scroll to row number 5 being the top row, so the last two rows are visible
+ // - somebody remove row number 6
+ // - the user scroll to row number 1
+ // => in this case, the need for the scrollbar vanishes immediately.
+ if ( m_nTopRow == 0 )
+ m_rAntiImpl.PostUserEvent( LINK( this, TableControl_Impl, OnUpdateScrollbars ) );
+
+ return static_cast<TableSize>( m_nTopRow - nOldTopRow );
+ }
+
+
+ TableSize TableControl_Impl::impl_scrollRows( TableSize const i_rowDelta )
+ {
+ return impl_ni_ScrollRows( i_rowDelta );
+ }
+
+
+ TableSize TableControl_Impl::impl_ni_ScrollColumns( TableSize _nColumnDelta )
+ {
+ // compute new left column
+ const ColPos nNewLeftColumn =
+ ::std::max(
+ ::std::min( static_cast<ColPos>( m_nLeftColumn + _nColumnDelta ), static_cast<ColPos>( m_nColumnCount - 1 ) ),
+ ColPos(0)
+ );
+
+ const ColPos nOldLeftColumn = m_nLeftColumn;
+ m_nLeftColumn = nNewLeftColumn;
+
+ // if updates are enabled currently, scroll the viewport
+ if ( m_nLeftColumn != nOldLeftColumn )
+ {
+ SuppressCursor aHideCursor( *this );
+ // TODO: call an onStartScroll at our listener (or better an own onStartScroll,
+ // which hides the cursor and then calls the listener)
+ // Same for onEndScroll
+
+ // scroll the view port, if possible
+ const tools::Rectangle aDataArea( Point( m_nRowHeaderWidthPixel, 0 ), m_pDataWindow->GetOutputSizePixel() );
+
+ tools::Long nPixelDelta =
+ m_aColumnWidths[ nOldLeftColumn ].getStart()
+ - m_aColumnWidths[ m_nLeftColumn ].getStart();
+
+ // update our column positions
+ // Do this *before* scrolling, as ScrollFlags::Update will trigger a paint, which already needs the correct
+ // information in m_aColumnWidths
+ for (auto & columnWidth : m_aColumnWidths)
+ {
+ columnWidth.move(nPixelDelta);
+ }
+
+ // scroll the window content (if supported and possible), or invalidate the complete window
+ if ( m_pDataWindow->GetBackground().IsScrollable()
+ && std::abs( nPixelDelta ) < aDataArea.GetWidth()
+ )
+ {
+ m_pDataWindow->Scroll( nPixelDelta, 0, aDataArea, ScrollFlags::Clip | ScrollFlags::Update );
+ }
+ else
+ {
+ m_pDataWindow->Invalidate( InvalidateFlags::Update );
+ m_pDataWindow->GetParent()->Invalidate( InvalidateFlags::Transparent );
+ }
+
+ // update the position at the horizontal scrollbar
+ if ( m_pHScroll != nullptr )
+ m_pHScroll->SetThumbPos( m_nLeftColumn );
+ }
+
+ // The scroll bar availability might change when we scrolled. This is because we do not hide
+ // the scrollbar when it is, in theory, unnecessary, but currently at a position > 0. In this case, it will
+ // be auto-hidden when it's scrolled back to pos 0.
+ if ( m_nLeftColumn == 0 )
+ m_rAntiImpl.PostUserEvent( LINK( this, TableControl_Impl, OnUpdateScrollbars ) );
+
+ return static_cast<TableSize>( m_nLeftColumn - nOldLeftColumn );
+ }
+
+
+ TableSize TableControl_Impl::impl_scrollColumns( TableSize const i_columnDelta )
+ {
+ return impl_ni_ScrollColumns( i_columnDelta );
+ }
+
+
+ SelectionEngine* TableControl_Impl::getSelEngine()
+ {
+ return m_pSelEngine.get();
+ }
+
+ bool TableControl_Impl::isRowSelected( RowPos i_row ) const
+ {
+ return ::std::find( m_aSelectedRows.begin(), m_aSelectedRows.end(), i_row ) != m_aSelectedRows.end();
+ }
+
+
+ RowPos TableControl_Impl::getSelectedRowIndex( size_t const i_selectionIndex ) const
+ {
+ if ( i_selectionIndex < m_aSelectedRows.size() )
+ return m_aSelectedRows[ i_selectionIndex ];
+ return ROW_INVALID;
+ }
+
+
+ int TableControl_Impl::getRowSelectedNumber(const ::std::vector<RowPos>& selectedRows, RowPos current)
+ {
+ std::vector<RowPos>::const_iterator it = ::std::find(selectedRows.begin(),selectedRows.end(),current);
+ if ( it != selectedRows.end() )
+ {
+ return it - selectedRows.begin();
+ }
+ return -1;
+ }
+
+
+ ColPos TableControl_Impl::impl_getColumnForOrdinate( tools::Long const i_ordinate ) const
+ {
+ if ( ( m_aColumnWidths.empty() ) || ( i_ordinate < 0 ) )
+ return COL_INVALID;
+
+ if ( i_ordinate < m_nRowHeaderWidthPixel )
+ return COL_ROW_HEADERS;
+
+ ColumnPositions::const_iterator lowerBound = ::std::lower_bound(
+ m_aColumnWidths.begin(),
+ m_aColumnWidths.end(),
+ MutableColumnMetrics(i_ordinate+1, i_ordinate+1),
+ ColumnInfoPositionLess()
+ );
+ if ( lowerBound == m_aColumnWidths.end() )
+ {
+ // point is *behind* the start of the last column ...
+ if ( i_ordinate < m_aColumnWidths.rbegin()->getEnd() )
+ // ... but still before its end
+ return m_nColumnCount - 1;
+ return COL_INVALID;
+ }
+ return lowerBound - m_aColumnWidths.begin();
+ }
+
+
+ RowPos TableControl_Impl::impl_getRowForAbscissa( tools::Long const i_abscissa ) const
+ {
+ if ( i_abscissa < 0 )
+ return ROW_INVALID;
+
+ if ( i_abscissa < m_nColHeaderHeightPixel )
+ return ROW_COL_HEADERS;
+
+ tools::Long const abscissa = i_abscissa - m_nColHeaderHeightPixel;
+ tools::Long const row = m_nTopRow + abscissa / m_nRowHeightPixel;
+ return row < m_pModel->getRowCount() ? row : ROW_INVALID;
+ }
+
+
+ bool TableControl_Impl::markRowAsDeselected( RowPos const i_rowIndex )
+ {
+ ::std::vector< RowPos >::iterator selPos = ::std::find( m_aSelectedRows.begin(), m_aSelectedRows.end(), i_rowIndex );
+ if ( selPos == m_aSelectedRows.end() )
+ return false;
+
+ m_aSelectedRows.erase( selPos );
+ return true;
+ }
+
+
+ bool TableControl_Impl::markRowAsSelected( RowPos const i_rowIndex )
+ {
+ if ( isRowSelected( i_rowIndex ) )
+ return false;
+
+ SelectionMode const eSelMode = getSelEngine()->GetSelectionMode();
+ switch ( eSelMode )
+ {
+ case SelectionMode::Single:
+ if ( !m_aSelectedRows.empty() )
+ {
+ OSL_ENSURE( m_aSelectedRows.size() == 1, "TableControl::markRowAsSelected: SingleSelection with more than one selected element?" );
+ m_aSelectedRows[0] = i_rowIndex;
+ break;
+ }
+ [[fallthrough]];
+
+ case SelectionMode::Multiple:
+ m_aSelectedRows.push_back( i_rowIndex );
+ break;
+
+ default:
+ OSL_ENSURE( false, "TableControl_Impl::markRowAsSelected: unsupported selection mode!" );
+ return false;
+ }
+
+ return true;
+ }
+
+
+ bool TableControl_Impl::markAllRowsAsDeselected()
+ {
+ if ( m_aSelectedRows.empty() )
+ return false;
+
+ m_aSelectedRows.clear();
+ return true;
+ }
+
+
+ bool TableControl_Impl::markAllRowsAsSelected()
+ {
+ SelectionMode const eSelMode = getSelEngine()->GetSelectionMode();
+ ENSURE_OR_RETURN_FALSE( eSelMode == SelectionMode::Multiple, "TableControl_Impl::markAllRowsAsSelected: unsupported selection mode!" );
+
+ if ( m_aSelectedRows.size() == size_t( m_pModel->getRowCount() ) )
+ {
+ #if OSL_DEBUG_LEVEL > 0
+ for ( TableSize row = 0; row < m_pModel->getRowCount(); ++row )
+ {
+ OSL_ENSURE( isRowSelected( row ), "TableControl_Impl::markAllRowsAsSelected: inconsistency in the selected rows!" );
+ }
+ #endif
+ // already all rows marked as selected
+ return false;
+ }
+
+ m_aSelectedRows.clear();
+ for ( RowPos i=0; i < m_pModel->getRowCount(); ++i )
+ m_aSelectedRows.push_back(i);
+
+ return true;
+ }
+
+
+ void TableControl_Impl::commitAccessibleEvent( sal_Int16 const i_eventID )
+ {
+ impl_commitAccessibleEvent( i_eventID, Any() );
+ }
+
+
+ void TableControl_Impl::commitCellEvent( sal_Int16 const i_eventID, const Any& i_newValue, const Any& i_oldValue )
+ {
+ if ( impl_isAccessibleAlive() )
+ m_pAccessibleTable->commitCellEvent( i_eventID, i_newValue, i_oldValue );
+ }
+
+
+ void TableControl_Impl::commitTableEvent( sal_Int16 const i_eventID, const Any& i_newValue, const Any& i_oldValue )
+ {
+ if ( impl_isAccessibleAlive() )
+ m_pAccessibleTable->commitTableEvent( i_eventID, i_newValue, i_oldValue );
+ }
+
+
+ tools::Rectangle TableControl_Impl::calcHeaderRect(bool bColHeader)
+ {
+ tools::Rectangle const aRectTableWithHeaders( impl_getAllVisibleCellsArea() );
+ Size const aSizeTableWithHeaders( aRectTableWithHeaders.GetSize() );
+ if ( bColHeader )
+ return tools::Rectangle( aRectTableWithHeaders.TopLeft(), Size( aSizeTableWithHeaders.Width(), m_nColHeaderHeightPixel ) );
+ else
+ return tools::Rectangle( aRectTableWithHeaders.TopLeft(), Size( m_nRowHeaderWidthPixel, aSizeTableWithHeaders.Height() ) );
+ }
+
+
+ tools::Rectangle TableControl_Impl::calcHeaderCellRect( bool bColHeader, sal_Int32 nPos )
+ {
+ tools::Rectangle const aHeaderRect = calcHeaderRect( bColHeader );
+ TableCellGeometry const aGeometry(
+ *this, aHeaderRect,
+ bColHeader ? nPos : COL_ROW_HEADERS,
+ bColHeader ? ROW_COL_HEADERS : nPos
+ );
+ return aGeometry.getRect();
+ }
+
+
+ tools::Rectangle TableControl_Impl::calcTableRect() const
+ {
+ return impl_getAllVisibleDataCellArea();
+ }
+
+
+ tools::Rectangle TableControl_Impl::calcCellRect( sal_Int32 nRow, sal_Int32 nCol ) const
+ {
+ tools::Rectangle aCellRect;
+ impl_getCellRect( nRow, nCol, aCellRect );
+ return aCellRect;
+ }
+
+
+ IMPL_LINK_NOARG( TableControl_Impl, OnUpdateScrollbars, void*, void )
+ {
+ // TODO: can't we simply use lcl_updateScrollbar here, so the scrollbars ranges are updated, instead of
+ // doing a complete re-layout?
+ impl_ni_relayout();
+ }
+
+
+ IMPL_LINK( TableControl_Impl, OnScroll, ScrollBar*, _pScrollbar, void )
+ {
+ DBG_ASSERT( ( _pScrollbar == m_pVScroll ) || ( _pScrollbar == m_pHScroll ),
+ "TableControl_Impl::OnScroll: where did this come from?" );
+
+ if ( _pScrollbar == m_pVScroll )
+ impl_ni_ScrollRows( _pScrollbar->GetDelta() );
+ else
+ impl_ni_ScrollColumns( _pScrollbar->GetDelta() );
+ }
+
+
+ rtl::Reference<vcl::table::IAccessibleTableControl> TableControl_Impl::getAccessible( vcl::Window& i_parentWindow )
+ {
+ if (m_pAccessibleTable)
+ return m_pAccessibleTable;
+
+ DBG_TESTSOLARMUTEX();
+ if ( m_pAccessibleTable == nullptr )
+ {
+ Reference< XAccessible > const xAccParent = i_parentWindow.GetAccessible();
+ if ( xAccParent.is() )
+ {
+ m_pAccessibleTable = m_aFactoryAccess.getFactory().createAccessibleTableControl(
+ xAccParent, m_rAntiImpl
+ );
+ }
+ }
+
+ return m_pAccessibleTable;
+ }
+
+
+ void TableControl_Impl::disposeAccessible()
+ {
+ if ( m_pAccessibleTable )
+ m_pAccessibleTable->DisposeAccessImpl();
+ m_pAccessibleTable = nullptr;
+ }
+
+
+ bool TableControl_Impl::impl_isAccessibleAlive() const
+ {
+ return m_pAccessibleTable && m_pAccessibleTable->isAlive();
+ }
+
+
+ void TableControl_Impl::impl_commitAccessibleEvent( sal_Int16 const i_eventID, Any const & i_newValue )
+ {
+ if ( impl_isAccessibleAlive() )
+ m_pAccessibleTable->commitEvent( i_eventID, i_newValue );
+ }
+
+
+ //= TableFunctionSet
+
+
+ TableFunctionSet::TableFunctionSet(TableControl_Impl* _pTableControl)
+ :m_pTableControl( _pTableControl)
+ ,m_nCurrentRow( ROW_INVALID )
+ {
+ }
+
+ TableFunctionSet::~TableFunctionSet()
+ {
+ }
+
+ void TableFunctionSet::BeginDrag()
+ {
+ }
+
+ void TableFunctionSet::CreateAnchor()
+ {
+ m_pTableControl->setAnchor( m_pTableControl->getCurRow() );
+ }
+
+
+ void TableFunctionSet::DestroyAnchor()
+ {
+ m_pTableControl->setAnchor( ROW_INVALID );
+ }
+
+
+ void TableFunctionSet::SetCursorAtPoint(const Point& rPoint, bool bDontSelectAtCursor)
+ {
+ // newRow is the row which includes the point, getCurRow() is the last selected row, before the mouse click
+ RowPos newRow = m_pTableControl->getRowAtPoint( rPoint );
+ if ( newRow == ROW_COL_HEADERS )
+ newRow = m_pTableControl->getTopRow();
+
+ ColPos newCol = m_pTableControl->getColAtPoint( rPoint );
+ if ( newCol == COL_ROW_HEADERS )
+ newCol = m_pTableControl->getLeftColumn();
+
+ if ( ( newRow == ROW_INVALID ) || ( newCol == COL_INVALID ) )
+ return;
+
+ if ( bDontSelectAtCursor )
+ {
+ if ( m_pTableControl->getSelectedRowCount() > 1 )
+ m_pTableControl->getSelEngine()->AddAlways(true);
+ }
+ else if ( m_pTableControl->getAnchor() == m_pTableControl->getCurRow() )
+ {
+ //selected region lies above the last selection
+ if( m_pTableControl->getCurRow() >= newRow)
+ {
+ //put selected rows in vector
+ while ( m_pTableControl->getAnchor() >= newRow )
+ {
+ m_pTableControl->markRowAsSelected( m_pTableControl->getAnchor() );
+ m_pTableControl->setAnchor( m_pTableControl->getAnchor() - 1 );
+ }
+ m_pTableControl->setAnchor( m_pTableControl->getAnchor() + 1 );
+ }
+ //selected region lies beneath the last selected row
+ else
+ {
+ while ( m_pTableControl->getAnchor() <= newRow )
+ {
+ m_pTableControl->markRowAsSelected( m_pTableControl->getAnchor() );
+ m_pTableControl->setAnchor( m_pTableControl->getAnchor() + 1 );
+ }
+ m_pTableControl->setAnchor( m_pTableControl->getAnchor() - 1 );
+ }
+ m_pTableControl->invalidateSelectedRegion( m_pTableControl->getCurRow(), newRow );
+ }
+ //no region selected
+ else
+ {
+ if ( !m_pTableControl->hasRowSelection() )
+ m_pTableControl->markRowAsSelected( newRow );
+ else
+ {
+ if ( m_pTableControl->getSelEngine()->GetSelectionMode() == SelectionMode::Single )
+ {
+ DeselectAll();
+ m_pTableControl->markRowAsSelected( newRow );
+ }
+ else
+ {
+ m_pTableControl->markRowAsSelected( newRow );
+ }
+ }
+ if ( m_pTableControl->getSelectedRowCount() > 1 && m_pTableControl->getSelEngine()->GetSelectionMode() != SelectionMode::Single )
+ m_pTableControl->getSelEngine()->AddAlways(true);
+
+ m_pTableControl->invalidateRow( newRow );
+ }
+ m_pTableControl->goTo( newCol, newRow );
+ }
+
+ bool TableFunctionSet::IsSelectionAtPoint( const Point& rPoint )
+ {
+ m_pTableControl->getSelEngine()->AddAlways(false);
+ if ( !m_pTableControl->hasRowSelection() )
+ return false;
+ else
+ {
+ RowPos curRow = m_pTableControl->getRowAtPoint( rPoint );
+ m_pTableControl->setAnchor( ROW_INVALID );
+ bool selected = m_pTableControl->isRowSelected( curRow );
+ m_nCurrentRow = curRow;
+ return selected;
+ }
+ }
+
+ void TableFunctionSet::DeselectAtPoint( const Point& )
+ {
+ m_pTableControl->invalidateRow( m_nCurrentRow );
+ m_pTableControl->markRowAsDeselected( m_nCurrentRow );
+ }
+
+
+ void TableFunctionSet::DeselectAll()
+ {
+ if ( m_pTableControl->hasRowSelection() )
+ {
+ for ( size_t i=0; i<m_pTableControl->getSelectedRowCount(); ++i )
+ {
+ RowPos const rowIndex = m_pTableControl->getSelectedRowIndex(i);
+ m_pTableControl->invalidateRow( rowIndex );
+ }
+
+ m_pTableControl->markAllRowsAsDeselected();
+ }
+ }
+
+
+} // namespace svt::table
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/table/tablecontrol_impl.hxx b/toolkit/source/controls/table/tablecontrol_impl.hxx
new file mode 100644
index 0000000000..a9498958e7
--- /dev/null
+++ b/toolkit/source/controls/table/tablecontrol_impl.hxx
@@ -0,0 +1,480 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <controls/table/tablemodel.hxx>
+#include <controls/table/tablecontrolinterface.hxx>
+
+#include <vcl/svtaccessiblefactory.hxx>
+#include <vcl/accessibletable.hxx>
+
+#include <vcl/seleng.hxx>
+
+#include <vector>
+
+class ScrollBar;
+class ScrollBarBox;
+
+namespace svt::table
+{
+ struct MutableColumnMetrics : public ColumnMetrics
+ {
+ MutableColumnMetrics()
+ :ColumnMetrics()
+ {
+ }
+
+ MutableColumnMetrics( tools::Long const i_startPixel, tools::Long const i_endPixel )
+ :ColumnMetrics( i_startPixel, i_endPixel )
+ {
+ }
+
+ tools::Long getStart() const { return nStartPixel; }
+ tools::Long getEnd() const { return nEndPixel; }
+
+ void move( tools::Long const i_offset ) { nStartPixel += i_offset; nEndPixel += i_offset; }
+
+ tools::Long getWidth() const { return nEndPixel - nStartPixel; }
+ };
+
+ struct ColumnInfoPositionLess
+ {
+ bool operator()( MutableColumnMetrics const& i_lhs, MutableColumnMetrics const& i_rhs )
+ {
+ return i_lhs.getEnd() < i_rhs.getStart();
+ }
+ };
+
+ typedef ::std::vector< MutableColumnMetrics > ColumnPositions;
+
+ class TableControl;
+ class TableDataWindow;
+ class TableFunctionSet;
+
+
+ //= TableControl_Impl
+
+ class TableControl_Impl :public ITableControl
+ ,public ITableModelListener
+ {
+ friend class TableGeometry;
+ friend class TableRowGeometry;
+ friend class TableColumnGeometry;
+ friend class SuspendInvariants;
+
+ private:
+ /// the control whose impl-instance we implement
+ TableControl& m_rAntiImpl;
+ /// the model of the table control
+ PTableModel m_pModel;
+ /// the input handler to use, usually the input handler as provided by ->m_pModel
+ PTableInputHandler m_pInputHandler;
+ /// info about the widths of our columns
+ ColumnPositions m_aColumnWidths;
+
+ /// the height of a single row in the table, measured in pixels
+ tools::Long m_nRowHeightPixel;
+ /// the height of the column header row in the table, measured in pixels
+ tools::Long m_nColHeaderHeightPixel;
+ /// the width of the row header column in the table, measured in pixels
+ tools::Long m_nRowHeaderWidthPixel;
+
+ /// the number of columns in the table control. Cached model value.
+ TableSize m_nColumnCount;
+
+ /// the number of rows in the table control. Cached model value.
+ TableSize m_nRowCount;
+
+ ColPos m_nCurColumn;
+ RowPos m_nCurRow;
+ ColPos m_nLeftColumn;
+ RowPos m_nTopRow;
+
+ sal_Int32 m_nCursorHidden;
+
+ /** the window to contain all data content, including header bars
+
+ The window's upper left corner is at position (0,0), relative to the
+ table control, which is the direct parent of the data window.
+ */
+ VclPtr<TableDataWindow> m_pDataWindow;
+ /// the vertical scrollbar, if any
+ VclPtr<ScrollBar> m_pVScroll;
+ /// the horizontal scrollbar, if any
+ VclPtr<ScrollBar> m_pHScroll;
+ VclPtr<ScrollBarBox> m_pScrollCorner;
+ //selection engine - for determining selection range, e.g. single, multiple
+ std::unique_ptr<SelectionEngine> m_pSelEngine;
+ //vector which contains the selected rows
+ std::vector<RowPos> m_aSelectedRows;
+ //part of selection engine
+ std::unique_ptr<TableFunctionSet> m_pTableFunctionSet;
+ //part of selection engine
+ RowPos m_nAnchor;
+ bool m_bUpdatingColWidths;
+
+ vcl::AccessibleFactoryAccess m_aFactoryAccess;
+ rtl::Reference<vcl::table::IAccessibleTableControl> m_pAccessibleTable;
+
+ public:
+ void setModel( const PTableModel& _pModel );
+
+ const PTableInputHandler& getInputHandler() const { return m_pInputHandler; }
+
+ RowPos getCurRow() const { return m_nCurRow; }
+
+ RowPos getAnchor() const { return m_nAnchor; }
+ void setAnchor( RowPos const i_anchor ) { m_nAnchor = i_anchor; }
+
+ RowPos getTopRow() const { return m_nTopRow; }
+ ColPos getLeftColumn() const { return m_nLeftColumn; }
+
+ const TableControl& getAntiImpl() const { return m_rAntiImpl; }
+ TableControl& getAntiImpl() { return m_rAntiImpl; }
+
+ public:
+ explicit TableControl_Impl( TableControl& _rAntiImpl );
+ virtual ~TableControl_Impl() override;
+
+ /** to be called when the anti-impl instance has been resized
+ */
+ void onResize();
+
+ /** paints the table control content which intersects with the given rectangle
+ */
+ void doPaintContent(vcl::RenderContext& rRenderContext, const tools::Rectangle& _rUpdateRect);
+
+ /** moves the cursor to the cell with the given coordinates
+
+ To ease the caller's code, the coordinates must not necessarily denote a
+ valid position. If they don't, <FALSE/> will be returned.
+ */
+ bool goTo( ColPos _nColumn, RowPos _nRow );
+
+ /** ensures that the given coordinate is visible
+ @param _nColumn
+ the column position which should be visible. Must be non-negative, and smaller
+ than the column count.
+ @param _nRow
+ the row position which should be visibleMust be non-negative, and smaller
+ than the row count.
+ */
+ void ensureVisible( ColPos _nColumn, RowPos _nRow );
+
+ /** retrieves the content of the given cell, converted to a string
+ */
+ OUString getCellContentAsString( RowPos const i_row, ColPos const i_col );
+
+ /** returns the position of the current row in the selection vector */
+ static int getRowSelectedNumber(const ::std::vector<RowPos>& selectedRows, RowPos current);
+
+ void invalidateRect(const tools::Rectangle &rInvalidateRect);
+
+ /** ??? */
+ void invalidateSelectedRegion( RowPos _nPrevRow, RowPos _nCurRow );
+
+ /** invalidates the part of the data window which is covered by the given rows
+ @param i_firstRow
+ the index of the first row to include in the invalidation
+ @param i_lastRow
+ the index of the last row to include in the invalidation, or ROW_INVALID if the invalidation
+ should happen down to the bottom of the data window.
+ */
+ void invalidateRowRange( RowPos const i_firstRow, RowPos const i_lastRow );
+
+ /** invalidates the part of the data window which is covered by the given row
+ */
+ void invalidateRow( RowPos const i_row ) { invalidateRowRange( i_row, i_row ); }
+
+ /** invalidates all selected rows
+ */
+ void invalidateSelectedRows();
+
+ void checkCursorPosition();
+
+ bool hasRowSelection() const { return !m_aSelectedRows.empty(); }
+ size_t getSelectedRowCount() const { return m_aSelectedRows.size(); }
+ RowPos getSelectedRowIndex( size_t const i_selectionIndex ) const;
+
+ /** removes the given row index from m_aSelectedRows
+
+ @return
+ <TRUE/> if and only if the row was previously marked as selected
+ */
+ bool markRowAsDeselected( RowPos const i_rowIndex );
+
+ /** marks the given row as selected, by putting it into m_aSelectedRows
+ @return
+ <TRUE/> if and only if the row was previously <em>not</em> marked as selected
+ */
+ bool markRowAsSelected( RowPos const i_rowIndex );
+
+ /** marks all rows as deselected
+ @return
+ <TRUE/> if and only if the selection actually changed by this operation
+ */
+ bool markAllRowsAsDeselected();
+
+ /** marks all rows as selected
+ @return
+ <FALSE/> if and only if all rows were selected already.
+ */
+ bool markAllRowsAsSelected();
+
+ void commitAccessibleEvent( sal_Int16 const i_eventID );
+ void commitCellEvent( sal_Int16 const i_eventID, const css::uno::Any& i_newValue, const css::uno::Any& i_oldValue );
+ void commitTableEvent( sal_Int16 const i_eventID, const css::uno::Any& i_newValue, const css::uno::Any& i_oldValue );
+
+ // ITableControl
+ virtual void hideCursor() override;
+ virtual void showCursor() override;
+ virtual bool dispatchAction( TableControlAction _eAction ) override;
+ virtual SelectionEngine* getSelEngine() override;
+ virtual PTableModel getModel() const override;
+ virtual ColPos getCurrentColumn() const override;
+ virtual RowPos getCurrentRow() const override;
+ virtual void activateCell( ColPos const i_col, RowPos const i_row ) override;
+ virtual ::Size getTableSizePixel() const override;
+ virtual void setPointer( PointerStyle i_pointer ) override;
+ virtual void captureMouse() override;
+ virtual void releaseMouse() override;
+ virtual void invalidate( TableArea const i_what ) override;
+ virtual tools::Long pixelWidthToAppFont( tools::Long const i_pixels ) const override;
+ virtual void hideTracking() override;
+ virtual void showTracking( tools::Rectangle const & i_location, ShowTrackFlags const i_flags ) override;
+ RowPos getRowAtPoint( const Point& rPoint ) const;
+ ColPos getColAtPoint( const Point& rPoint ) const;
+ virtual TableCell hitTest( const Point& rPoint ) const override;
+ virtual ColumnMetrics getColumnMetrics( ColPos const i_column ) const override;
+ virtual bool isRowSelected( RowPos i_row ) const override;
+
+
+ tools::Long appFontWidthToPixel( tools::Long const i_appFontUnits ) const;
+
+ TableDataWindow& getDataWindow() { return *m_pDataWindow; }
+ const TableDataWindow& getDataWindow() const { return *m_pDataWindow; }
+ ScrollBar* getHorzScrollbar() { return m_pHScroll; }
+ ScrollBar* getVertScrollbar() { return m_pVScroll; }
+
+ tools::Rectangle calcHeaderRect( bool bColHeader );
+ tools::Rectangle calcHeaderCellRect( bool bColHeader, sal_Int32 nPos );
+ tools::Rectangle calcTableRect() const;
+ tools::Rectangle calcCellRect( sal_Int32 nRow, sal_Int32 nCol ) const;
+
+ // A11Y
+ rtl::Reference<vcl::table::IAccessibleTableControl>
+ getAccessible( vcl::Window& i_parentWindow );
+ void disposeAccessible();
+
+ bool isAccessibleAlive() const { return impl_isAccessibleAlive(); }
+
+ // ITableModelListener
+ virtual void rowsInserted( RowPos first, RowPos last ) override;
+ virtual void rowsRemoved( RowPos first, RowPos last ) override;
+ virtual void columnInserted() override;
+ virtual void columnRemoved() override;
+ virtual void allColumnsRemoved() override;
+ virtual void cellsUpdated( RowPos const i_firstRow, RowPos const i_lastRow ) override;
+ virtual void columnChanged( ColPos const i_column, ColumnAttributeGroup const i_attributeGroup ) override;
+ virtual void tableMetricsChanged() override;
+
+ private:
+ bool impl_isAccessibleAlive() const;
+ void impl_commitAccessibleEvent(
+ sal_Int16 const i_eventID,
+ css::uno::Any const & i_newValue
+ );
+
+ /** toggles the cursor visibility
+
+ The method is not bound to the classes public invariants, as it's used in
+ situations where the they must not necessarily be fulfilled.
+ */
+ void impl_ni_doSwitchCursor( bool _bOn );
+
+ /** returns the number of visible rows.
+
+ @param _bAcceptPartialRow
+ specifies whether a possible only partially visible last row is
+ counted, too.
+ */
+ TableSize impl_getVisibleRows( bool _bAcceptPartialRow ) const;
+
+ /** returns the number of visible columns
+
+ The value may change with different horizontal scroll positions, as
+ different columns have different widths. For instance, if your control is
+ 100 pixels wide, and has three columns of width 50, 50, 100, respectively,
+ then this method will return either "2" or "1", depending on which column
+ is the first visible one.
+
+ @param _bAcceptPartialRow
+ specifies whether a possible only partially visible last row is
+ counted, too.
+ */
+ TableSize impl_getVisibleColumns( bool _bAcceptPartialCol ) const;
+
+ /** determines the rectangle occupied by the given cell
+ */
+ void impl_getCellRect( ColPos _nColumn, RowPos _nRow, tools::Rectangle& _rCellRect ) const;
+
+ /** updates all cached model values
+
+ The method is not bound to the classes public invariants, as it's used in
+ situations where the they must not necessarily be fulfilled.
+ */
+ void impl_ni_updateCachedModelValues();
+
+ /** updates the cached table metrics (row height etc.)
+ */
+ void impl_ni_updateCachedTableMetrics();
+
+ /** does a relayout of the table control
+
+ Column widths, and consequently the availability of the vertical and horizontal scrollbar, are updated
+ with a call to this method.
+
+ @param i_assumeInflexibleColumnsUpToIncluding
+ the index of a column up to which all columns should be considered as inflexible, or
+ <code>COL_INVALID</code>.
+ */
+ void impl_ni_relayout( ColPos const i_assumeInflexibleColumnsUpToIncluding = COL_INVALID );
+
+ /** calculates the new width of our columns, taking into account their min and max widths, and their relative
+ flexibility.
+
+ @param i_assumeInflexibleColumnsUpToIncluding
+ the index of a column up to which all columns should be considered as inflexible, or
+ <code>COL_INVALID</code>.
+
+ @param i_assumeVerticalScrollbar
+ controls whether or not we should assume the presence of a vertical scrollbar. If <true/>, and
+ if the model has a VerticalScrollbarVisibility != ScrollbarShowNever, the method will leave
+ space for a vertical scrollbar.
+
+ @return
+ the overall width of the grid, which is available for columns
+ */
+ tools::Long impl_ni_calculateColumnWidths(
+ ColPos const i_assumeInflexibleColumnsUpToIncluding,
+ bool const i_assumeVerticalScrollbar,
+ ::std::vector< tools::Long >& o_newColWidthsPixel
+ ) const;
+
+ /** positions all child windows, e.g. the both scrollbars, the corner window, and the data window
+ */
+ void impl_ni_positionChildWindows(
+ tools::Rectangle const & i_dataCellPlayground,
+ bool const i_verticalScrollbar,
+ bool const i_horizontalScrollbar
+ );
+
+ /** scrolls the view by the given number of rows
+
+ The method is not bound to the classes public invariants, as it's used in
+ situations where the they must not necessarily be fulfilled.
+
+ @return
+ the number of rows by which the viewport was scrolled. This may differ
+ from the given numbers to scroll in case the begin or the end of the
+ row range were reached.
+ */
+ TableSize impl_ni_ScrollRows( TableSize _nRowDelta );
+
+ /** equivalent to impl_ni_ScrollRows, but checks the instances invariants beforehand (in a non-product build only)
+ */
+ TableSize impl_scrollRows( TableSize const i_rowDelta );
+
+ /** scrolls the view by the given number of columns
+
+ The method is not bound to the classes public invariants, as it's used in
+ situations where the they must not necessarily be fulfilled.
+
+ @return
+ the number of columns by which the viewport was scrolled. This may differ
+ from the given numbers to scroll in case the begin or the end of the
+ column range were reached.
+ */
+ TableSize impl_ni_ScrollColumns( TableSize _nColumnDelta );
+
+ /** equivalent to impl_ni_ScrollColumns, but checks the instances invariants beforehand (in a non-product build only)
+ */
+ TableSize impl_scrollColumns( TableSize const i_columnDelta );
+
+ /** retrieves the area occupied by the totality of (at least partially) visible cells
+
+ The returned area includes row and column headers. Also, it takes into
+ account the fact that there might be less columns than would normally
+ find room in the control.
+
+ As a result of respecting the partial visibility of rows and columns,
+ the returned area might be larger than the data window's output size.
+ */
+ tools::Rectangle impl_getAllVisibleCellsArea() const;
+
+ /** retrieves the area occupied by all (at least partially) visible data cells.
+
+ Effectively, the returned area is the same as returned by ->impl_getAllVisibleCellsArea,
+ minus the row and column header areas.
+ */
+ tools::Rectangle impl_getAllVisibleDataCellArea() const;
+
+ /** retrieves the column which covers the given ordinate
+ */
+ ColPos impl_getColumnForOrdinate( tools::Long const i_ordinate ) const;
+
+ /** retrieves the row which covers the given abscissa
+ */
+ RowPos impl_getRowForAbscissa( tools::Long const i_abscissa ) const;
+
+ /// invalidates the window area occupied by the given column
+ void impl_invalidateColumn( ColPos const i_column );
+
+ DECL_LINK( OnScroll, ScrollBar*, void );
+ DECL_LINK( OnUpdateScrollbars, void*, void );
+ };
+
+ //see seleng.hxx, seleng.cxx, FunctionSet overridables, part of selection engine
+ class TableFunctionSet : public FunctionSet
+ {
+ private:
+ TableControl_Impl* m_pTableControl;
+ RowPos m_nCurrentRow;
+
+ public:
+ explicit TableFunctionSet(TableControl_Impl* _pTableControl);
+ virtual ~TableFunctionSet() override;
+
+ virtual void BeginDrag() override;
+ virtual void CreateAnchor() override;
+ virtual void DestroyAnchor() override;
+ virtual void SetCursorAtPoint(const Point& rPoint, bool bDontSelectAtCursor = false) override;
+ virtual bool IsSelectionAtPoint( const Point& rPoint ) override;
+ virtual void DeselectAtPoint( const Point& rPoint ) override;
+ virtual void DeselectAll() override;
+ };
+
+
+} // namespace svt::table
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/table/tabledatawindow.cxx b/toolkit/source/controls/table/tabledatawindow.cxx
new file mode 100644
index 0000000000..fc49ee08d6
--- /dev/null
+++ b/toolkit/source/controls/table/tabledatawindow.cxx
@@ -0,0 +1,201 @@
+/* -*- 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/table/tablecontrol.hxx>
+
+#include "tabledatawindow.hxx"
+#include "tablecontrol_impl.hxx"
+#include "tablegeometry.hxx"
+
+#include <vcl/help.hxx>
+#include <vcl/toolkit/scrbar.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/commandevent.hxx>
+
+namespace svt::table
+{
+ using css::uno::Any;
+
+ TableDataWindow::TableDataWindow( TableControl_Impl& _rTableControl )
+ :Window( &_rTableControl.getAntiImpl() )
+ ,m_rTableControl( _rTableControl )
+ {
+ // by default, use the background as determined by the style settings
+ const Color aWindowColor( GetSettings().GetStyleSettings().GetFieldColor() );
+ SetBackground( Wallpaper( aWindowColor ) );
+ GetOutDev()->SetFillColor( aWindowColor );
+ }
+
+ TableDataWindow::~TableDataWindow()
+ {
+ disposeOnce();
+ }
+
+ void TableDataWindow::dispose()
+ {
+ impl_hideTipWindow();
+ Window::dispose();
+ }
+
+ void TableDataWindow::Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& rUpdateRect )
+ {
+ m_rTableControl.doPaintContent(rRenderContext, rUpdateRect);
+ }
+
+ void TableDataWindow::RequestHelp( const HelpEvent& rHEvt )
+ {
+ HelpEventMode const nHelpMode = rHEvt.GetMode();
+ if ( IsMouseCaptured()
+ || !( nHelpMode & HelpEventMode::QUICK )
+ )
+ {
+ Window::RequestHelp( rHEvt );
+ return;
+ }
+
+ OUString sHelpText;
+ QuickHelpFlags nHelpStyle = QuickHelpFlags::NONE;
+
+ Point const aMousePos( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ) );
+ RowPos const hitRow = m_rTableControl.getRowAtPoint( aMousePos );
+ ColPos const hitCol = m_rTableControl.getColAtPoint( aMousePos );
+
+ PTableModel const pTableModel( m_rTableControl.getModel() );
+ if ( ( hitCol >= 0 ) && ( hitCol < pTableModel->getColumnCount() ) )
+ {
+ if ( hitRow == ROW_COL_HEADERS )
+ {
+ sHelpText = pTableModel->getColumnModel( hitCol )->getHelpText();
+ }
+ else if ( ( hitRow >= 0 ) && ( hitRow < pTableModel->getRowCount() ) )
+ {
+ Any aCellToolTip;
+ pTableModel->getCellToolTip( hitCol, hitRow, aCellToolTip );
+ if ( !aCellToolTip.hasValue() )
+ {
+ // use the cell content
+ pTableModel->getCellContent( hitCol, hitRow, aCellToolTip );
+
+ // use the cell content as tool tip only if it doesn't fit into the cell.
+ tools::Rectangle const aWindowRect( Point( 0, 0 ), GetOutputSizePixel() );
+ TableCellGeometry const aCell( m_rTableControl, aWindowRect, hitCol, hitRow );
+ tools::Rectangle const aCellRect( aCell.getRect() );
+
+ PTableRenderer const pRenderer = pTableModel->getRenderer();
+ if ( pRenderer->FitsIntoCell( aCellToolTip, *GetOutDev(), aCellRect ) )
+ aCellToolTip.clear();
+ }
+
+ pTableModel->getRenderer()->GetFormattedCellString( aCellToolTip, sHelpText );
+
+ if ( sHelpText.indexOf( '\n' ) >= 0 )
+ nHelpStyle = QuickHelpFlags::TipStyleBalloon;
+ }
+ }
+
+ if ( !sHelpText.isEmpty() )
+ {
+ // hide the standard (singleton) help window, so we do not have two help windows open at the same time
+ Help::HideBalloonAndQuickHelp();
+
+ tools::Rectangle const aControlScreenRect(
+ OutputToScreenPixel( Point( 0, 0 ) ),
+ GetOutputSizePixel()
+ );
+
+ Help::ShowQuickHelp(this, aControlScreenRect, sHelpText, nHelpStyle);
+ }
+ else
+ {
+ impl_hideTipWindow();
+ Window::RequestHelp( rHEvt );
+ }
+ }
+
+ void TableDataWindow::impl_hideTipWindow()
+ {
+ Help::HideBalloonAndQuickHelp();
+ }
+
+ void TableDataWindow::MouseMove( const MouseEvent& rMEvt )
+ {
+ if ( rMEvt.IsLeaveWindow() )
+ impl_hideTipWindow();
+
+ if ( !m_rTableControl.getInputHandler()->MouseMove( m_rTableControl, rMEvt ) )
+ {
+ Window::MouseMove( rMEvt );
+ }
+ }
+
+ void TableDataWindow::MouseButtonDown( const MouseEvent& rMEvt )
+ {
+ impl_hideTipWindow();
+
+ Point const aPoint = rMEvt.GetPosPixel();
+ RowPos const hitRow = m_rTableControl.getRowAtPoint( aPoint );
+ bool const wasRowSelected = m_rTableControl.isRowSelected( hitRow );
+ size_t const nPrevSelRowCount = m_rTableControl.getSelectedRowCount();
+
+ if ( !m_rTableControl.getInputHandler()->MouseButtonDown( m_rTableControl, rMEvt ) )
+ {
+ Window::MouseButtonDown( rMEvt );
+ return;
+ }
+
+ bool const isRowSelected = m_rTableControl.isRowSelected( hitRow );
+ size_t const nCurSelRowCount = m_rTableControl.getSelectedRowCount();
+ if ( isRowSelected != wasRowSelected || nCurSelRowCount != nPrevSelRowCount )
+ {
+ m_aSelectHdl.Call( nullptr );
+ }
+ }
+
+
+ void TableDataWindow::MouseButtonUp( const MouseEvent& rMEvt )
+ {
+ if ( !m_rTableControl.getInputHandler()->MouseButtonUp( m_rTableControl, rMEvt ) )
+ Window::MouseButtonUp( rMEvt );
+
+ m_rTableControl.getAntiImpl().GrabFocus();
+ }
+
+
+ bool TableDataWindow::EventNotify(NotifyEvent& rNEvt )
+ {
+ bool bDone = false;
+ if ( rNEvt.GetType() == NotifyEventType::COMMAND )
+ {
+ const CommandEvent& rCEvt = *rNEvt.GetCommandEvent();
+ if ( rCEvt.GetCommand() == CommandEventId::Wheel )
+ {
+ const CommandWheelData* pData = rCEvt.GetWheelData();
+ if( !pData->GetModifier() && ( pData->GetMode() == CommandWheelMode::SCROLL ) )
+ {
+ bDone = HandleScrollCommand( rCEvt, m_rTableControl.getHorzScrollbar(), m_rTableControl.getVertScrollbar() );
+ }
+ }
+ }
+ return bDone || Window::EventNotify( rNEvt );
+ }
+
+} // namespace svt::table
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/table/tabledatawindow.hxx b/toolkit/source/controls/table/tabledatawindow.hxx
new file mode 100644
index 0000000000..e42a054939
--- /dev/null
+++ b/toolkit/source/controls/table/tabledatawindow.hxx
@@ -0,0 +1,66 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <vcl/window.hxx>
+
+
+namespace svt::table
+{
+ class TableControl_Impl;
+ class TableFunctionSet;
+
+ /** the window containing the content area (including headers) of
+ a table control
+ */
+ class TableDataWindow : public vcl::Window
+ {
+ friend class TableFunctionSet;
+ private:
+ TableControl_Impl& m_rTableControl;
+ Link<LinkParamNone*,void> m_aSelectHdl;
+
+ public:
+ explicit TableDataWindow( TableControl_Impl& _rTableControl );
+ virtual ~TableDataWindow() override;
+ virtual void dispose() override;
+
+ void SetSelectHdl(const Link<LinkParamNone*,void>& rLink)
+ {
+ m_aSelectHdl = rLink;
+ }
+
+ // Window overridables
+ virtual void Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect) override;
+ virtual void MouseMove( const MouseEvent& rMEvt) override;
+ virtual void MouseButtonDown( const MouseEvent& rMEvt) override;
+ virtual void MouseButtonUp( const MouseEvent& rMEvt) override;
+ virtual bool EventNotify(NotifyEvent& rNEvt) override;
+ virtual void RequestHelp( const HelpEvent& rHEvt ) override;
+
+ private:
+ static void impl_hideTipWindow();
+ };
+
+} // namespace svt::table
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/table/tablegeometry.cxx b/toolkit/source/controls/table/tablegeometry.cxx
new file mode 100644
index 0000000000..5b18826c50
--- /dev/null
+++ b/toolkit/source/controls/table/tablegeometry.cxx
@@ -0,0 +1,154 @@
+/* -*- 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 "tablegeometry.hxx"
+#include "tablecontrol_impl.hxx"
+
+
+namespace svt::table
+{
+
+
+ //= TableRowGeometry
+
+
+ TableRowGeometry::TableRowGeometry( TableControl_Impl const & _rControl, tools::Rectangle const & _rBoundaries,
+ RowPos const _nRow, bool const i_allowVirtualRows )
+ :TableGeometry( _rControl, _rBoundaries )
+ ,m_nRowPos( _nRow )
+ ,m_bAllowVirtualRows( i_allowVirtualRows )
+ {
+ if ( m_nRowPos == ROW_COL_HEADERS )
+ {
+ m_aRect.SetTop( 0 );
+ m_aRect.SetBottom( m_rControl.m_nColHeaderHeightPixel - 1 );
+ }
+ else
+ {
+ impl_initRect();
+ }
+ }
+
+
+ void TableRowGeometry::impl_initRect()
+ {
+ if ( ( m_nRowPos >= m_rControl.m_nTopRow ) && impl_isValidRow( m_nRowPos ) )
+ {
+ m_aRect.SetTop( m_rControl.m_nColHeaderHeightPixel + ( m_nRowPos - m_rControl.m_nTopRow ) * m_rControl.m_nRowHeightPixel );
+ m_aRect.SetBottom( m_aRect.Top() + m_rControl.m_nRowHeightPixel - 1 );
+ }
+ else
+ m_aRect.SetEmpty();
+ }
+
+
+ bool TableRowGeometry::impl_isValidRow( RowPos const i_row ) const
+ {
+ return m_bAllowVirtualRows || ( i_row < m_rControl.m_pModel->getRowCount() );
+ }
+
+
+ bool TableRowGeometry::moveDown()
+ {
+ if ( m_nRowPos == ROW_COL_HEADERS )
+ {
+ m_nRowPos = m_rControl.m_nTopRow;
+ impl_initRect();
+ }
+ else
+ {
+ if ( impl_isValidRow( ++m_nRowPos ) )
+ m_aRect.Move( 0, m_rControl.m_nRowHeightPixel );
+ else
+ m_aRect.SetEmpty();
+ }
+ return isValid();
+ }
+
+
+ //= TableColumnGeometry
+
+
+ TableColumnGeometry::TableColumnGeometry( TableControl_Impl const & _rControl, tools::Rectangle const & _rBoundaries,
+ ColPos const _nCol )
+ :TableGeometry( _rControl, _rBoundaries )
+ ,m_nColPos( _nCol )
+ {
+ if ( m_nColPos == COL_ROW_HEADERS )
+ {
+ m_aRect.SetLeft( 0 );
+ m_aRect.SetRight( m_rControl.m_nRowHeaderWidthPixel - 1 );
+ }
+ else
+ {
+ impl_initRect();
+ }
+ }
+
+
+ void TableColumnGeometry::impl_initRect()
+ {
+ ColPos nLeftColumn = m_rControl.m_nLeftColumn;
+ if ( ( m_nColPos >= nLeftColumn ) && impl_isValidColumn( m_nColPos ) )
+ {
+ m_aRect.SetLeft( m_rControl.m_nRowHeaderWidthPixel );
+ // TODO: take into account any possibly frozen columns
+
+ for ( ColPos col = nLeftColumn; col < m_nColPos; ++col )
+ m_aRect.AdjustLeft(m_rControl.m_aColumnWidths[ col ].getWidth() );
+ m_aRect.SetRight( m_aRect.Left() + m_rControl.m_aColumnWidths[ m_nColPos ].getWidth() - 1 );
+ }
+ else
+ m_aRect.SetEmpty();
+ }
+
+
+ bool TableColumnGeometry::impl_isValidColumn( ColPos const i_column ) const
+ {
+ return i_column < ColPos( m_rControl.m_aColumnWidths.size() );
+ }
+
+
+ bool TableColumnGeometry::moveRight()
+ {
+ if ( m_nColPos == COL_ROW_HEADERS )
+ {
+ m_nColPos = m_rControl.m_nLeftColumn;
+ impl_initRect();
+ }
+ else
+ {
+ if ( impl_isValidColumn( ++m_nColPos ) )
+ {
+ m_aRect.SetLeft( m_aRect.Right() + 1 );
+ m_aRect.AdjustRight(m_rControl.m_aColumnWidths[ m_nColPos ].getWidth() );
+ }
+ else
+ m_aRect.SetEmpty();
+ }
+
+ return isValid();
+ }
+
+
+} // namespace svt::table
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/table/tablegeometry.hxx b/toolkit/source/controls/table/tablegeometry.hxx
new file mode 100644
index 0000000000..dde156ffd2
--- /dev/null
+++ b/toolkit/source/controls/table/tablegeometry.hxx
@@ -0,0 +1,156 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <controls/table/tabletypes.hxx>
+#include <tools/gen.hxx>
+
+namespace svt::table
+{
+
+
+ class TableControl_Impl;
+
+
+ //= TableGeometry
+
+ class TableGeometry
+ {
+ protected:
+ const TableControl_Impl& m_rControl;
+ const tools::Rectangle& m_rBoundaries;
+ tools::Rectangle m_aRect;
+
+ protected:
+ TableGeometry(
+ const TableControl_Impl& _rControl,
+ const tools::Rectangle& _rBoundaries
+ )
+ :m_rControl( _rControl )
+ ,m_rBoundaries( _rBoundaries )
+ ,m_aRect( _rBoundaries )
+ {
+ }
+
+ public:
+ // attribute access
+ const TableControl_Impl& getControl() const { return m_rControl; }
+
+ // status
+ const tools::Rectangle& getRect() const { return m_aRect; }
+ bool isValid() const { return !m_aRect.GetIntersection( m_rBoundaries ).IsEmpty(); }
+ };
+
+
+ //= TableRowGeometry
+
+ class TableRowGeometry final : public TableGeometry
+ {
+ public:
+ TableRowGeometry(
+ TableControl_Impl const & _rControl,
+ tools::Rectangle const & _rBoundaries,
+ RowPos const _nRow,
+ bool const i_allowVirtualRows = false
+ // allow rows >= getRowCount()?
+ );
+
+ // status
+ RowPos getRow() const { return m_nRowPos; }
+ // operations
+ bool moveDown();
+
+ private:
+ void impl_initRect();
+ bool impl_isValidRow( RowPos const i_row ) const;
+
+ RowPos m_nRowPos;
+ bool m_bAllowVirtualRows;
+ };
+
+
+ //= TableColumnGeometry
+
+ class TableColumnGeometry final : public TableGeometry
+ {
+ public:
+ TableColumnGeometry(
+ TableControl_Impl const & _rControl,
+ tools::Rectangle const & _rBoundaries,
+ ColPos const _nCol
+ );
+
+ // status
+ ColPos getCol() const { return m_nColPos; }
+ // operations
+ bool moveRight();
+
+ private:
+ void impl_initRect();
+ bool impl_isValidColumn( ColPos const i_column ) const;
+
+ ColPos m_nColPos;
+ };
+
+
+ //= TableCellGeometry
+
+ /** a helper representing geometry information of a cell
+ */
+ class TableCellGeometry
+ {
+ private:
+ TableRowGeometry m_aRow;
+ TableColumnGeometry m_aCol;
+
+ public:
+ TableCellGeometry(
+ TableControl_Impl const & _rControl,
+ tools::Rectangle const & _rBoundaries,
+ ColPos const _nCol,
+ RowPos const _nRow
+ )
+ :m_aRow( _rControl, _rBoundaries, _nRow, false/*allowVirtualCells*/ )
+ ,m_aCol( _rControl, _rBoundaries, _nCol )
+ {
+ }
+
+ TableCellGeometry(
+ const TableRowGeometry& _rRow,
+ ColPos _nCol
+ )
+ :m_aRow( _rRow )
+ ,m_aCol( _rRow.getControl(), _rRow.getRect(), _nCol )
+ {
+ }
+
+ tools::Rectangle getRect() const { return m_aRow.getRect().GetIntersection( m_aCol.getRect() ); }
+ ColPos getColumn() const { return m_aCol.getCol(); }
+ bool isValid() const { return !getRect().IsEmpty(); }
+
+ bool moveRight() {return m_aCol.moveRight(); }
+ };
+
+
+} // namespace svt::table
+
+
+
+/* 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 0000000000..367b5c4f22
--- /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 <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 <comphelper/diagnose_ex.hxx>
+#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, getXWeak(), 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(), getXWeak() );
+ 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( )
+{
+ std::unique_lock aGuard( m_aMutex );
+ return sal_Int32( m_aTabPageVector.size());
+}
+
+uno::Any SAL_CALL UnoControlTabPageContainerModel::getByIndex( ::sal_Int32 nIndex )
+{
+ std::unique_lock aGuard( m_aMutex );
+ 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( )
+{
+ std::unique_lock aGuard( m_aMutex );
+ 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 = getXWeak();
+ 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 0000000000..7185f82419
--- /dev/null
+++ b/toolkit/source/controls/tabpagemodel.cxx
@@ -0,0 +1,295 @@
+/* -*- 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 <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 );
+ ImplRegisterProperty( BASEPROPERTY_IMAGEURL );
+}
+
+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 OUString s_sResourceResolver = u"ResourceResolver"_ustr;
+ setPropertyValue(s_sResourceResolver,xDialogProp->getPropertyValue(s_sResourceResolver));
+ setPropertyValue(GetPropertyName(BASEPROPERTY_TITLE),xDialogProp->getPropertyValue(GetPropertyName(BASEPROPERTY_TITLE)));
+ setPropertyValue(GetPropertyName(BASEPROPERTY_HELPTEXT),xDialogProp->getPropertyValue(GetPropertyName(BASEPROPERTY_HELPTEXT)));
+ 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 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 0000000000..ff2c8cd623
--- /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 <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 = getXWeak();
+ 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 0000000000..59dad491c5
--- /dev/null
+++ b/toolkit/source/controls/tkspinbutton.cxx
@@ -0,0 +1,422 @@
+/* -*- 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 <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& getInfoHelper() override;
+
+public:
+ explicit UnoSpinButtonModel( const css::uno::Reference< css::uno::XComponentContext >& i_factory );
+ UnoSpinButtonModel(const UnoSpinButtonModel & rOther) : UnoControlModel(rOther) {}
+
+ 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 0000000000..c696220001
--- /dev/null
+++ b/toolkit/source/controls/tree/treecontrol.cxx
@@ -0,0 +1,524 @@
+/* -*- 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 <helper/property.hxx>
+#include <osl/diagnose.h>
+#include <cppuhelper/implbase1.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::AggImplInheritanceHelper1< 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 = getXWeak();
+ 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 )
+{
+ std::unique_lock g(m_aMutex);
+ ::comphelper::OInterfaceIteratorHelper4 aIt(g, maListeners);
+ g.unlock();
+ 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() )
+ {
+ std::unique_lock g2(m_aMutex);
+ aIt.remove(g2);
+ }
+ }
+ catch( const RuntimeException& )
+ {
+ DISPLAY_EXCEPTION( TreeEditListenerMultiplexer, nodeEditing )
+ }
+ }
+}
+
+void SAL_CALL TreeEditListenerMultiplexer::nodeEdited( const Reference< XTreeNode >& Node, const OUString& NewText )
+{
+ std::unique_lock g(m_aMutex);
+ ::comphelper::OInterfaceIteratorHelper4 aIt(g, maListeners);
+ g.unlock();
+ 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() )
+ {
+ std::unique_lock g2(m_aMutex);
+ aIt.remove(g2);
+ }
+ }
+ 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 0000000000..357afddb0f
--- /dev/null
+++ b/toolkit/source/controls/tree/treecontrol.hxx
@@ -0,0 +1,69 @@
+/* -*- 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& getInfoHelper() override;
+
+public:
+ explicit UnoTreeModel(const css::uno::Reference<css::uno::XComponentContext>& i_factory);
+ UnoTreeModel(const UnoTreeModel& rOther)
+ : UnoControlModel(rOther)
+ {
+ }
+
+ 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 0000000000..c05650f972
--- /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 <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( getXWeak() );
+ EventObject aEvent( xSource );
+ maSelectionListeners.selectionChanged( aEvent );
+}
+
+
+void TreeControlPeer::onRequestChildNodes( const Reference< XTreeNode >& xNode )
+{
+ try
+ {
+ Reference< XInterface > xSource( getXWeak() );
+ TreeExpansionEvent aEvent( xSource, xNode );
+ maTreeExpansionListeners.requestChildNodes( aEvent );
+ }
+ catch( Exception& )
+ {
+ }
+}
+
+
+bool TreeControlPeer::onExpanding( const Reference< XTreeNode >& xNode, bool bExpanding )
+{
+ try
+ {
+ Reference< XInterface > xSource( getXWeak() );
+ 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( getXWeak() );
+ 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 0000000000..4471697fb6
--- /dev/null
+++ b/toolkit/source/controls/tree/treedatamodel.cxx
@@ -0,0 +1,535 @@
+/* -*- 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/implbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <o3tl/safeint.hxx>
+#include <rtl/ref.hxx>
+#include <comphelper/interfacecontainer4.hxx>
+#include <mutex>
+#include <utility>
+
+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::WeakImplHelper< XMutableTreeDataModel, XServiceInfo >
+{
+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:
+ void broadcastImpl( std::unique_lock<std::mutex>& rGuard, broadcast_type eType, const Reference< XTreeNode >& xParentNode, const Reference< XTreeNode >& rNode );
+
+ std::mutex m_aMutex;
+ comphelper::OInterfaceContainerHelper4<XTreeDataModelListener> maTreeDataModelListeners;
+ comphelper::OInterfaceContainerHelper4<XEventListener> maEventListeners;
+ bool mbDisposed;
+ rtl::Reference< MutableTreeNode > mxRootNode;
+};
+
+class MutableTreeNode: public ::cppu::WeakImplHelper< XMutableTreeNode, XServiceInfo >
+{
+ friend class MutableTreeDataModel;
+
+public:
+ MutableTreeNode( rtl::Reference< MutableTreeDataModel > xModel, Any aValue, 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 )
+{
+ std::unique_lock aGuard(m_aMutex);
+ broadcastImpl(aGuard, eType, xParentNode, rNode);
+}
+
+void MutableTreeDataModel::broadcastImpl( std::unique_lock<std::mutex>& rGuard, broadcast_type eType, const Reference< XTreeNode >& xParentNode, const Reference< XTreeNode >& rNode )
+{
+ if( !maTreeDataModelListeners.getLength(rGuard) )
+ return;
+
+ Reference< XInterface > xSource( getXWeak() );
+ const Sequence< Reference< XTreeNode > > aNodes { rNode };
+ TreeDataModelEvent aEvent( xSource, aNodes, xParentNode );
+
+ comphelper::OInterfaceIteratorHelper4 aListIter(rGuard, maTreeDataModelListeners);
+ rGuard.unlock();
+ while(aListIter.hasMoreElements())
+ {
+ XTreeDataModelListener* pListener = aListIter.next().get();
+ 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();
+
+ std::unique_lock aGuard( m_aMutex );
+ if( xNode.get() == mxRootNode.get() )
+ return;
+
+ if( mxRootNode.is() )
+ mxRootNode->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;
+ broadcastImpl( aGuard, structure_changed, xParentNode, mxRootNode );
+}
+
+Reference< XTreeNode > SAL_CALL MutableTreeDataModel::getRoot( )
+{
+ std::unique_lock aGuard( m_aMutex );
+ return mxRootNode;
+}
+
+void SAL_CALL MutableTreeDataModel::addTreeDataModelListener( const Reference< XTreeDataModelListener >& xListener )
+{
+ std::unique_lock aGuard( m_aMutex );
+ maTreeDataModelListeners.addInterface( aGuard, xListener );
+}
+
+void SAL_CALL MutableTreeDataModel::removeTreeDataModelListener( const Reference< XTreeDataModelListener >& xListener )
+{
+ std::unique_lock aGuard( m_aMutex );
+ maTreeDataModelListeners.removeInterface( aGuard, xListener );
+}
+
+void SAL_CALL MutableTreeDataModel::dispose()
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ if( !mbDisposed )
+ {
+ mbDisposed = true;
+ css::lang::EventObject aEvent;
+ aEvent.Source.set( getXWeak() );
+ maTreeDataModelListeners.disposeAndClear( aGuard, aEvent );
+ maEventListeners.disposeAndClear( aGuard, aEvent );
+ }
+}
+
+void SAL_CALL MutableTreeDataModel::addEventListener( const Reference< XEventListener >& xListener )
+{
+ std::unique_lock aGuard( m_aMutex );
+ maEventListeners.addInterface( aGuard, xListener );
+}
+
+void SAL_CALL MutableTreeDataModel::removeEventListener( const Reference< XEventListener >& xListener )
+{
+ std::unique_lock aGuard( m_aMutex );
+ maEventListeners.removeInterface( aGuard, 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( rtl::Reference< MutableTreeDataModel > xModel, Any aValue, bool bChildrenOnDemand )
+: maDisplayValue(std::move( aValue ))
+, mbHasChildrenOnDemand( bChildrenOnDemand )
+, mpParent( nullptr )
+, mxModel(std::move( 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 0000000000..0880455581
--- /dev/null
+++ b/toolkit/source/controls/unocontrol.cxx
@@ -0,0 +1,1588 @@
+/* -*- 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 <comphelper/diagnose_ex.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <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< XVclWindowPeer > UnoControl::ImplGetCompatiblePeer()
+{
+ DBG_ASSERT( !mbCreatingCompatiblePeer, "ImplGetCompatiblePeer - recursive?" );
+
+ mbCreatingCompatiblePeer = true;
+
+ Reference< XVclWindowPeer > xCompatiblePeer = getVclWindowPeer();
+
+ if ( !xCompatiblePeer.is() )
+ {
+ // Create the pair as invisible
+ bool bVis = maComponentInfos.bVisible;
+ if( bVis )
+ maComponentInfos.bVisible = false;
+
+ Reference< XVclWindowPeer > xCurrentPeer = getVclWindowPeer();
+ 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 = getVclWindowPeer();
+ 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< XVclWindowPeer > xPeer;
+ Reference<XComponent> xAccessibleComp;
+ {
+ ::osl::MutexGuard aGuard( GetMutex() );
+ if( mbDisposePeer )
+ {
+ xPeer = mxVclWindowPeer;
+ }
+ 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();
+ mxVclWindowPeer.clear();
+ 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() )
+ {
+ throw RuntimeException("createPeer: no model!", getXWeak());
+ }
+
+ 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
+ Reference<XWindowPeer> xTemp = xToolkit->createWindow( aDescr );
+ mxVclWindowPeer.set(xTemp, UNO_QUERY);
+ assert(mxVclWindowPeer);
+
+ // 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();
+
+ // tdf#150886 if false use the same settings for widgets regardless of theme
+ // for consistency of document across platforms and in pdf/print output
+ // note: tdf#155029 do this before updateFromModel
+ if (xInfo->hasPropertyByName("StandardTheme"))
+ {
+ aVal = xPSet->getPropertyValue("StandardTheme");
+ bool bUseStandardTheme = false;
+ aVal >>= bUseStandardTheme;
+ if (bUseStandardTheme)
+ {
+ VclPtr<vcl::Window> pVclPeer = VCLUnoHelper::GetWindow(getPeer());
+ AllSettings aAllSettings = pVclPeer->GetSettings();
+ StyleSettings aStyleSettings = aAllSettings.GetStyleSettings();
+ aStyleSettings.SetStandardStyles();
+ aAllSettings.SetStyleSettings(aStyleSettings);
+ pVclPeer->SetSettings(aAllSettings);
+ }
+ }
+
+ // 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 mxVclWindowPeer;
+}
+
+Reference< XVclWindowPeer > UnoControl::getVclWindowPeer()
+{
+ ::osl::MutexGuard aGuard( GetMutex() );
+ return mxVclWindowPeer;
+}
+
+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 0000000000..134e7b181b
--- /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 <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 0000000000..1610f36629
--- /dev/null
+++ b/toolkit/source/controls/unocontrolcontainer.cxx
@@ -0,0 +1,823 @@
+/* -*- 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>
+#include <utility>
+
+using namespace ::com::sun::star;
+
+
+
+namespace {
+
+struct UnoControlHolder
+{
+ uno::Reference< awt::XControl > mxControl;
+ OUString msName;
+
+public:
+ UnoControlHolder( OUString aName, uno::Reference< awt::XControl > xControl )
+ : mxControl(std::move( xControl )),
+ msName(std::move( aName ))
+ {
+ }
+
+ 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 > xControlContainer )
+ : mxControlContainer(std::move( 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::XVclWindowPeer >& 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 0000000000..6bfaf4448c
--- /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 <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 0000000000..0868fc2f6a
--- /dev/null
+++ b/toolkit/source/controls/unocontrolmodel.cxx
@@ -0,0 +1,1357 @@
+/* -*- 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 <comphelper/diagnose_ex.hxx>
+#include <tools/debug.hxx>
+#include <tools/long.hxx>
+#include <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()
+ ,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()
+ , 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:
+ case BASEPROPERTY_HIGHLIGHT_COLOR:
+ case BASEPROPERTY_HIGHLIGHT_TEXT_COLOR: 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 = ::comphelper::OPropertySetHelper::queryInterface( rType );
+ return aRet;
+}
+
+// XInterface
+IMPLEMENT_FORWARD_REFCOUNT( UnoControlModel, UnoControlModel_Base )
+
+// css::lang::XTypeProvider
+IMPLEMENT_FORWARD_XTYPEPROVIDER2( UnoControlModel, UnoControlModel_Base, ::comphelper::OPropertySetHelper )
+
+
+uno::Reference< util::XCloneable > UnoControlModel::createClone()
+{
+ rtl::Reference<UnoControlModel> pClone = Clone();
+ return pClone;
+}
+
+// css::lang::XComponent
+void UnoControlModel::dispose( )
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ css::lang::EventObject aEvt;
+ aEvt.Source = static_cast<css::uno::XAggregation*>(static_cast<cppu::OWeakAggObject*>(this));
+ maDisposeListeners.disposeAndClear( aGuard, aEvt );
+
+ // let the property set helper notify our property listeners
+ OPropertySetHelper::disposing(aGuard);
+}
+
+void UnoControlModel::addEventListener( const css::uno::Reference< css::lang::XEventListener >& rxListener )
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ maDisposeListeners.addInterface( rxListener );
+}
+
+void UnoControlModel::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& rxListener )
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ maDisposeListeners.removeInterface( rxListener );
+}
+
+
+// css::beans::XPropertyState
+css::beans::PropertyState UnoControlModel::getPropertyState( const OUString& PropertyName )
+{
+ std::unique_lock aGuard( m_aMutex );
+ return getPropertyStateImpl(aGuard, PropertyName);
+}
+
+css::beans::PropertyState UnoControlModel::getPropertyStateImpl( std::unique_lock<std::mutex>& rGuard, const OUString& PropertyName )
+{
+ sal_uInt16 nPropId = GetPropertyId( PropertyName );
+
+ css::uno::Any aValue = getPropertyValueImpl( rGuard, 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 )
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ sal_Int32 nNames = PropertyNames.getLength();
+
+ css::uno::Sequence< css::beans::PropertyState > aStates( nNames );
+
+ std::transform(PropertyNames.begin(), PropertyNames.end(), aStates.getArray(),
+ [this, &aGuard](const OUString& rName) -> css::beans::PropertyState
+ { return getPropertyStateImpl(aGuard, rName); });
+
+ return aStates;
+}
+
+void UnoControlModel::setPropertyToDefault( const OUString& PropertyName )
+{
+ Any aDefaultValue;
+ {
+ std::unique_lock aGuard( m_aMutex );
+ aDefaultValue = ImplGetDefaultValue( GetPropertyId( PropertyName ) );
+ }
+ setPropertyValue( PropertyName, aDefaultValue );
+}
+
+css::uno::Any UnoControlModel::getPropertyDefault( const OUString& rPropertyName )
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ return ImplGetDefaultValue( GetPropertyId( rPropertyName ) );
+}
+
+
+// css::io::XPersistObjec
+OUString UnoControlModel::getServiceName( )
+{
+ OSL_FAIL( "ServiceName of UnoControlModel ?!" );
+ return OUString();
+}
+
+void UnoControlModel::write( const css::uno::Reference< css::io::XObjectOutputStream >& OutStream )
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ 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 )
+ && ( getPropertyStateImpl( aGuard, 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 )
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ 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);
+ auto it = maData.find( BASEPROPERTY_FONTDESCRIPTOR );
+ if ( it != maData.end() ) // due to defaults...
+ it->second >>= *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);
+ auto it = maData.find(BASEPROPERTY_FONTDESCRIPTOR);
+ if ( it != maData.end() ) // due to defaults...
+ it->second >>= *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);
+ auto it = maData.find(BASEPROPERTY_FONTDESCRIPTOR);
+ if ( it != maData.end() ) // due to defaults...
+ it->second >>= *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
+ {
+ setPropertyValuesImpl( aGuard, aProps, aValues );
+ }
+ catch ( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit.controls");
+ }
+
+ if ( pFD )
+ {
+ css::uno::Any aValue;
+ aValue <<= *pFD;
+ setFastPropertyValueImpl( aGuard, 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" };
+}
+
+bool UnoControlModel::convertFastPropertyValue( std::unique_lock<std::mutex>& rGuard, Any & rConvertedValue, Any & rOldValue, sal_Int32 nPropId, const Any& rValue )
+{
+ 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( rGuard, rOldValue, nPropId );
+ return !CompareProperties( rConvertedValue, rOldValue );
+}
+
+void UnoControlModel::setFastPropertyValue_NoBroadcast( std::unique_lock<std::mutex>& /*rGuard*/, 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( std::unique_lock<std::mutex>& /*rGuard*/, css::uno::Any& rValue, sal_Int32 nPropId ) const
+{
+ 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 ) )
+ {
+ const auto iter = maData.find( BASEPROPERTY_FONTDESCRIPTOR );
+ assert(iter != maData.end());
+ pProp = &(iter->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::XFastPropertySet
+void UnoControlModel::setFastPropertyValueImpl( std::unique_lock<std::mutex>& rGuard, sal_Int32 nPropId, const css::uno::Any& rValue )
+{
+ if ( ( nPropId >= BASEPROPERTY_FONTDESCRIPTORPART_START ) && ( nPropId <= BASEPROPERTY_FONTDESCRIPTORPART_END ) )
+ {
+ Any aOldSingleValue;
+ getFastPropertyValue( rGuard, 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( rGuard, aNewSingleValue, BASEPROPERTY_FONTDESCRIPTORPART_START );
+
+ setFastPropertyValues( rGuard, 1, &nDescriptorId, &aNewValue, 1 );
+ fire( rGuard, &nPropId, &aNewSingleValue, &aOldSingleValue, 1, false );
+ }
+ else
+ setFastPropertyValues( rGuard, 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 )
+{
+ std::unique_lock aGuard( m_aMutex );
+ setPropertyValuesImpl(aGuard, rPropertyNames, Values);
+}
+
+void UnoControlModel::setPropertyValuesImpl( std::unique_lock<std::mutex>& rGuard, const css::uno::Sequence< OUString >& rPropertyNames, const css::uno::Sequence< css::uno::Any >& Values )
+{
+ sal_Int32 nProps = rPropertyNames.getLength();
+ if (nProps != Values.getLength())
+ throw css::lang::IllegalArgumentException("lengths do not match",
+ getXWeak(), -1);
+
+// 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 );
+ setFastPropertyValues( rGuard, nProps, pHandles, pValues, nValidHandles );
+ }
+
+ // 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( rGuard, 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 0000000000..d9bc55f8cb
--- /dev/null
+++ b/toolkit/source/controls/unocontrols.cxx
@@ -0,0 +1,4757 @@
+/* -*- 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 <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 <comphelper/diagnose_ex.hxx>
+
+#include <algorithm>
+
+#include <helper/imagealign.hxx>
+#include <helper/unopropertyarrayhelper.hxx>
+#include <utility>
+
+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 GraphicControlModel::setFastPropertyValue_NoBroadcast( std::unique_lock<std::mutex>& rGuard, sal_Int32 nHandle, const css::uno::Any& rValue )
+{
+ UnoControlModel::setFastPropertyValue_NoBroadcast( rGuard, 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( rGuard, BASEPROPERTY_GRAPHIC, uno::Any( ImageHelper::getGraphicFromURL_nothrow( sImageURL ) ) );
+ mbAdjustingGraphic = false;
+ }
+ break;
+
+ case BASEPROPERTY_GRAPHIC:
+ if ( !mbAdjustingGraphic && ImplHasProperty( BASEPROPERTY_IMAGEURL ) )
+ {
+ mbAdjustingGraphic = true;
+ setDependentFastPropertyValue( rGuard, 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( rGuard, 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( rGuard, 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 );
+ {
+ std::unique_lock aGuard(m_aMutex);
+ setFastPropertyValue_NoBroadcast( aGuard, 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 = getXWeak();
+ 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 UnoControlImageControlModel::setFastPropertyValue_NoBroadcast( std::unique_lock<std::mutex>& rGuard, sal_Int32 _nHandle, const css::uno::Any& _rValue )
+{
+ GraphicControlModel::setFastPropertyValue_NoBroadcast( rGuard, _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( rGuard, 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( rGuard, 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 = getXWeak();
+ 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 = getXWeak();
+ 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 = getXWeak();
+ 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 = getXWeak();
+ 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( OUString i_ItemText )
+ :ItemText(std::move( i_ItemText ))
+ {
+ }
+};
+
+}
+
+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 ) )
+{
+ 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_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 UnoControlListBoxModel::setFastPropertyValue_NoBroadcast( std::unique_lock<std::mutex>& rGuard, sal_Int32 nHandle, const uno::Any& rValue )
+{
+ UnoControlModel::setFastPropertyValue_NoBroadcast( rGuard, nHandle, rValue );
+
+ if ( nHandle != BASEPROPERTY_STRINGITEMLIST )
+ return;
+
+ // reset selection
+ uno::Sequence<sal_Int16> aSeq;
+ setDependentFastPropertyValue( rGuard, 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( rGuard, 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( rGuard, &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()
+{
+ std::unique_lock aGuard( m_aMutex );
+ return m_xData->getItemCount();
+}
+
+
+void SAL_CALL UnoControlListBoxModel::insertItem( ::sal_Int32 i_nPosition, const OUString& i_rItemText, const OUString& i_rItemImageURL )
+{
+ std::unique_lock aGuard( m_aMutex );
+ // SYNCHRONIZED ----->
+ ListItem& rItem( m_xData->insertItem( i_nPosition ) );
+ rItem.ItemText = i_rItemText;
+ rItem.ItemImageURL = i_rItemImageURL;
+
+ impl_handleInsert( aGuard, i_nPosition, i_rItemText, i_rItemImageURL );
+ // <----- SYNCHRONIZED
+}
+
+
+void SAL_CALL UnoControlListBoxModel::insertItemText( ::sal_Int32 i_nPosition, const OUString& i_rItemText )
+{
+ std::unique_lock aGuard( m_aMutex );
+ // SYNCHRONIZED ----->
+ ListItem& rItem( m_xData->insertItem( i_nPosition ) );
+ rItem.ItemText = i_rItemText;
+
+ impl_handleInsert( aGuard, i_nPosition, i_rItemText, ::std::optional< OUString >() );
+ // <----- SYNCHRONIZED
+}
+
+
+void SAL_CALL UnoControlListBoxModel::insertItemImage( ::sal_Int32 i_nPosition, const OUString& i_rItemImageURL )
+{
+ std::unique_lock aGuard( m_aMutex );
+ // SYNCHRONIZED ----->
+ ListItem& rItem( m_xData->insertItem( i_nPosition ) );
+ rItem.ItemImageURL = i_rItemImageURL;
+
+ impl_handleInsert( aGuard, i_nPosition, ::std::optional< OUString >(), i_rItemImageURL );
+ // <----- SYNCHRONIZED
+}
+
+
+void SAL_CALL UnoControlListBoxModel::removeItem( ::sal_Int32 i_nPosition )
+{
+ std::unique_lock aGuard( m_aMutex );
+ // SYNCHRONIZED ----->
+ m_xData->removeItem( i_nPosition );
+
+ impl_handleRemove( i_nPosition, aGuard );
+ // <----- SYNCHRONIZED
+}
+
+
+void SAL_CALL UnoControlListBoxModel::removeAllItems( )
+{
+ std::unique_lock aGuard( m_aMutex );
+ // SYNCHRONIZED ----->
+ m_xData->removeAllItems();
+
+ impl_handleRemove( -1, aGuard );
+ // <----- SYNCHRONIZED
+}
+
+
+void SAL_CALL UnoControlListBoxModel::setItemText( ::sal_Int32 i_nPosition, const OUString& i_rItemText )
+{
+ std::unique_lock aGuard( m_aMutex );
+ // 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 )
+{
+ std::unique_lock aGuard( m_aMutex );
+ // 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 )
+{
+ std::unique_lock aGuard( m_aMutex );
+ // 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 )
+{
+ std::unique_lock aGuard( m_aMutex );
+ ListItem& rItem( m_xData->getItem( i_nPosition ) );
+ rItem.ItemData = i_rDataValue;
+}
+
+
+OUString SAL_CALL UnoControlListBoxModel::getItemText( ::sal_Int32 i_nPosition )
+{
+ std::unique_lock aGuard( m_aMutex );
+ const ListItem& rItem( m_xData->getItem( i_nPosition ) );
+ return rItem.ItemText;
+}
+
+
+OUString SAL_CALL UnoControlListBoxModel::getItemImage( ::sal_Int32 i_nPosition )
+{
+ std::unique_lock aGuard( m_aMutex );
+ const ListItem& rItem( m_xData->getItem( i_nPosition ) );
+ return rItem.ItemImageURL;
+}
+
+
+beans::Pair< OUString, OUString > SAL_CALL UnoControlListBoxModel::getItemTextAndImage( ::sal_Int32 i_nPosition )
+{
+ std::unique_lock aGuard( m_aMutex );
+ 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 )
+{
+ std::unique_lock aGuard( m_aMutex );
+ const ListItem& rItem( m_xData->getItem( i_nPosition ) );
+ return rItem.ItemData;
+}
+
+
+Sequence< beans::Pair< OUString, OUString > > SAL_CALL UnoControlListBoxModel::getAllItems( )
+{
+ std::unique_lock aGuard( m_aMutex );
+ return m_xData->getAllItems();
+}
+
+
+void SAL_CALL UnoControlListBoxModel::addItemListListener( const uno::Reference< awt::XItemListListener >& i_Listener )
+{
+ std::unique_lock aGuard( m_aMutex );
+ if ( i_Listener.is() )
+ m_aItemListListeners.addInterface( aGuard, i_Listener );
+}
+
+
+void SAL_CALL UnoControlListBoxModel::removeItemListListener( const uno::Reference< awt::XItemListListener >& i_Listener )
+{
+ std::unique_lock aGuard( m_aMutex );
+ if ( i_Listener.is() )
+ m_aItemListListeners.removeInterface( aGuard, i_Listener );
+}
+
+
+void UnoControlListBoxModel::impl_getStringItemList( std::unique_lock<std::mutex>& rGuard, ::std::vector< OUString >& o_rStringItems ) const
+{
+ Sequence< OUString > aStringItemList;
+ Any aPropValue;
+ getFastPropertyValue( rGuard, aPropValue, BASEPROPERTY_STRINGITEMLIST );
+ OSL_VERIFY( aPropValue >>= aStringItemList );
+
+ comphelper::sequenceToContainer(o_rStringItems, aStringItemList);
+}
+
+
+void UnoControlListBoxModel::impl_setStringItemList( std::unique_lock<std::mutex>& rGuard, const ::std::vector< OUString >& i_rStringItems )
+{
+ Sequence< OUString > aStringItems( comphelper::containerToSequence(i_rStringItems) );
+ m_xData->m_bSettingLegacyProperty = true;
+ try
+ {
+ setFastPropertyValueImpl( rGuard, BASEPROPERTY_STRINGITEMLIST, uno::Any( aStringItems ) );
+ }
+ catch( const Exception& )
+ {
+ m_xData->m_bSettingLegacyProperty = false;
+ throw;
+ }
+ m_xData->m_bSettingLegacyProperty = false;
+}
+
+
+void UnoControlListBoxModel::impl_handleInsert( std::unique_lock<std::mutex>& rGuard,
+ const sal_Int32 i_nItemPosition,
+ const ::std::optional< OUString >& i_rItemText,
+ const ::std::optional< OUString >& i_rItemImageURL )
+{
+ // SYNCHRONIZED ----->
+ // sync with legacy StringItemList property
+ ::std::vector< OUString > aStringItems;
+ impl_getStringItemList( rGuard, 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 );
+ }
+
+ impl_setStringItemList( rGuard, aStringItems );
+
+ // notify ItemListListeners
+ impl_notifyItemListEvent( rGuard, i_nItemPosition, i_rItemText, i_rItemImageURL, &XItemListListener::listItemInserted );
+}
+
+
+void UnoControlListBoxModel::impl_handleRemove(
+ const sal_Int32 i_nItemPosition,
+ std::unique_lock<std::mutex>& i_rClearBeforeNotify )
+{
+ // SYNCHRONIZED ----->
+ const bool bAllItems = ( i_nItemPosition < 0 );
+ // sync with legacy StringItemList property
+ ::std::vector< OUString > aStringItems;
+ impl_getStringItemList( i_rClearBeforeNotify, 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);
+ }
+
+ impl_setStringItemList( i_rClearBeforeNotify, aStringItems );
+
+ // notify ItemListListeners
+ if ( bAllItems )
+ {
+ EventObject aEvent( *this );
+ m_aItemListListeners.notifyEach( i_rClearBeforeNotify, &XItemListListener::allItemsRemoved, aEvent );
+ }
+ else
+ {
+ impl_notifyItemListEvent( i_rClearBeforeNotify, 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,
+ std::unique_lock<std::mutex>& i_rClearBeforeNotify )
+{
+ // SYNCHRONIZED ----->
+ if ( !!i_rItemText )
+ {
+ // sync with legacy StringItemList property
+ ::std::vector< OUString > aStringItems;
+ impl_getStringItemList( i_rClearBeforeNotify, 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;
+ }
+
+ impl_setStringItemList( i_rClearBeforeNotify, aStringItems );
+ }
+
+ // notify ItemListListeners
+ impl_notifyItemListEvent( i_rClearBeforeNotify, i_nItemPosition, i_rItemText, i_rItemImageURL, &XItemListListener::listItemModified );
+}
+
+
+void UnoControlListBoxModel::impl_notifyItemListEvent(
+ std::unique_lock<std::mutex>& rGuard,
+ 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( rGuard, 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 = getXWeak();
+ 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 UnoControlComboBoxModel::setFastPropertyValue_NoBroadcast( std::unique_lock<std::mutex>& rGuard, sal_Int32 nHandle, const uno::Any& rValue )
+{
+ UnoControlModel::setFastPropertyValue_NoBroadcast( rGuard, 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( rGuard, 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( rGuard, &XItemListListener::itemListChanged, aEvent );
+}
+
+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 = getXWeak();
+ 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: */
diff --git a/toolkit/source/controls/unocontroltablemodel.cxx b/toolkit/source/controls/unocontroltablemodel.cxx
new file mode 100644
index 0000000000..50f6cac3cf
--- /dev/null
+++ b/toolkit/source/controls/unocontroltablemodel.cxx
@@ -0,0 +1,834 @@
+/* -*- 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 "unocontroltablemodel.hxx"
+#include "unogridcolumnfacade.hxx"
+
+#include <controls/table/defaultinputhandler.hxx>
+#include <controls/table/gridtablerenderer.hxx>
+
+#include <com/sun/star/awt/grid/XSortableGridData.hpp>
+#include <com/sun/star/util/Color.hpp>
+#include <o3tl/safeint.hxx>
+#include <sal/log.hxx>
+#include <cppuhelper/weakref.hxx>
+#include <tools/debug.hxx>
+#include <comphelper/diagnose_ex.hxx>
+
+
+namespace svt::table
+{
+
+
+ using css::uno::Reference;
+ using css::uno::Sequence;
+ using css::uno::UNO_QUERY_THROW;
+ using css::uno::UNO_QUERY;
+ using css::awt::grid::XGridColumn;
+ using css::uno::Exception;
+ using css::awt::grid::XGridDataModel;
+ using css::awt::grid::XGridColumnModel;
+ using css::uno::Any;
+ using css::style::VerticalAlignment_TOP;
+ using css::style::VerticalAlignment;
+ using css::awt::grid::GridDataEvent;
+ using css::awt::grid::XSortableGridData;
+ using css::beans::Pair;
+
+
+ //= UnoControlTableModel
+#define DBG_CHECK_ME() \
+ DBG_TESTSOLARMUTEX(); \
+
+ UnoControlTableModel::UnoControlTableModel()
+ :aColumns ( )
+ ,bHasColumnHeaders ( true )
+ ,bHasRowHeaders ( false )
+ ,eVScrollMode ( ScrollbarShowNever )
+ ,eHScrollMode ( ScrollbarShowNever )
+ ,pRenderer ( )
+ ,pInputHandler ( )
+ ,nRowHeight ( 10 )
+ ,nColumnHeaderHeight ( 10 )
+ ,nRowHeaderWidth ( 10 )
+ ,m_aGridLineColor ( )
+ ,m_aHeaderBackgroundColor ( )
+ ,m_aHeaderTextColor ( )
+ ,m_aActiveSelectionBackColor ( )
+ ,m_aInactiveSelectionBackColor ( )
+ ,m_aActiveSelectionTextColor ( )
+ ,m_aInactiveSelectionTextColor ( )
+ ,m_aTextColor ( )
+ ,m_aTextLineColor ( )
+ ,m_aRowColors ( )
+ ,m_eVerticalAlign ( VerticalAlignment_TOP )
+ ,bEnabled ( true )
+ {
+ pRenderer = std::make_shared<GridTableRenderer>( *this );
+ pInputHandler = std::make_shared<DefaultInputHandler>();
+ }
+
+
+ UnoControlTableModel::~UnoControlTableModel()
+ {
+ }
+
+
+ TableSize UnoControlTableModel::getColumnCount() const
+ {
+ DBG_CHECK_ME();
+ return static_cast<TableSize>(aColumns.size());
+ }
+
+
+ TableSize UnoControlTableModel::getRowCount() const
+ {
+ DBG_CHECK_ME();
+
+ TableSize nRowCount = 0;
+ try
+ {
+ Reference< XGridDataModel > const xDataModel( m_aDataModel );
+ ENSURE_OR_THROW( xDataModel.is(), "no data model anymore!" );
+ nRowCount = xDataModel->getRowCount();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.uno");
+ }
+ return nRowCount;
+ }
+
+
+ bool UnoControlTableModel::hasColumnHeaders() const
+ {
+ DBG_CHECK_ME();
+ return bHasColumnHeaders;
+ }
+
+
+ bool UnoControlTableModel::hasRowHeaders() const
+ {
+ DBG_CHECK_ME();
+ return bHasRowHeaders;
+ }
+
+
+ void UnoControlTableModel::setRowHeaders(bool _bRowHeaders)
+ {
+ DBG_CHECK_ME();
+ if ( bHasRowHeaders == _bRowHeaders )
+ return;
+
+ bHasRowHeaders = _bRowHeaders;
+ impl_notifyTableMetricsChanged();
+ }
+
+
+ void UnoControlTableModel::setColumnHeaders(bool _bColumnHeaders)
+ {
+ DBG_CHECK_ME();
+ if ( bHasColumnHeaders == _bColumnHeaders )
+ return;
+
+ bHasColumnHeaders = _bColumnHeaders;
+ impl_notifyTableMetricsChanged();
+ }
+
+
+ PColumnModel UnoControlTableModel::getColumnModel( ColPos column )
+ {
+ DBG_CHECK_ME();
+ ENSURE_OR_RETURN( ( column >= 0 ) && ( column < getColumnCount() ),
+ "DefaultTableModel::getColumnModel: invalid index!", PColumnModel() );
+ return aColumns[ column ];
+ }
+
+
+ void UnoControlTableModel::appendColumn( Reference< XGridColumn > const & i_column )
+ {
+ DBG_CHECK_ME();
+ insertColumn( aColumns.size(), i_column );
+ }
+
+
+ void UnoControlTableModel::insertColumn( ColPos const i_position, Reference< XGridColumn > const & i_column )
+ {
+ DBG_CHECK_ME();
+ ENSURE_OR_RETURN_VOID( ( i_position >= 0 ) && ( o3tl::make_unsigned( i_position ) <= aColumns.size() ),
+ "UnoControlTableModel::insertColumn: illegal position!" );
+
+ const PColumnModel pColumn = std::make_shared<UnoGridColumnFacade>( *this, i_column );
+ aColumns.insert( aColumns.begin() + i_position, pColumn );
+
+ // notify listeners
+ ModellListeners aListeners( m_aListeners );
+ for (auto const& listener : aListeners)
+ {
+ listener->columnInserted();
+ }
+ }
+
+
+ void UnoControlTableModel::removeColumn( ColPos const i_position )
+ {
+ DBG_CHECK_ME();
+ ENSURE_OR_RETURN_VOID( ( i_position >= 0 ) && ( o3tl::make_unsigned( i_position ) <= aColumns.size() ),
+ "UnoControlTableModel::removeColumn: illegal position!" );
+
+ // remove the column
+ ColumnModels::iterator pos = aColumns.begin() + i_position;
+ const PColumnModel pColumn = *pos;
+ aColumns.erase( pos );
+
+ // notify listeners
+ ModellListeners aListeners( m_aListeners );
+ for (auto const& listener : aListeners)
+ {
+ listener->columnRemoved();
+ }
+
+ // dispose the column
+ UnoGridColumnFacade* pColumnImpl = dynamic_cast< UnoGridColumnFacade* >( pColumn.get() );
+ OSL_ENSURE( pColumnImpl != nullptr, "UnoControlTableModel::removeColumn: illegal column implementation!" );
+ if ( pColumnImpl )
+ pColumnImpl->dispose();
+ }
+
+
+ void UnoControlTableModel::removeAllColumns()
+ {
+ DBG_CHECK_ME();
+ if ( aColumns.empty() )
+ return;
+
+ // dispose the column instances
+ for (auto const& col : aColumns)
+ {
+ UnoGridColumnFacade* pColumn = dynamic_cast< UnoGridColumnFacade* >( col.get() );
+ if ( !pColumn )
+ {
+ SAL_WARN( "svtools.uno", "UnoControlTableModel::removeAllColumns: illegal column implementation!" );
+ continue;
+ }
+
+ pColumn->dispose();
+ }
+ aColumns.clear();
+
+ // notify listeners
+ ModellListeners aListeners( m_aListeners );
+ for (auto const& listener : aListeners)
+ {
+ listener->allColumnsRemoved();
+ }
+ }
+
+
+ void UnoControlTableModel::impl_notifyTableMetricsChanged() const
+ {
+ ModellListeners aListeners( m_aListeners );
+ for (auto const& listener : aListeners)
+ {
+ listener->tableMetricsChanged();
+ }
+ }
+
+
+ PTableRenderer UnoControlTableModel::getRenderer() const
+ {
+ DBG_CHECK_ME();
+ return pRenderer;
+ }
+
+
+ PTableInputHandler UnoControlTableModel::getInputHandler() const
+ {
+ DBG_CHECK_ME();
+ return pInputHandler;
+ }
+
+
+ TableMetrics UnoControlTableModel::getRowHeight() const
+ {
+ DBG_CHECK_ME();
+ return nRowHeight;
+ }
+
+
+ void UnoControlTableModel::setRowHeight(TableMetrics _nRowHeight)
+ {
+ DBG_CHECK_ME();
+ if ( nRowHeight == _nRowHeight )
+ return;
+
+ nRowHeight = _nRowHeight;
+ impl_notifyTableMetricsChanged();
+ }
+
+
+ TableMetrics UnoControlTableModel::getColumnHeaderHeight() const
+ {
+ DBG_CHECK_ME();
+ DBG_ASSERT( hasColumnHeaders(), "DefaultTableModel::getColumnHeaderHeight: invalid call!" );
+ return nColumnHeaderHeight;
+ }
+
+
+ TableMetrics UnoControlTableModel::getRowHeaderWidth() const
+ {
+ DBG_CHECK_ME();
+ DBG_ASSERT( hasRowHeaders(), "DefaultTableModel::getRowHeaderWidth: invalid call!" );
+ return nRowHeaderWidth;
+ }
+
+ void UnoControlTableModel::setColumnHeaderHeight(TableMetrics _nHeight)
+ {
+ DBG_CHECK_ME();
+ if ( nColumnHeaderHeight == _nHeight )
+ return;
+
+ nColumnHeaderHeight = _nHeight;
+ impl_notifyTableMetricsChanged();
+ }
+
+
+ void UnoControlTableModel::setRowHeaderWidth(TableMetrics _nWidth)
+ {
+ DBG_CHECK_ME();
+ if ( nRowHeaderWidth == _nWidth )
+ return;
+
+ nRowHeaderWidth = _nWidth;
+ impl_notifyTableMetricsChanged();
+ }
+
+
+ ScrollbarVisibility UnoControlTableModel::getVerticalScrollbarVisibility() const
+ {
+ DBG_CHECK_ME();
+ return eVScrollMode;
+ }
+
+
+ ScrollbarVisibility UnoControlTableModel::getHorizontalScrollbarVisibility() const
+ {
+ DBG_CHECK_ME();
+ return eHScrollMode;
+ }
+
+
+ void UnoControlTableModel::addTableModelListener( const PTableModelListener& i_listener )
+ {
+ DBG_CHECK_ME();
+ ENSURE_OR_RETURN_VOID( !!i_listener, "illegal NULL listener" );
+ m_aListeners.push_back( i_listener );
+ }
+
+
+ void UnoControlTableModel::removeTableModelListener( const PTableModelListener& i_listener )
+ {
+ DBG_CHECK_ME();
+ auto lookup = std::find(m_aListeners.begin(), m_aListeners.end(), i_listener);
+ if (lookup != m_aListeners.end())
+ {
+ m_aListeners.erase( lookup );
+ return;
+ }
+ OSL_ENSURE( false, "UnoControlTableModel::removeTableModelListener: listener is not registered - sure you're doing the right thing here?" );
+ }
+
+
+ void UnoControlTableModel::setVerticalScrollbarVisibility( ScrollbarVisibility const i_visibility )
+ {
+ DBG_CHECK_ME();
+ eVScrollMode = i_visibility;
+ }
+
+
+ void UnoControlTableModel::setHorizontalScrollbarVisibility( ScrollbarVisibility const i_visibility )
+ {
+ DBG_CHECK_ME();
+ eHScrollMode = i_visibility;
+ }
+
+
+ void UnoControlTableModel::setDataModel( Reference< XGridDataModel > const & i_gridDataModel )
+ {
+ DBG_CHECK_ME();
+ m_aDataModel = i_gridDataModel;
+ // TODO: register as listener, so we're notified of row/data changes, and can multiplex them to our
+ // own listeners
+ }
+
+
+ Reference< XGridDataModel > UnoControlTableModel::getDataModel() const
+ {
+ Reference< XGridDataModel > const xDataModel( m_aDataModel );
+ return xDataModel;
+ }
+
+
+ bool UnoControlTableModel::hasDataModel() const
+ {
+ return getDataModel().is();
+ }
+
+
+ void UnoControlTableModel::setColumnModel( Reference< XGridColumnModel > const & i_gridColumnModel )
+ {
+ DBG_CHECK_ME();
+ m_aColumnModel = i_gridColumnModel;
+ }
+
+
+ Reference< XGridColumnModel > UnoControlTableModel::getColumnModel() const
+ {
+ Reference< XGridColumnModel > const xColumnModel( m_aColumnModel );
+ return xColumnModel;
+ }
+
+
+ bool UnoControlTableModel::hasColumnModel() const
+ {
+ return getColumnModel().is();
+ }
+
+
+ void UnoControlTableModel::getCellContent( ColPos const i_col, RowPos const i_row, Any& o_cellContent )
+ {
+ DBG_CHECK_ME();
+
+ o_cellContent.clear();
+ try
+ {
+ Reference< XGridDataModel > const xDataModel( m_aDataModel );
+ ENSURE_OR_RETURN_VOID( xDataModel.is(), "UnoControlTableModel::getCellContent: no data model anymore!" );
+
+ PColumnModel const pColumn = getColumnModel( i_col );
+ UnoGridColumnFacade* pColumnImpl = dynamic_cast< UnoGridColumnFacade* >( pColumn.get() );
+ ENSURE_OR_RETURN_VOID( pColumnImpl != nullptr, "UnoControlTableModel::getCellContent: no (valid) column at this position!" );
+ sal_Int32 const nDataColumnIndex = pColumnImpl->getDataColumnIndex() >= 0 ? pColumnImpl->getDataColumnIndex() : i_col;
+
+ if ( nDataColumnIndex >= xDataModel->getColumnCount() )
+ {
+ // this is allowed, in case the column model has been dynamically extended, but the data model does
+ // not (yet?) know about it.
+ // So, handle it gracefully.
+ #if OSL_DEBUG_LEVEL > 0
+ Reference< XGridColumnModel > const xColumnModel( m_aColumnModel );
+ OSL_ENSURE( xColumnModel.is() && i_col < xColumnModel->getColumnCount(),
+ "UnoControlTableModel::getCellContent: request a column's value which the ColumnModel doesn't know about!" );
+ #endif
+ }
+ else
+ {
+ o_cellContent = xDataModel->getCellData( nDataColumnIndex, i_row );
+ }
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.uno");
+ }
+ }
+
+
+ void UnoControlTableModel::getCellToolTip( ColPos const i_col, RowPos const i_row, Any& o_cellToolTip )
+ {
+ DBG_CHECK_ME();
+ try
+ {
+ Reference< XGridDataModel > const xDataModel( m_aDataModel );
+ ENSURE_OR_THROW( xDataModel.is(), "no data model anymore!" );
+
+ o_cellToolTip = xDataModel->getCellToolTip( i_col, i_row );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.uno");
+ }
+ }
+
+
+ Any UnoControlTableModel::getRowHeading( RowPos const i_rowPos ) const
+ {
+ DBG_CHECK_ME();
+
+ Any aRowHeading;
+
+ Reference< XGridDataModel > const xDataModel( m_aDataModel );
+ ENSURE_OR_RETURN( xDataModel.is(), "UnoControlTableModel::getRowHeading: no data model anymore!", aRowHeading );
+
+ try
+ {
+ aRowHeading = xDataModel->getRowHeading( i_rowPos );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.uno");
+ }
+ return aRowHeading;
+ }
+
+
+ namespace
+ {
+ void lcl_setColor( Any const & i_color, ::std::optional< ::Color > & o_convertedColor )
+ {
+ if ( !i_color.hasValue() )
+ o_convertedColor.reset();
+ else
+ {
+ Color nColor = COL_TRANSPARENT;
+ if ( i_color >>= nColor )
+ {
+ o_convertedColor = nColor;
+ }
+ else
+ {
+ OSL_ENSURE( false, "lcl_setColor: could not extract color value!" );
+ }
+ }
+ }
+ }
+
+
+ ::std::optional< ::Color > UnoControlTableModel::getLineColor() const
+ {
+ DBG_CHECK_ME();
+ return m_aGridLineColor;
+ }
+
+
+ void UnoControlTableModel::setLineColor( Any const & i_color )
+ {
+ DBG_CHECK_ME();
+ lcl_setColor( i_color, m_aGridLineColor );
+ }
+
+
+ ::std::optional< ::Color > UnoControlTableModel::getHeaderBackgroundColor() const
+ {
+ DBG_CHECK_ME();
+ return m_aHeaderBackgroundColor;
+ }
+
+
+ void UnoControlTableModel::setHeaderBackgroundColor( Any const & i_color )
+ {
+ DBG_CHECK_ME();
+ lcl_setColor( i_color, m_aHeaderBackgroundColor );
+ }
+
+
+ ::std::optional< ::Color > UnoControlTableModel::getHeaderTextColor() const
+ {
+ DBG_CHECK_ME();
+ return m_aHeaderTextColor;
+ }
+
+
+ ::std::optional< ::Color > UnoControlTableModel::getActiveSelectionBackColor() const
+ {
+ DBG_CHECK_ME();
+ return m_aActiveSelectionBackColor;
+ }
+
+
+ ::std::optional< ::Color > UnoControlTableModel::getInactiveSelectionBackColor() const
+ {
+ DBG_CHECK_ME();
+ return m_aInactiveSelectionBackColor;
+ }
+
+
+ ::std::optional< ::Color > UnoControlTableModel::getActiveSelectionTextColor() const
+ {
+ DBG_CHECK_ME();
+ return m_aActiveSelectionTextColor;
+ }
+
+
+ ::std::optional< ::Color > UnoControlTableModel::getInactiveSelectionTextColor() const
+ {
+ DBG_CHECK_ME();
+ return m_aInactiveSelectionTextColor;
+ }
+
+
+ void UnoControlTableModel::setHeaderTextColor( Any const & i_color )
+ {
+ DBG_CHECK_ME();
+ lcl_setColor( i_color, m_aHeaderTextColor );
+ }
+
+
+ void UnoControlTableModel::setActiveSelectionBackColor( Any const & i_color )
+ {
+ DBG_CHECK_ME();
+ lcl_setColor( i_color, m_aActiveSelectionBackColor );
+ }
+
+
+ void UnoControlTableModel::setInactiveSelectionBackColor( Any const & i_color )
+ {
+ DBG_CHECK_ME();
+ lcl_setColor( i_color, m_aInactiveSelectionBackColor );
+ }
+
+
+ void UnoControlTableModel::setActiveSelectionTextColor( Any const & i_color )
+ {
+ DBG_CHECK_ME();
+ lcl_setColor( i_color, m_aActiveSelectionTextColor );
+ }
+
+
+ void UnoControlTableModel::setInactiveSelectionTextColor( Any const & i_color )
+ {
+ DBG_CHECK_ME();
+ lcl_setColor( i_color, m_aInactiveSelectionTextColor );
+ }
+
+
+ ::std::optional< ::Color > UnoControlTableModel::getTextColor() const
+ {
+ DBG_CHECK_ME();
+ return m_aTextColor;
+ }
+
+
+ void UnoControlTableModel::setTextColor( Any const & i_color )
+ {
+ DBG_CHECK_ME();
+ lcl_setColor( i_color, m_aTextColor );
+ }
+
+
+ ::std::optional< ::Color > UnoControlTableModel::getTextLineColor() const
+ {
+ DBG_CHECK_ME();
+ return m_aTextColor;
+ }
+
+
+ void UnoControlTableModel::setTextLineColor( Any const & i_color )
+ {
+ DBG_CHECK_ME();
+ lcl_setColor( i_color, m_aTextLineColor );
+ }
+
+
+ ::std::optional< ::std::vector< ::Color > > UnoControlTableModel::getRowBackgroundColors() const
+ {
+ DBG_CHECK_ME();
+ return m_aRowColors;
+ }
+
+
+ void UnoControlTableModel::setRowBackgroundColors( css::uno::Any const & i_APIValue )
+ {
+ DBG_CHECK_ME();
+ Sequence< css::util::Color > aAPIColors;
+ if ( !( i_APIValue >>= aAPIColors ) )
+ m_aRowColors.reset();
+ else
+ {
+ ::std::vector< ::Color > aColors( aAPIColors.getLength() );
+ std::transform(std::cbegin(aAPIColors), std::cend(aAPIColors), aColors.begin(),
+ [](const css::util::Color& rAPIColor) -> ::Color { return Color(ColorTransparency, rAPIColor); });
+ m_aRowColors = aColors;
+ }
+ }
+
+
+ VerticalAlignment UnoControlTableModel::getVerticalAlign() const
+ {
+ DBG_CHECK_ME();
+ return m_eVerticalAlign;
+ }
+
+
+ void UnoControlTableModel::setVerticalAlign( VerticalAlignment _xAlign )
+ {
+ DBG_CHECK_ME();
+ m_eVerticalAlign = _xAlign;
+ }
+
+
+ ColPos UnoControlTableModel::getColumnPos( UnoGridColumnFacade const & i_column ) const
+ {
+ DBG_CHECK_ME();
+ ColPos nPos = 0;
+ for (auto const& col : aColumns)
+ {
+ if ( &i_column == col.get() )
+ return nPos;
+ ++nPos;
+ }
+ OSL_ENSURE( false, "UnoControlTableModel::getColumnPos: column not found!" );
+ return COL_INVALID;
+ }
+
+
+ ITableDataSort* UnoControlTableModel::getSortAdapter()
+ {
+ DBG_CHECK_ME();
+
+ Reference< XSortableGridData > const xSortAccess( getDataModel(), UNO_QUERY );
+ if ( xSortAccess.is() )
+ return this;
+ return nullptr;
+ }
+
+
+ bool UnoControlTableModel::isEnabled() const
+ {
+ DBG_CHECK_ME();
+ return bEnabled;
+ }
+
+
+ void UnoControlTableModel::setEnabled( bool _bEnabled )
+ {
+ DBG_CHECK_ME();
+ bEnabled = _bEnabled;
+ }
+
+
+ void UnoControlTableModel::sortByColumn( ColPos const i_column, ColumnSortDirection const i_sortDirection )
+ {
+ DBG_CHECK_ME();
+
+ try
+ {
+ Reference< XSortableGridData > const xSortAccess( getDataModel(), UNO_QUERY_THROW );
+ xSortAccess->sortByColumn( i_column, i_sortDirection == ColumnSortAscending );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.uno");
+ }
+ }
+
+
+ ColumnSort UnoControlTableModel::getCurrentSortOrder() const
+ {
+ DBG_CHECK_ME();
+
+ ColumnSort currentSort;
+ try
+ {
+ Reference< XSortableGridData > const xSortAccess( getDataModel(), UNO_QUERY_THROW );
+ Pair< ::sal_Int32, sal_Bool > const aCurrentSortOrder( xSortAccess->getCurrentSortOrder() );
+ currentSort.nColumnPos = aCurrentSortOrder.First;
+ currentSort.eSortDirection = aCurrentSortOrder.Second ? ColumnSortAscending : ColumnSortDescending;
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.uno");
+ }
+ return currentSort;
+ }
+
+
+ void UnoControlTableModel::notifyColumnChange( ColPos const i_columnPos, ColumnAttributeGroup const i_attributeGroup ) const
+ {
+ DBG_CHECK_ME();
+ ENSURE_OR_RETURN_VOID( ( i_columnPos >= 0 ) && ( i_columnPos < getColumnCount() ),
+ "UnoControlTableModel::notifyColumnChange: invalid column index!" );
+
+ ModellListeners aListeners( m_aListeners );
+ for (auto const& listener : aListeners)
+ {
+ listener->columnChanged( i_columnPos, i_attributeGroup );
+ }
+ }
+
+
+ void UnoControlTableModel::notifyRowsInserted( GridDataEvent const & i_event ) const
+ {
+ // check sanity of the event
+ ENSURE_OR_RETURN_VOID( i_event.FirstRow >= 0, "UnoControlTableModel::notifyRowsInserted: invalid first row!" );
+ ENSURE_OR_RETURN_VOID( i_event.LastRow >= i_event.FirstRow, "UnoControlTableModel::notifyRowsInserted: invalid row indexes!" );
+
+ // check own sanity
+ Reference< XGridColumnModel > const xColumnModel( m_aColumnModel );
+ ENSURE_OR_RETURN_VOID( xColumnModel.is(), "UnoControlTableModel::notifyRowsInserted: no column model anymore!" );
+
+ Reference< XGridDataModel > const xDataModel( m_aDataModel );
+ ENSURE_OR_RETURN_VOID( xDataModel.is(), "UnoControlTableModel::notifyRowsInserted: no data model anymore!" );
+
+ // implicitly add columns to the column model
+ // TODO: is this really a good idea?
+ sal_Int32 const dataColumnCount = xDataModel->getColumnCount();
+ OSL_ENSURE( dataColumnCount > 0, "UnoControlTableModel::notifyRowsInserted: no columns at all?" );
+
+ sal_Int32 const modelColumnCount = xColumnModel->getColumnCount();
+ if ( ( modelColumnCount == 0 ) && ( dataColumnCount > 0 ) )
+ {
+ // TODO: shouldn't we clear the mutexes guard for this call?
+ xColumnModel->setDefaultColumns( dataColumnCount );
+ }
+
+ // multiplex the event to our own listeners
+ ModellListeners aListeners( m_aListeners );
+ for (auto const& listener : aListeners)
+ {
+ listener->rowsInserted( i_event.FirstRow, i_event.LastRow );
+ }
+ }
+
+
+ void UnoControlTableModel::notifyRowsRemoved( GridDataEvent const & i_event ) const
+ {
+ ModellListeners aListeners( m_aListeners );
+ for (auto const& listener : aListeners)
+ {
+ listener->rowsRemoved( i_event.FirstRow, i_event.LastRow );
+ }
+ }
+
+
+ void UnoControlTableModel::notifyDataChanged( css::awt::grid::GridDataEvent const & i_event ) const
+ {
+ RowPos const firstRow = i_event.FirstRow == -1 ? 0 : i_event.FirstRow;
+ RowPos const lastRow = i_event.FirstRow == -1 ? getRowCount() - 1 : i_event.LastRow;
+
+ ModellListeners aListeners( m_aListeners );
+ for (auto const& listener : aListeners)
+ {
+ listener->cellsUpdated( firstRow, lastRow );
+ }
+ }
+
+
+ void UnoControlTableModel::notifyAllDataChanged() const
+ {
+ ModellListeners aListeners( m_aListeners );
+ for (auto const& listener : aListeners)
+ {
+ listener->cellsUpdated( 0, getRowCount() - 1 );
+ }
+ }
+
+
+} // svt::table
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/unocontroltablemodel.hxx b/toolkit/source/controls/unocontroltablemodel.hxx
new file mode 100644
index 0000000000..2619407941
--- /dev/null
+++ b/toolkit/source/controls/unocontroltablemodel.hxx
@@ -0,0 +1,181 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <controls/table/tablemodel.hxx>
+#include <controls/table/tablesort.hxx>
+#include <tools/color.hxx>
+
+#include <com/sun/star/awt/grid/GridDataEvent.hpp>
+#include <com/sun/star/awt/grid/XGridColumnModel.hpp>
+#include <com/sun/star/awt/grid/XGridDataModel.hpp>
+#include <com/sun/star/awt/grid/XGridColumn.hpp>
+#include <com/sun/star/awt/grid/XGridColumn.hpp>
+#include <com/sun/star/style/VerticalAlignment.hpp>
+#include <cppuhelper/weakref.hxx>
+
+
+namespace svt::table
+{
+
+
+ //= UnoControlTableModel
+
+ class UnoGridColumnFacade;
+ class UnoControlTableModel : public ITableModel, public ITableDataSort
+ {
+ public:
+ UnoControlTableModel();
+ virtual ~UnoControlTableModel() override;
+
+ public:
+ // ITableModel overridables
+ virtual TableSize getColumnCount() const override;
+ virtual TableSize getRowCount() const override;
+ virtual bool hasColumnHeaders() const override;
+ virtual bool hasRowHeaders() const override;
+ virtual PColumnModel getColumnModel( ColPos column ) override;
+ virtual PTableRenderer getRenderer() const override;
+ virtual PTableInputHandler getInputHandler() const override;
+ virtual TableMetrics getRowHeight() const override;
+ virtual TableMetrics getColumnHeaderHeight() const override;
+ virtual TableMetrics getRowHeaderWidth() const override;
+ virtual ScrollbarVisibility getVerticalScrollbarVisibility() const override;
+ virtual ScrollbarVisibility getHorizontalScrollbarVisibility() const override;
+ virtual void addTableModelListener( const PTableModelListener& i_listener ) override;
+ virtual void removeTableModelListener( const PTableModelListener& i_listener ) override;
+ virtual void getCellContent( ColPos const i_col, RowPos const i_row, css::uno::Any& o_cellContent ) override;
+ virtual void getCellToolTip( ColPos const i_col, RowPos const i_row, css::uno::Any & o_cellToolTip ) override;
+ virtual css::uno::Any getRowHeading( RowPos const i_rowPos ) const override;
+ virtual ::std::optional< ::Color > getLineColor() const override;
+ virtual ::std::optional< ::Color > getHeaderBackgroundColor() const override;
+ virtual ::std::optional< ::Color > getHeaderTextColor() const override;
+ virtual ::std::optional< ::Color > getActiveSelectionBackColor() const override;
+ virtual ::std::optional< ::Color > getInactiveSelectionBackColor() const override;
+ virtual ::std::optional< ::Color > getActiveSelectionTextColor() const override;
+ virtual ::std::optional< ::Color > getInactiveSelectionTextColor() const override;
+ virtual ::std::optional< ::Color > getTextColor() const override;
+ virtual ::std::optional< ::Color > getTextLineColor() const override;
+ virtual ::std::optional< ::std::vector< ::Color > >
+ getRowBackgroundColors() const override;
+ virtual css::style::VerticalAlignment
+ getVerticalAlign() const override;
+ virtual ITableDataSort* getSortAdapter() override;
+ virtual bool isEnabled() const override;
+
+ // ITableDataSort overridables
+ virtual void sortByColumn( ColPos const i_column, ColumnSortDirection const i_sortDirection ) override;
+ virtual ColumnSort getCurrentSortOrder() const override;
+
+ // column write access
+ void appendColumn( css::uno::Reference< css::awt::grid::XGridColumn > const & i_column );
+ void insertColumn( ColPos const i_position, css::uno::Reference< css::awt::grid::XGridColumn > const & i_column );
+ void removeColumn( ColPos const i_position );
+ void removeAllColumns();
+
+ // other operations
+ void setVerticalScrollbarVisibility( ScrollbarVisibility const i_visibility );
+ void setHorizontalScrollbarVisibility( ScrollbarVisibility const i_visibility );
+
+ void setDataModel( css::uno::Reference< css::awt::grid::XGridDataModel > const & i_gridDataModel );
+ bool hasDataModel() const;
+ css::uno::Reference< css::awt::grid::XGridDataModel >
+ getDataModel() const;
+ void setColumnModel( css::uno::Reference< css::awt::grid::XGridColumnModel > const & i_gridColumnModel );
+ bool hasColumnModel() const;
+ css::uno::Reference< css::awt::grid::XGridColumnModel >
+ getColumnModel() const;
+
+ void setRowHeaders(bool _bRowHeaders);
+ void setColumnHeaders(bool _bColumnHeaders);
+
+ void setRowHeight( TableMetrics _nHeight );
+ void setRowHeaderWidth( TableMetrics _nWidth );
+ void setColumnHeaderHeight( TableMetrics _nHeight );
+
+ void setLineColor( css::uno::Any const & i_color );
+ void setHeaderBackgroundColor( css::uno::Any const & i_color );
+ void setHeaderTextColor( css::uno::Any const & i_color );
+ void setActiveSelectionBackColor( css::uno::Any const & i_color );
+ void setInactiveSelectionBackColor( css::uno::Any const & i_color );
+ void setActiveSelectionTextColor( css::uno::Any const & i_color );
+ void setInactiveSelectionTextColor( css::uno::Any const & i_color );
+ void setTextColor( css::uno::Any const & i_color );
+ void setTextLineColor( css::uno::Any const & i_color );
+ void setRowBackgroundColors( css::uno::Any const & i_APIValue );
+
+ void setVerticalAlign(css::style::VerticalAlignment _rAlign);
+ void setEnabled( bool _bEnabled );
+
+ // multiplexing of XGridDataListener events
+ void notifyRowsInserted( css::awt::grid::GridDataEvent const & i_event ) const;
+ void notifyRowsRemoved( css::awt::grid::GridDataEvent const & i_event ) const;
+ void notifyDataChanged( css::awt::grid::GridDataEvent const & i_event ) const;
+
+ /// retrieves the index of a column within the model
+ ColPos getColumnPos( UnoGridColumnFacade const & i_column ) const;
+
+ /// notifies a change in a column belonging to the model
+ void notifyColumnChange( ColPos const i_columnPos, ColumnAttributeGroup const i_attributeGroup ) const;
+
+ /** notifies a change in all data represented by the model. To be used if you cannot specified the changed data
+ in more detail.
+ */
+ void notifyAllDataChanged() const;
+
+ private:
+ void impl_notifyTableMetricsChanged() const;
+
+ typedef ::std::vector< PTableModelListener > ModellListeners;
+ typedef ::std::vector< PColumnModel > ColumnModels;
+
+ ColumnModels aColumns;
+ bool bHasColumnHeaders;
+ bool bHasRowHeaders;
+ ScrollbarVisibility eVScrollMode;
+ ScrollbarVisibility eHScrollMode;
+ PTableRenderer pRenderer;
+ PTableInputHandler pInputHandler;
+ TableMetrics nRowHeight;
+ TableMetrics nColumnHeaderHeight;
+ TableMetrics nRowHeaderWidth;
+ ::std::optional< ::Color > m_aGridLineColor;
+ ::std::optional< ::Color > m_aHeaderBackgroundColor;
+ ::std::optional< ::Color > m_aHeaderTextColor;
+ ::std::optional< ::Color > m_aActiveSelectionBackColor;
+ ::std::optional< ::Color > m_aInactiveSelectionBackColor;
+ ::std::optional< ::Color > m_aActiveSelectionTextColor;
+ ::std::optional< ::Color > m_aInactiveSelectionTextColor;
+ ::std::optional< ::Color > m_aTextColor;
+ ::std::optional< ::Color > m_aTextLineColor;
+ ::std::optional< ::std::vector< ::Color > > m_aRowColors;
+ css::style::VerticalAlignment m_eVerticalAlign;
+ bool bEnabled;
+ ModellListeners m_aListeners;
+ css::uno::WeakReference< css::awt::grid::XGridDataModel > m_aDataModel;
+ css::uno::WeakReference< css::awt::grid::XGridColumnModel > m_aColumnModel;
+ };
+
+
+} // svt::table
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/unogridcolumnfacade.cxx b/toolkit/source/controls/unogridcolumnfacade.cxx
new file mode 100644
index 0000000000..a060c8cf3e
--- /dev/null
+++ b/toolkit/source/controls/unogridcolumnfacade.cxx
@@ -0,0 +1,310 @@
+/* -*- 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 "unogridcolumnfacade.hxx"
+#include "unocontroltablemodel.hxx"
+
+#include <com/sun/star/awt/grid/XGridColumn.hpp>
+#include <com/sun/star/awt/grid/XGridColumnListener.hpp>
+
+#include <tools/debug.hxx>
+#include <comphelper/diagnose_ex.hxx>
+#include <vcl/svapp.hxx>
+#include <cppuhelper/implbase.hxx>
+
+
+namespace svt::table
+{
+
+
+ using css::uno::Reference;
+ using css::awt::grid::XGridColumn;
+ using css::uno::Exception;
+ using css::awt::grid::XGridColumnListener;
+ using css::lang::EventObject;
+ using css::awt::grid::GridColumnEvent;
+ using css::style::HorizontalAlignment_LEFT;
+ using css::style::HorizontalAlignment;
+
+
+ namespace
+ {
+ template< class T1, class T2 >
+ void lcl_set( Reference< XGridColumn > const & i_column, void ( SAL_CALL XGridColumn::*i_setter )( T1 ),
+ T2 i_value )
+ {
+ try
+ {
+ (i_column.get()->*i_setter) ( i_value );
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.uno");
+ }
+ }
+
+ template< class ATTRIBUTE_TYPE >
+ ATTRIBUTE_TYPE lcl_get( Reference< XGridColumn > const & i_column, ATTRIBUTE_TYPE ( SAL_CALL XGridColumn::*i_getter )() )
+ {
+ ATTRIBUTE_TYPE value = ATTRIBUTE_TYPE();
+ try
+ {
+ value = (i_column.get()->*i_getter)();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.uno");
+ }
+ return value;
+ }
+ }
+
+
+ //= ColumnChangeMultiplexer
+
+ typedef ::cppu::WeakImplHelper < XGridColumnListener
+ > ColumnChangeMultiplexer_Base;
+ class ColumnChangeMultiplexer :public ColumnChangeMultiplexer_Base
+ {
+ public:
+ explicit ColumnChangeMultiplexer( UnoGridColumnFacade& i_colImpl );
+ ColumnChangeMultiplexer(const ColumnChangeMultiplexer&) = delete;
+ ColumnChangeMultiplexer& operator=(const ColumnChangeMultiplexer&) = delete;
+
+ void dispose();
+
+ protected:
+ virtual ~ColumnChangeMultiplexer() override;
+
+ // XGridColumnListener
+ virtual void SAL_CALL columnChanged( const GridColumnEvent& i_event ) override;
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const EventObject& i_event ) override;
+
+ private:
+ UnoGridColumnFacade* m_pColumnImplementation;
+ };
+
+
+ ColumnChangeMultiplexer::ColumnChangeMultiplexer( UnoGridColumnFacade& i_colImpl )
+ :m_pColumnImplementation( &i_colImpl )
+ {
+ }
+
+
+ ColumnChangeMultiplexer::~ColumnChangeMultiplexer()
+ {
+ }
+
+
+ void ColumnChangeMultiplexer::dispose()
+ {
+ DBG_TESTSOLARMUTEX();
+ m_pColumnImplementation = nullptr;
+ }
+
+
+ void SAL_CALL ColumnChangeMultiplexer::columnChanged( const GridColumnEvent& i_event )
+ {
+ if ( i_event.AttributeName == "DataColumnIndex" )
+ {
+ SolarMutexGuard aGuard;
+ if ( m_pColumnImplementation != nullptr )
+ m_pColumnImplementation->dataColumnIndexChanged();
+ return;
+ }
+
+ ColumnAttributeGroup nChangedAttributes( ColumnAttributeGroup::NONE );
+
+ if ( i_event.AttributeName == "HorizontalAlign" )
+ nChangedAttributes |= ColumnAttributeGroup::APPEARANCE;
+
+ if ( i_event.AttributeName == "ColumnWidth"
+ || i_event.AttributeName == "MaxWidth"
+ || i_event.AttributeName == "MinWidth"
+ || i_event.AttributeName == "PreferredWidth"
+ || i_event.AttributeName == "Resizeable"
+ || i_event.AttributeName == "Flexibility"
+ )
+ nChangedAttributes |= ColumnAttributeGroup::WIDTH;
+
+ OSL_ENSURE( nChangedAttributes != ColumnAttributeGroup::NONE,
+ "ColumnChangeMultiplexer::columnChanged: unknown column attributed changed!" );
+
+ SolarMutexGuard aGuard;
+ if ( m_pColumnImplementation != nullptr )
+ m_pColumnImplementation->columnChanged( nChangedAttributes );
+ }
+
+
+ void SAL_CALL ColumnChangeMultiplexer::disposing( const EventObject& )
+ {
+ }
+
+
+ //= UnoGridColumnFacade
+
+
+ UnoGridColumnFacade::UnoGridColumnFacade( UnoControlTableModel const & i_owner, Reference< XGridColumn > const & i_gridColumn )
+ :m_pOwner( &i_owner )
+ ,m_nDataColumnIndex( -1 )
+ ,m_xGridColumn( i_gridColumn, css::uno::UNO_SET_THROW )
+ ,m_pChangeMultiplexer( new ColumnChangeMultiplexer( *this ) )
+ {
+ m_xGridColumn->addGridColumnListener( m_pChangeMultiplexer );
+ impl_updateDataColumnIndex_nothrow();
+ }
+
+
+ UnoGridColumnFacade::~UnoGridColumnFacade()
+ {
+ }
+
+
+ void UnoGridColumnFacade::dispose()
+ {
+ DBG_TESTSOLARMUTEX();
+ ENSURE_OR_RETURN_VOID( m_pOwner != nullptr, "UnoGridColumnFacade::dispose: already disposed!" );
+
+ m_xGridColumn->removeGridColumnListener( m_pChangeMultiplexer );
+ m_pChangeMultiplexer->dispose();
+ m_pChangeMultiplexer.clear();
+ m_xGridColumn.clear();
+ m_pOwner = nullptr;
+ }
+
+
+ void UnoGridColumnFacade::impl_updateDataColumnIndex_nothrow()
+ {
+ m_nDataColumnIndex = -1;
+ ENSURE_OR_RETURN_VOID( m_xGridColumn.is(), "UnoGridColumnFacade: already disposed!" );
+ try
+ {
+ m_nDataColumnIndex = m_xGridColumn->getDataColumnIndex();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.uno");
+ }
+ }
+
+
+ void UnoGridColumnFacade::dataColumnIndexChanged()
+ {
+ DBG_TESTSOLARMUTEX();
+ impl_updateDataColumnIndex_nothrow();
+ if ( m_pOwner != nullptr )
+ m_pOwner->notifyAllDataChanged();
+ }
+
+
+ void UnoGridColumnFacade::columnChanged( ColumnAttributeGroup const i_attributeGroup )
+ {
+ DBG_TESTSOLARMUTEX();
+ if ( m_pOwner != nullptr )
+ m_pOwner->notifyColumnChange( m_pOwner->getColumnPos( *this ), i_attributeGroup );
+ }
+
+
+ OUString UnoGridColumnFacade::getName() const
+ {
+ OUString sName;
+ ENSURE_OR_RETURN( m_xGridColumn.is(), "UnoGridColumnFacade: already disposed!", sName );
+ try
+ {
+ sName = m_xGridColumn->getTitle();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.uno");
+ }
+ return sName;
+ }
+
+
+ OUString UnoGridColumnFacade::getHelpText() const
+ {
+ OUString sHelpText;
+ ENSURE_OR_RETURN( m_xGridColumn.is(), "UnoGridColumnFacade: already disposed!", sHelpText );
+ try
+ {
+ sHelpText = m_xGridColumn->getHelpText();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("svtools.uno");
+ }
+ return sHelpText;
+ }
+
+
+ bool UnoGridColumnFacade::isResizable() const
+ {
+ ENSURE_OR_RETURN( m_xGridColumn.is(), "UnoGridColumnFacade: already disposed!", false );
+ return lcl_get( m_xGridColumn, &XGridColumn::getResizeable );
+ }
+
+
+ sal_Int32 UnoGridColumnFacade::getFlexibility() const
+ {
+ ENSURE_OR_RETURN( m_xGridColumn.is(), "UnoGridColumnFacade: already disposed!", 1 );
+ return lcl_get( m_xGridColumn, &XGridColumn::getFlexibility );
+ }
+
+
+ TableMetrics UnoGridColumnFacade::getWidth() const
+ {
+ ENSURE_OR_RETURN( m_xGridColumn.is(), "UnoGridColumnFacade: already disposed!", 0 );
+ return lcl_get( m_xGridColumn, &XGridColumn::getColumnWidth );
+ }
+
+
+ void UnoGridColumnFacade::setWidth( TableMetrics _nWidth )
+ {
+ ENSURE_OR_RETURN_VOID( m_xGridColumn.is(), "UnoGridColumnFacade: already disposed!" );
+ lcl_set( m_xGridColumn, &XGridColumn::setColumnWidth, _nWidth );
+ }
+
+
+ TableMetrics UnoGridColumnFacade::getMinWidth() const
+ {
+ ENSURE_OR_RETURN( m_xGridColumn.is(), "UnoGridColumnFacade: already disposed!", 0 );
+ return lcl_get( m_xGridColumn, &XGridColumn::getMinWidth );
+ }
+
+
+ TableMetrics UnoGridColumnFacade::getMaxWidth() const
+ {
+ ENSURE_OR_RETURN( m_xGridColumn.is(), "UnoGridColumnFacade: already disposed!", 0 );
+ return lcl_get( m_xGridColumn, &XGridColumn::getMaxWidth );
+ }
+
+
+ css::style::HorizontalAlignment UnoGridColumnFacade::getHorizontalAlign()
+ {
+ ENSURE_OR_RETURN( m_xGridColumn.is(), "UnoGridColumnFacade: already disposed!", HorizontalAlignment_LEFT );
+ return lcl_get( m_xGridColumn, &XGridColumn::getHorizontalAlign );
+ }
+
+
+} // svt::table
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/controls/unogridcolumnfacade.hxx b/toolkit/source/controls/unogridcolumnfacade.hxx
new file mode 100644
index 0000000000..580aee52bc
--- /dev/null
+++ b/toolkit/source/controls/unogridcolumnfacade.hxx
@@ -0,0 +1,89 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <controls/table/tablemodel.hxx>
+
+#include <com/sun/star/awt/grid/XGridColumn.hpp>
+#include <com/sun/star/style/HorizontalAlignment.hpp>
+
+#include <rtl/ref.hxx>
+
+
+namespace svt::table
+{
+
+
+ //= UnoGridColumnFacade
+
+ class ColumnChangeMultiplexer;
+ class UnoControlTableModel;
+ class UnoGridColumnFacade :public IColumnModel
+ {
+ public:
+ UnoGridColumnFacade(
+ UnoControlTableModel const & i_owner,
+ css::uno::Reference< css::awt::grid::XGridColumn > const & i_gridColumn
+ );
+ virtual ~UnoGridColumnFacade() override;
+ UnoGridColumnFacade(const UnoGridColumnFacade&) = delete;
+ UnoGridColumnFacade& operator=(const UnoGridColumnFacade&) = delete;
+
+ // IColumnModel overridables
+ virtual OUString getName() const override;
+ virtual OUString getHelpText() const override;
+ virtual bool isResizable() const override;
+ virtual sal_Int32 getFlexibility() const override;
+ virtual TableMetrics getWidth() const override;
+ virtual void setWidth( TableMetrics _nWidth ) override;
+ virtual TableMetrics getMinWidth() const override;
+ virtual TableMetrics getMaxWidth() const override;
+ virtual css::style::HorizontalAlignment getHorizontalAlign() override;
+
+ /** disposes the column wrapper
+
+ Note that the XGridColumn which is wrapped by the instance is <strong>not</strong> disposed, as we
+ do not own it.
+ */
+ void dispose();
+
+ sal_Int32
+ getDataColumnIndex() const { return m_nDataColumnIndex; }
+
+ // callbacks for the XGridColumnListener
+ void columnChanged( ColumnAttributeGroup const i_attributeGroup );
+ void dataColumnIndexChanged();
+
+ private:
+ void impl_updateDataColumnIndex_nothrow();
+
+ private:
+ UnoControlTableModel const * m_pOwner;
+ sal_Int32 m_nDataColumnIndex;
+ css::uno::Reference< css::awt::grid::XGridColumn > m_xGridColumn;
+ ::rtl::Reference< ColumnChangeMultiplexer > m_pChangeMultiplexer;
+ };
+
+
+} // svt::table
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/hatchwindow/documentcloser.cxx b/toolkit/source/hatchwindow/documentcloser.cxx
new file mode 100644
index 0000000000..70171d7308
--- /dev/null
+++ b/toolkit/source/hatchwindow/documentcloser.cxx
@@ -0,0 +1,229 @@
+/* -*- 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 <com/sun/star/util/XCloseable.hpp>
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/awt/XVclWindowPeer.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/interfacecontainer4.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <utility>
+#include <vcl/svapp.hxx>
+#include <vcl/dialoghelper.hxx>
+#include <vcl/window.hxx>
+#include <tools/link.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+
+using namespace ::com::sun::star;
+
+namespace {
+
+// the service is implemented as a wrapper to be able to die by refcount
+// the disposing mechanics is required for java related scenarios
+class ODocumentCloser : public ::cppu::WeakImplHelper< css::lang::XComponent,
+ css::lang::XServiceInfo >
+{
+ std::mutex m_aMutex;
+ css::uno::Reference< css::frame::XFrame > m_xFrame;
+ ::comphelper::OInterfaceContainerHelper4<lang::XEventListener> m_aListenersContainer; // list of listeners
+
+ bool m_bDisposed;
+
+public:
+ explicit ODocumentCloser(const css::uno::Sequence< css::uno::Any >& aArguments);
+
+// XComponent
+ virtual void SAL_CALL dispose() override;
+ virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) override;
+ virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) 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;
+};
+
+class MainThreadFrameCloserRequest
+{
+ uno::Reference< frame::XFrame > m_xFrame;
+
+ public:
+ explicit MainThreadFrameCloserRequest( uno::Reference< frame::XFrame > xFrame )
+ : m_xFrame(std::move( xFrame ))
+ {}
+
+ DECL_STATIC_LINK( MainThreadFrameCloserRequest, worker, void*, void );
+
+ static void Start( MainThreadFrameCloserRequest* pRequest );
+};
+
+
+void MainThreadFrameCloserRequest::Start( MainThreadFrameCloserRequest* pMTRequest )
+{
+ if ( pMTRequest )
+ {
+ if ( Application::IsMainThread() )
+ {
+ // this is the main thread
+ worker( nullptr, pMTRequest );
+ }
+ else
+ Application::PostUserEvent( LINK( nullptr, MainThreadFrameCloserRequest, worker ), pMTRequest );
+ }
+}
+
+
+IMPL_STATIC_LINK( MainThreadFrameCloserRequest, worker, void*, p, void )
+{
+ MainThreadFrameCloserRequest* pMTRequest = static_cast<MainThreadFrameCloserRequest*>(p);
+ if ( !pMTRequest )
+ return;
+
+ if ( pMTRequest->m_xFrame.is() )
+ {
+ // this is the main thread, the solar mutex must be locked
+ SolarMutexGuard aGuard;
+
+ try
+ {
+ uno::Reference< awt::XWindow > xWindow = pMTRequest->m_xFrame->getContainerWindow();
+ uno::Reference< awt::XVclWindowPeer > xWinPeer( xWindow, uno::UNO_QUERY_THROW );
+
+ xWindow->setVisible( false );
+
+ // reparent the window
+ xWinPeer->setProperty( "PluginParent", uno::Any( sal_Int64(0) ) );
+
+ VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
+ if (pWindow)
+ vcl::EndAllDialogs(pWindow);
+ }
+ catch( uno::Exception& )
+ {
+ // ignore all the errors
+ }
+
+ try
+ {
+ uno::Reference< util::XCloseable > xCloseable( pMTRequest->m_xFrame, uno::UNO_QUERY_THROW );
+ xCloseable->close( true );
+ }
+ catch( uno::Exception& )
+ {
+ // ignore all the errors
+ }
+ }
+
+ delete pMTRequest;
+}
+
+ODocumentCloser::ODocumentCloser(const css::uno::Sequence< css::uno::Any >& aArguments)
+: m_bDisposed( false )
+{
+ std::unique_lock aGuard( m_aMutex );
+ if ( !m_refCount )
+ throw uno::RuntimeException(); // the object must be refcounted already!
+
+ sal_Int32 nLen = aArguments.getLength();
+ if ( nLen != 1 )
+ throw lang::IllegalArgumentException(
+ "Wrong count of parameters!",
+ uno::Reference< uno::XInterface >(),
+ 0 );
+
+ if ( !( aArguments[0] >>= m_xFrame ) || !m_xFrame.is() )
+ throw lang::IllegalArgumentException(
+ "Nonempty reference is expected as the first argument!",
+ uno::Reference< uno::XInterface >(),
+ 0 );
+}
+
+
+// XComponent
+
+void SAL_CALL ODocumentCloser::dispose()
+{
+ std::unique_lock aGuard( m_aMutex );
+
+ if ( m_bDisposed )
+ return;
+
+ lang::EventObject aSource( getXWeak() );
+ m_aListenersContainer.disposeAndClear( aGuard, aSource );
+
+ // TODO: trigger a main thread execution to close the frame
+ if ( m_xFrame.is() )
+ {
+ // the created object will be deleted after thread execution
+ MainThreadFrameCloserRequest* pCloser = new MainThreadFrameCloserRequest( m_xFrame );
+ MainThreadFrameCloserRequest::Start( pCloser );
+ }
+
+ m_bDisposed = true;
+}
+
+
+void SAL_CALL ODocumentCloser::addEventListener( const uno::Reference< lang::XEventListener >& xListener )
+{
+ std::unique_lock aGuard( m_aMutex );
+ if ( m_bDisposed )
+ throw lang::DisposedException(); // TODO
+
+ m_aListenersContainer.addInterface( aGuard, xListener );
+}
+
+
+void SAL_CALL ODocumentCloser::removeEventListener( const uno::Reference< lang::XEventListener >& xListener )
+{
+ std::unique_lock aGuard( m_aMutex );
+ m_aListenersContainer.removeInterface( aGuard, xListener );
+}
+
+// XServiceInfo
+OUString SAL_CALL ODocumentCloser::getImplementationName( )
+{
+ return "com.sun.star.comp.embed.DocumentCloser";
+}
+
+sal_Bool SAL_CALL ODocumentCloser::supportsService( const OUString& ServiceName )
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL ODocumentCloser::getSupportedServiceNames()
+{
+ return { "com.sun.star.embed.DocumentCloser" };
+}
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_embed_DocumentCloser_get_implementation(
+ SAL_UNUSED_PARAMETER css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &arguments)
+{
+ return cppu::acquire(new ODocumentCloser(arguments));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/hatchwindow/hatchwindow.cxx b/toolkit/source/hatchwindow/hatchwindow.cxx
new file mode 100644
index 0000000000..4685126b20
--- /dev/null
+++ b/toolkit/source/hatchwindow/hatchwindow.cxx
@@ -0,0 +1,159 @@
+/* -*- 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/embed/XHatchWindowController.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+
+#include "hatchwindow.hxx"
+#include "ipwin.hxx"
+
+#include <toolkit/helper/convert.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <osl/diagnose.h>
+#include <vcl/svapp.hxx>
+
+using namespace ::com::sun::star;
+
+VCLXHatchWindow::VCLXHatchWindow()
+: pHatchWindow(nullptr)
+{
+}
+
+VCLXHatchWindow::~VCLXHatchWindow()
+{
+}
+
+void VCLXHatchWindow::initializeWindow( const uno::Reference< awt::XWindowPeer >& xParent,
+ const awt::Rectangle& aBounds,
+ const awt::Size& aSize )
+{
+ SolarMutexGuard aGuard;
+
+ VclPtr<vcl::Window> pParent;
+ VCLXWindow* pParentComponent = dynamic_cast<VCLXWindow*>( xParent.get() );
+
+ if ( pParentComponent )
+ pParent = pParentComponent->GetWindow();
+
+ OSL_ENSURE( pParent, "No parent window is provided!" );
+ if ( !pParent )
+ throw lang::IllegalArgumentException(); // TODO
+
+ pHatchWindow = VclPtr<SvResizeWindow>::Create( pParent, this );
+ pHatchWindow->setPosSizePixel( aBounds.X, aBounds.Y, aBounds.Width, aBounds.Height );
+ aHatchBorderSize = aSize;
+ pHatchWindow->SetHatchBorderPixel( Size( aSize.Width, aSize.Height ) );
+
+ SetWindow( pHatchWindow );
+ pHatchWindow->SetComponentInterface( this );
+
+ //pHatchWindow->Show();
+}
+
+void VCLXHatchWindow::QueryObjAreaPixel( tools::Rectangle & aRect )
+{
+ if ( !m_xController.is() )
+ return;
+
+ awt::Rectangle aUnoRequestRect = AWTRectangle( aRect );
+
+ try {
+ awt::Rectangle aUnoResultRect = m_xController->calcAdjustedRectangle( aUnoRequestRect );
+ aRect = VCLRectangle( aUnoResultRect );
+ }
+ catch( uno::Exception& )
+ {
+ OSL_FAIL( "Can't adjust rectangle size!" );
+ }
+}
+
+void VCLXHatchWindow::RequestObjAreaPixel( const tools::Rectangle & aRect )
+{
+ if ( m_xController.is() )
+ {
+ awt::Rectangle aUnoRequestRect = AWTRectangle( aRect );
+
+ try {
+ m_xController->requestPositioning( aUnoRequestRect );
+ }
+ catch( uno::Exception& )
+ {
+ OSL_FAIL( "Can't request resizing!" );
+ }
+ }
+}
+
+void VCLXHatchWindow::InplaceDeactivate()
+{
+ if ( m_xController.is() )
+ {
+ // TODO: communicate with controller
+ }
+}
+
+
+css::awt::Size SAL_CALL VCLXHatchWindow::getHatchBorderSize()
+{
+ return aHatchBorderSize;
+}
+
+void SAL_CALL VCLXHatchWindow::setHatchBorderSize( const css::awt::Size& _hatchbordersize )
+{
+ if ( pHatchWindow )
+ {
+ aHatchBorderSize = _hatchbordersize;
+ pHatchWindow->SetHatchBorderPixel( Size( aHatchBorderSize.Width, aHatchBorderSize.Height ) );
+ }
+}
+
+void SAL_CALL VCLXHatchWindow::setController( const uno::Reference< embed::XHatchWindowController >& xController )
+{
+ m_xController = xController;
+}
+
+void SAL_CALL VCLXHatchWindow::dispose()
+{
+ pHatchWindow.clear();
+ VCLXWindow::dispose();
+}
+
+void SAL_CALL VCLXHatchWindow::addEventListener( const uno::Reference< lang::XEventListener >& xListener )
+{
+ VCLXWindow::addEventListener( xListener );
+}
+
+void SAL_CALL VCLXHatchWindow::removeEventListener( const uno::Reference< lang::XEventListener >& xListener )
+{
+ VCLXWindow::removeEventListener( xListener );
+}
+
+void VCLXHatchWindow::Activated()
+{
+ if ( m_xController.is() )
+ m_xController->activated();
+}
+
+void VCLXHatchWindow::Deactivated()
+{
+ if ( m_xController.is() )
+ m_xController->deactivated();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/hatchwindow/hatchwindow.hxx b/toolkit/source/hatchwindow/hatchwindow.hxx
new file mode 100644
index 0000000000..128a5198f9
--- /dev/null
+++ b/toolkit/source/hatchwindow/hatchwindow.hxx
@@ -0,0 +1,60 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <com/sun/star/embed/XHatchWindow.hpp>
+
+#include <toolkit/awt/vclxwindow.hxx>
+
+class SvResizeWindow;
+typedef cppu::ImplInheritanceHelper< VCLXWindow, css::embed::XHatchWindow> VCLXHatchWindow_Base;
+class VCLXHatchWindow : public VCLXHatchWindow_Base
+{
+ css::uno::Reference< css::embed::XHatchWindowController > m_xController;
+ css::awt::Size aHatchBorderSize;
+ VclPtr<SvResizeWindow> pHatchWindow;
+
+public:
+ VCLXHatchWindow();
+ virtual ~VCLXHatchWindow() override;
+
+ void initializeWindow( const css::uno::Reference< css::awt::XWindowPeer >& xParent,
+ const css::awt::Rectangle& aBounds,
+ const css::awt::Size& aSize );
+
+ void QueryObjAreaPixel( tools::Rectangle & );
+ void RequestObjAreaPixel( const tools::Rectangle & );
+ void InplaceDeactivate();
+ void Activated();
+ void Deactivated();
+
+ // XHatchWindow
+ virtual void SAL_CALL setController( const css::uno::Reference< css::embed::XHatchWindowController >& xController ) override;
+ virtual css::awt::Size SAL_CALL getHatchBorderSize() override;
+ virtual void SAL_CALL setHatchBorderSize( const css::awt::Size& _hatchbordersize ) override;
+
+ // XComponent
+ virtual void SAL_CALL dispose() override;
+ virtual void SAL_CALL addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) override;
+ virtual void SAL_CALL removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) override;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/hatchwindow/hatchwindowfactory.cxx b/toolkit/source/hatchwindow/hatchwindowfactory.cxx
new file mode 100644
index 0000000000..3e50db64ee
--- /dev/null
+++ b/toolkit/source/hatchwindow/hatchwindowfactory.cxx
@@ -0,0 +1,89 @@
+/* -*- 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/embed/XHatchWindowFactory.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <vcl/svapp.hxx>
+
+#include "hatchwindow.hxx"
+
+using namespace ::com::sun::star;
+
+namespace {
+
+class OHatchWindowFactory : public ::cppu::WeakImplHelper<
+ embed::XHatchWindowFactory,
+ lang::XServiceInfo >
+{
+public:
+ OHatchWindowFactory() {}
+
+ // XHatchWindowFactory
+ virtual uno::Reference< embed::XHatchWindow > SAL_CALL createHatchWindowInstance( const uno::Reference< awt::XWindowPeer >& xParent, const awt::Rectangle& aBounds, const awt::Size& aSize ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+};
+
+uno::Reference< embed::XHatchWindow > SAL_CALL OHatchWindowFactory::createHatchWindowInstance(
+ const uno::Reference< awt::XWindowPeer >& xParent,
+ const awt::Rectangle& aBounds,
+ const awt::Size& aHandlerSize )
+{
+ if ( !xParent.is() )
+ throw lang::IllegalArgumentException(); // TODO
+
+ SolarMutexGuard aGuard;
+ rtl::Reference<VCLXHatchWindow> pResult = new VCLXHatchWindow();
+ pResult->initializeWindow( xParent, aBounds, aHandlerSize );
+ return pResult;
+}
+
+OUString SAL_CALL OHatchWindowFactory::getImplementationName()
+{
+ return "com.sun.star.comp.embed.HatchWindowFactory";
+}
+
+sal_Bool SAL_CALL OHatchWindowFactory::supportsService( const OUString& ServiceName )
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL OHatchWindowFactory::getSupportedServiceNames()
+{
+ return { "com.sun.star.embed.HatchWindowFactory", "com.sun.star.comp.embed.HatchWindowFactory" };
+}
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
+com_sun_star_comp_embed_HatchWindowFactory_get_implementation(
+ css::uno::XComponentContext *,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new OHatchWindowFactory);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/hatchwindow/ipwin.cxx b/toolkit/source/hatchwindow/ipwin.cxx
new file mode 100644
index 0000000000..52d3668b7f
--- /dev/null
+++ b/toolkit/source/hatchwindow/ipwin.cxx
@@ -0,0 +1,621 @@
+/* -*- 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/accessibility/AccessibleRole.hpp>
+
+#include <osl/diagnose.h>
+#include <vcl/event.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/ptrstyle.hxx>
+
+#include "ipwin.hxx"
+#include "hatchwindow.hxx"
+
+/************************************************************************/
+/*************************************************************************
+|* SvResizeHelper::SvResizeHelper()
+|*
+|* Description
+*************************************************************************/
+SvResizeHelper::SvResizeHelper()
+ : aBorder( 5, 5 )
+ , nGrab( -1 )
+{
+}
+
+/*************************************************************************
+|* SvResizeHelper::FillHandleRects()
+|*
+|* Description: the eight handles to magnify
+*************************************************************************/
+std::array<tools::Rectangle,8> SvResizeHelper::FillHandleRectsPixel() const
+{
+ std::array<tools::Rectangle,8> aRects;
+
+ // only because of EMPTY_RECT
+ Point aBottomRight = aOuter.BottomRight();
+
+ // upper left
+ aRects[ 0 ] = tools::Rectangle( aOuter.TopLeft(), aBorder );
+ // upper middle
+ aRects[ 1 ] = tools::Rectangle( Point( aOuter.Center().X() - aBorder.Width() / 2,
+ aOuter.Top() ),
+ aBorder );
+ // upper right
+ aRects[ 2 ] = tools::Rectangle( Point( aBottomRight.X() - aBorder.Width() +1,
+ aOuter.Top() ),
+ aBorder );
+ // middle right
+ aRects[ 3 ] = tools::Rectangle( Point( aBottomRight.X() - aBorder.Width() +1,
+ aOuter.Center().Y() - aBorder.Height() / 2 ),
+ aBorder );
+ // lower right
+ aRects[ 4 ] = tools::Rectangle( Point( aBottomRight.X() - aBorder.Width() +1,
+ aBottomRight.Y() - aBorder.Height() +1 ),
+ aBorder );
+ // lower middle
+ aRects[ 5 ] = tools::Rectangle( Point( aOuter.Center().X() - aBorder.Width() / 2,
+ aBottomRight.Y() - aBorder.Height() +1),
+ aBorder );
+ // lower left
+ aRects[ 6 ] = tools::Rectangle( Point( aOuter.Left(),
+ aBottomRight.Y() - aBorder.Height() +1),
+ aBorder );
+ // middle left
+ aRects[ 7 ] = tools::Rectangle( Point( aOuter.Left(),
+ aOuter.Center().Y() - aBorder.Height() / 2 ),
+ aBorder );
+ return aRects;
+}
+
+/*************************************************************************
+|* SvResizeHelper::FillMoveRectsPixel()
+|*
+|* Description: the four edges are calculated
+*************************************************************************/
+std::array<tools::Rectangle,4> SvResizeHelper::FillMoveRectsPixel() const
+{
+ std::array<tools::Rectangle,4> aRects;
+
+ // upper
+ aRects[ 0 ] = aOuter;
+ aRects[ 0 ].SetBottom( aRects[ 0 ].Top() + aBorder.Height() -1 );
+ // right
+ aRects[ 1 ] = aOuter;
+ if (!aOuter.IsWidthEmpty())
+ aRects[ 1 ].SetLeft( aRects[ 1 ].Right() - aBorder.Width() -1 );
+ // lower
+ aRects[ 2 ] = aOuter;
+ if (!aOuter.IsHeightEmpty())
+ aRects[ 2 ].SetTop( aRects[ 2 ].Bottom() - aBorder.Height() -1 );
+ // left
+ aRects[ 3 ] = aOuter;
+ aRects[ 3 ].SetRight( aRects[ 3 ].Left() + aBorder.Width() -1 );
+
+ return aRects;
+}
+
+/*************************************************************************
+|* SvResizeHelper::Draw()
+|*
+|* Description
+*************************************************************************/
+void SvResizeHelper::Draw(vcl::RenderContext& rRenderContext)
+{
+ rRenderContext.Push();
+ rRenderContext.SetMapMode( MapMode() );
+
+ rRenderContext.SetFillColor( COL_LIGHTGRAY );
+ rRenderContext.SetLineColor();
+
+ std::array<tools::Rectangle,4> aMoveRects = FillMoveRectsPixel();
+ sal_uInt16 i;
+ for (i = 0; i < 4; i++)
+ rRenderContext.DrawRect(aMoveRects[i]);
+ // draw handles
+ rRenderContext.SetFillColor(Color()); // black
+ std::array<tools::Rectangle,8> aRects = FillHandleRectsPixel();
+ for (i = 0; i < 8; i++)
+ rRenderContext.DrawRect( aRects[ i ] );
+ rRenderContext.Pop();
+}
+
+/*************************************************************************
+|* SvResizeHelper::InvalidateBorder()
+|*
+|* Description
+*************************************************************************/
+void SvResizeHelper::InvalidateBorder( vcl::Window * pWin )
+{
+ std::array<tools::Rectangle,4> aMoveRects = FillMoveRectsPixel();
+ for(const auto & rMoveRect : aMoveRects)
+ pWin->Invalidate( rMoveRect );
+}
+
+/*************************************************************************
+|* SvResizeHelper::SelectBegin()
+|*
+|* Description
+*************************************************************************/
+bool SvResizeHelper::SelectBegin( vcl::Window * pWin, const Point & rPos )
+{
+ if( -1 == nGrab )
+ {
+ nGrab = SelectMove( pWin, rPos );
+ if( -1 != nGrab )
+ {
+ aSelPos = rPos; // store start position
+ pWin->CaptureMouse();
+ return true;
+ }
+ }
+ return false;
+}
+
+/*************************************************************************
+|* SvResizeHelper::SelectMove()
+|*
+|* Description
+*************************************************************************/
+short SvResizeHelper::SelectMove( vcl::Window * pWin, const Point & rPos )
+{
+ if( -1 == nGrab )
+ {
+ std::array<tools::Rectangle,8> aRects = FillHandleRectsPixel();
+ for( sal_uInt16 i = 0; i < 8; i++ )
+ if( aRects[ i ].Contains( rPos ) )
+ return i;
+ // Move-Rect overlaps Handles
+ std::array<tools::Rectangle,4> aMoveRects = FillMoveRectsPixel();
+ for(const auto & rMoveRect : aMoveRects)
+ if( rMoveRect.Contains( rPos ) )
+ return 8;
+ }
+ else
+ {
+ tools::Rectangle aRect = pWin->PixelToLogic(GetTrackRectPixel( rPos ));
+ pWin->ShowTracking( aRect );
+ }
+ return nGrab;
+}
+
+Point SvResizeHelper::GetTrackPosPixel( const tools::Rectangle & rRect ) const
+{
+ // not important how the rectangle is returned, it is important
+ // which handle has been touched
+ Point aPos;
+ tools::Rectangle aRect( rRect );
+ aRect.Normalize();
+ // only because of EMPTY_RECT
+ Point aBR = aOuter.BottomRight();
+ Point aTR = aOuter.TopRight();
+ Point aBL = aOuter.BottomLeft();
+ bool bRTL = AllSettings::GetLayoutRTL();
+ switch( nGrab )
+ {
+ case 0:
+ // FIXME: disable it for RTL because it's wrong calculations
+ if( bRTL )
+ break;
+ aPos = aRect.TopLeft() - aOuter.TopLeft();
+ break;
+ case 1:
+ aPos.setY( aRect.Top() - aOuter.Top() );
+ break;
+ case 2:
+ // FIXME: disable it for RTL because it's wrong calculations
+ if( bRTL )
+ break;
+ aPos = aRect.TopRight() - aTR;
+ break;
+ case 3:
+ if( bRTL )
+ aPos.setX( aRect.Left() - aTR.X() );
+ else
+ aPos.setX( aRect.Right() - aTR.X() );
+ break;
+ case 4:
+ // FIXME: disable it for RTL because it's wrong calculations
+ if( bRTL )
+ break;
+ aPos = aRect.BottomRight() - aBR;
+ break;
+ case 5:
+ aPos.setY( aRect.Bottom() - aBR.Y() );
+ break;
+ case 6:
+ // FIXME: disable it for RTL because it's wrong calculations
+ if( bRTL )
+ break;
+ aPos = aRect.BottomLeft() - aBL;
+ break;
+ case 7:
+ if( bRTL )
+ aPos.setX( aRect.Right() + aOuter.Right() - aOuter.Right() );
+ else
+ aPos.setX( aRect.Left() - aOuter.Left() );
+ break;
+ case 8:
+ aPos = aRect.TopLeft() - aOuter.TopLeft();
+ break;
+ }
+ return aPos + aSelPos;
+}
+
+/*************************************************************************
+|* SvResizeHelper::GetTrackRectPixel()
+|*
+|* Description
+*************************************************************************/
+tools::Rectangle SvResizeHelper::GetTrackRectPixel( const Point & rTrackPos ) const
+{
+ tools::Rectangle aTrackRect;
+ if( -1 != nGrab )
+ {
+ Point aDiff = rTrackPos - aSelPos;
+ aTrackRect = aOuter;
+ Point aBR = aOuter.BottomRight();
+ bool bRTL = AllSettings::GetLayoutRTL();
+ switch( nGrab )
+ {
+ case 0:
+ aTrackRect.AdjustTop(aDiff.Y() );
+ // ugly solution for resizing OLE objects in RTL
+ if( bRTL )
+ aTrackRect.SetRight( aBR.X() - aDiff.X() );
+ else
+ aTrackRect.AdjustLeft(aDiff.X() );
+ break;
+ case 1:
+ aTrackRect.AdjustTop(aDiff.Y() );
+ break;
+ case 2:
+ aTrackRect.AdjustTop(aDiff.Y() );
+ // ugly solution for resizing OLE objects in RTL
+ if( bRTL )
+ aTrackRect.AdjustLeft( -(aDiff.X()) );
+ else
+ aTrackRect.SetRight( aBR.X() + aDiff.X() );
+ break;
+ case 3:
+ // ugly solution for resizing OLE objects in RTL
+ if( bRTL )
+ aTrackRect.AdjustLeft( -(aDiff.X()) );
+ else
+ aTrackRect.SetRight( aBR.X() + aDiff.X() );
+ break;
+ case 4:
+ aTrackRect.SetBottom( aBR.Y() + aDiff.Y() );
+ // ugly solution for resizing OLE objects in RTL
+ if( bRTL )
+ aTrackRect.AdjustLeft( -(aDiff.X()) );
+ else
+ aTrackRect.SetRight( aBR.X() + aDiff.X() );
+ break;
+ case 5:
+ aTrackRect.SetBottom( aBR.Y() + aDiff.Y() );
+ break;
+ case 6:
+ aTrackRect.SetBottom( aBR.Y() + aDiff.Y() );
+ // ugly solution for resizing OLE objects in RTL
+ if( bRTL )
+ aTrackRect.SetRight( aBR.X() - aDiff.X() );
+ else
+ aTrackRect.AdjustLeft(aDiff.X() );
+ break;
+ case 7:
+ // ugly solution for resizing OLE objects in RTL
+ if( bRTL )
+ aTrackRect.SetRight( aBR.X() - aDiff.X() );
+ else
+ aTrackRect.AdjustLeft(aDiff.X() );
+ break;
+ case 8:
+ if( bRTL )
+ aDiff.setX( -aDiff.X() ); // workaround for move in RTL mode
+ aTrackRect.SetPos( aTrackRect.TopLeft() + aDiff );
+ break;
+ }
+ }
+ return aTrackRect;
+}
+
+void SvResizeHelper::ValidateRect( tools::Rectangle & rValidate ) const
+{
+ switch( nGrab )
+ {
+ case 0:
+ if( rValidate.Top() > rValidate.Bottom() )
+ rValidate.SetTop( rValidate.Bottom() );
+ if( rValidate.Left() > rValidate.Right() )
+ rValidate.SetLeft( rValidate.Right() );
+ break;
+ case 1:
+ if( rValidate.Top() > rValidate.Bottom() )
+ rValidate.SetTop( rValidate.Bottom() );
+ break;
+ case 2:
+ if( rValidate.Top() > rValidate.Bottom() )
+ rValidate.SetTop( rValidate.Bottom() );
+ if( rValidate.Left() > rValidate.Right() )
+ rValidate.SetRight( rValidate.Left() );
+ break;
+ case 3:
+ if( rValidate.Left() > rValidate.Right() )
+ rValidate.SetRight( rValidate.Left() );
+ break;
+ case 4:
+ if( rValidate.Top() > rValidate.Bottom() )
+ rValidate.SetBottom( rValidate.Top() );
+ if( rValidate.Left() > rValidate.Right() )
+ rValidate.SetRight( rValidate.Left() );
+ break;
+ case 5:
+ if( rValidate.Top() > rValidate.Bottom() )
+ rValidate.SetBottom( rValidate.Top() );
+ break;
+ case 6:
+ if( rValidate.Top() > rValidate.Bottom() )
+ rValidate.SetBottom( rValidate.Top() );
+ if( rValidate.Left() > rValidate.Right() )
+ rValidate.SetLeft( rValidate.Right() );
+ break;
+ case 7:
+ if( rValidate.Left() > rValidate.Right() )
+ rValidate.SetLeft( rValidate.Right() );
+ break;
+ }
+
+ // Mindestgr"osse 5 x 5
+ if( rValidate.Left() + 5 > rValidate.Right() )
+ rValidate.SetRight( rValidate.Left() + 5 );
+ if( rValidate.Top() + 5 > rValidate.Bottom() )
+ rValidate.SetBottom( rValidate.Top() + 5 );
+}
+
+/*************************************************************************
+|* SvResizeHelper::SelectRelease()
+|*
+|* Description
+*************************************************************************/
+bool SvResizeHelper::SelectRelease( vcl::Window * pWin, const Point & rPos,
+ tools::Rectangle & rOutPosSize )
+{
+ if( -1 != nGrab )
+ {
+ rOutPosSize = GetTrackRectPixel( rPos );
+ rOutPosSize.Normalize();
+ nGrab = -1;
+ pWin->ReleaseMouse();
+ pWin->HideTracking();
+ return true;
+ }
+ return false;
+}
+
+/*************************************************************************
+|* SvResizeHelper::Release()
+|*
+|* Description
+*************************************************************************/
+void SvResizeHelper::Release( vcl::Window * pWin )
+{
+ if( nGrab != -1 )
+ {
+ pWin->ReleaseMouse();
+ pWin->HideTracking();
+ nGrab = -1;
+ }
+}
+
+/*************************************************************************
+|* SvResizeWindow::SvResizeWindow()
+|*
+|* Description
+*************************************************************************/
+SvResizeWindow::SvResizeWindow
+(
+ vcl::Window * pParent,
+ VCLXHatchWindow* pWrapper
+)
+ : Window( pParent, WB_CLIPCHILDREN )
+ , m_aOldPointer(PointerStyle::Arrow)
+ , m_nMoveGrab( -1 )
+ , m_bActive( false )
+ , m_pWrapper( pWrapper )
+{
+ OSL_ENSURE( pParent != nullptr && pWrapper != nullptr, "Wrong initialization of hatch window!" );
+ SetBackground();
+ SetAccessibleRole( css::accessibility::AccessibleRole::EMBEDDED_OBJECT );
+ m_aResizer.SetOuterRectPixel( tools::Rectangle( Point(), GetOutputSizePixel() ) );
+}
+
+/*************************************************************************
+|* SvResizeWindow::SetHatchBorderPixel()
+|*
+|* Description
+*************************************************************************/
+void SvResizeWindow::SetHatchBorderPixel( const Size & rSize )
+{
+ m_aResizer.SetBorderPixel( rSize );
+}
+
+/*************************************************************************
+|* SvResizeWindow::SelectMouse()
+|*
+|* Description
+*************************************************************************/
+void SvResizeWindow::SelectMouse( const Point & rPos )
+{
+ short nGrab = m_aResizer.SelectMove( this, rPos );
+ if( nGrab >= 4 )
+ nGrab -= 4;
+ if( m_nMoveGrab == nGrab )
+ return;
+
+ // Pointer did change
+ if( -1 == nGrab )
+ SetPointer( m_aOldPointer );
+ else
+ {
+ PointerStyle aStyle = PointerStyle::Move;
+ if( nGrab == 3 )
+ aStyle = PointerStyle::ESize;
+ else if( nGrab == 2 )
+ aStyle = PointerStyle::NESize;
+ else if( nGrab == 1 )
+ aStyle = PointerStyle::SSize;
+ else if( nGrab == 0 )
+ aStyle = PointerStyle::SESize;
+ if( m_nMoveGrab == -1 ) // the first time
+ {
+ m_aOldPointer = GetPointer();
+ SetPointer( aStyle );
+ }
+ else
+ SetPointer( aStyle );
+ }
+ m_nMoveGrab = nGrab;
+}
+
+/*************************************************************************
+|* SvResizeWindow::MouseButtonDown()
+|*
+|* Description
+*************************************************************************/
+void SvResizeWindow::MouseButtonDown( const MouseEvent & rEvt )
+{
+ if( m_aResizer.SelectBegin( this, rEvt.GetPosPixel() ) )
+ SelectMouse( rEvt.GetPosPixel() );
+}
+
+/*************************************************************************
+|* SvResizeWindow::MouseMove()
+|*
+|* Description
+*************************************************************************/
+void SvResizeWindow::MouseMove( const MouseEvent & rEvt )
+{
+ if( m_aResizer.GetGrab() == -1 )
+ SelectMouse( rEvt.GetPosPixel() );
+ else
+ {
+ tools::Rectangle aRect( m_aResizer.GetTrackRectPixel( rEvt.GetPosPixel() ) );
+ Point aDiff = GetPosPixel();
+ aRect.SetPos( aRect.TopLeft() + aDiff );
+ m_aResizer.ValidateRect( aRect );
+
+ m_pWrapper->QueryObjAreaPixel( aRect );
+ aRect.SetPos( aRect.TopLeft() - aDiff );
+ Point aPos = m_aResizer.GetTrackPosPixel( aRect );
+
+ SelectMouse( aPos );
+ }
+}
+
+/*************************************************************************
+|* SvResizeWindow::MouseButtonUp()
+|*
+|* Description
+*************************************************************************/
+void SvResizeWindow::MouseButtonUp( const MouseEvent & rEvt )
+{
+ if( m_aResizer.GetGrab() == -1 )
+ return;
+
+ tools::Rectangle aRect( m_aResizer.GetTrackRectPixel( rEvt.GetPosPixel() ) );
+ Point aDiff = GetPosPixel();
+ aRect.SetPos( aRect.TopLeft() + aDiff );
+ // aRect -= GetAllBorderPixel();
+ m_aResizer.ValidateRect( aRect );
+
+ m_pWrapper->QueryObjAreaPixel( aRect );
+
+ tools::Rectangle aOutRect;
+ if( m_aResizer.SelectRelease( this, rEvt.GetPosPixel(), aOutRect ) )
+ {
+ m_nMoveGrab = -1;
+ SetPointer( m_aOldPointer );
+ m_pWrapper->RequestObjAreaPixel( aRect );
+ }
+}
+
+/*************************************************************************
+|* SvResizeWindow::KeyEvent()
+|*
+|* Description
+*************************************************************************/
+void SvResizeWindow::KeyInput( const KeyEvent & rEvt )
+{
+ if( rEvt.GetKeyCode().GetCode() == KEY_ESCAPE )
+ {
+ m_aResizer.Release( this );
+ m_pWrapper->InplaceDeactivate();
+ }
+}
+
+/*************************************************************************
+|* SvResizeWindow::Resize()
+|*
+|* Description
+*************************************************************************/
+void SvResizeWindow::Resize()
+{
+ m_aResizer.InvalidateBorder( this ); // old area
+ m_aResizer.SetOuterRectPixel( tools::Rectangle( Point(), GetOutputSizePixel() ) );
+ m_aResizer.InvalidateBorder( this ); // new area
+}
+
+/*************************************************************************
+|* SvResizeWindow::Paint()
+|*
+|* Description
+*************************************************************************/
+void SvResizeWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle & /*rRect*/ )
+{
+ m_aResizer.Draw(rRenderContext);
+}
+
+bool SvResizeWindow::PreNotify( NotifyEvent& rEvt )
+{
+ if ( rEvt.GetType() == NotifyEventType::GETFOCUS && !m_bActive )
+ {
+ m_bActive = true;
+ m_pWrapper->Activated();
+ }
+
+ return Window::PreNotify(rEvt);
+}
+
+bool SvResizeWindow::EventNotify( NotifyEvent& rEvt )
+{
+ if ( rEvt.GetType() == NotifyEventType::LOSEFOCUS && m_bActive )
+ {
+ bool bHasFocus = HasChildPathFocus(true);
+ if ( !bHasFocus )
+ {
+ m_bActive = false;
+ m_pWrapper->Deactivated();
+ }
+ }
+
+ return Window::EventNotify(rEvt);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/hatchwindow/ipwin.hxx b/toolkit/source/hatchwindow/ipwin.hxx
new file mode 100644
index 0000000000..72567ce268
--- /dev/null
+++ b/toolkit/source/hatchwindow/ipwin.hxx
@@ -0,0 +1,92 @@
+/* -*- 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 .
+ */
+
+#pragma once
+
+#include <tools/gen.hxx>
+#include <vcl/window.hxx>
+#include <array>
+
+/********************** SvResizeHelper ***********************************
+*************************************************************************/
+class SvResizeHelper
+{
+ Size aBorder;
+ tools::Rectangle aOuter;
+ short nGrab; // -1 no Grab, 0 - 7, 8 = Move, see FillHandle...
+ Point aSelPos;
+public:
+ SvResizeHelper();
+
+ short GetGrab() const
+ {
+ return nGrab;
+ }
+ void SetBorderPixel(const Size & rBorderP)
+ {
+ aBorder = rBorderP;
+ }
+ void SetOuterRectPixel(const tools::Rectangle& rRect)
+ {
+ aOuter = rRect;
+ }
+ // Clockwise, start at upper left
+
+ std::array<tools::Rectangle,8> FillHandleRectsPixel() const;
+ std::array<tools::Rectangle,4> FillMoveRectsPixel() const;
+ void Draw(vcl::RenderContext& rRenderContext);
+ void InvalidateBorder( vcl::Window * );
+ bool SelectBegin( vcl::Window *, const Point & rPos );
+ short SelectMove( vcl::Window * pWin, const Point & rPos );
+ Point GetTrackPosPixel( const tools::Rectangle & rRect ) const;
+ tools::Rectangle GetTrackRectPixel( const Point & rTrackPos ) const;
+ void ValidateRect( tools::Rectangle & rValidate ) const;
+ bool SelectRelease( vcl::Window *, const Point & rPos, tools::Rectangle & rOutPosSize );
+ void Release( vcl::Window * pWin );
+};
+
+/********************** SvResizeWindow ***********************************
+*************************************************************************/
+class VCLXHatchWindow;
+class SvResizeWindow : public vcl::Window
+{
+ PointerStyle m_aOldPointer;
+ short m_nMoveGrab; // last pointer type
+ SvResizeHelper m_aResizer;
+ bool m_bActive;
+
+ VCLXHatchWindow* m_pWrapper;
+public:
+ SvResizeWindow( vcl::Window* pParent, VCLXHatchWindow* pWrapper );
+
+ void SetHatchBorderPixel( const Size & rSize );
+
+ void SelectMouse( const Point & rPos );
+ virtual void MouseButtonUp( const MouseEvent & rEvt ) override;
+ virtual void MouseMove( const MouseEvent & rEvt ) override;
+ virtual void MouseButtonDown( const MouseEvent & rEvt ) override;
+ virtual void KeyInput( const KeyEvent & rEvt ) override;
+ virtual void Resize() override;
+ virtual void Paint( vcl::RenderContext& /*rRenderContext*/, const tools::Rectangle & ) override;
+ virtual bool EventNotify( NotifyEvent& rNEvt ) override;
+ virtual bool PreNotify( NotifyEvent& rNEvt ) override;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/helper/accessibilityclient.cxx b/toolkit/source/helper/accessibilityclient.cxx
new file mode 100644
index 0000000000..cad81b3a91
--- /dev/null
+++ b/toolkit/source/helper/accessibilityclient.cxx
@@ -0,0 +1,235 @@
+/* -*- 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 <config_feature_desktop.h>
+#include <config_wasm_strip.h>
+
+#include <sal/config.h>
+
+#include <toolkit/helper/accessiblefactory.hxx>
+#include <osl/module.h>
+#include <osl/diagnose.h>
+#include <osl/mutex.hxx>
+#include <rtl/ref.hxx>
+#include <tools/svlibrary.h>
+
+#include <helper/accessibilityclient.hxx>
+
+namespace toolkit
+{
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::accessibility;
+
+ namespace
+ {
+#ifndef DISABLE_DYNLOADING
+ oslModule s_hAccessibleImplementationModule = nullptr;
+#endif
+#if HAVE_FEATURE_DESKTOP
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+ GetStandardAccComponentFactory s_pAccessibleFactoryFunc = nullptr;
+#endif
+#endif
+ ::rtl::Reference< IAccessibleFactory > s_pFactory;
+ }
+
+
+ //= AccessibleDummyFactory
+
+ namespace {
+
+ class AccessibleDummyFactory:
+ public IAccessibleFactory
+ {
+ public:
+ AccessibleDummyFactory();
+ AccessibleDummyFactory(const AccessibleDummyFactory&) = delete;
+ AccessibleDummyFactory& operator=(const AccessibleDummyFactory&) = delete;
+
+ protected:
+ virtual ~AccessibleDummyFactory() override;
+
+ public:
+ // IAccessibleFactory
+ css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXButton* /*_pXWindow*/ ) override
+ {
+ return nullptr;
+ }
+ css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXCheckBox* /*_pXWindow*/ ) override
+ {
+ return nullptr;
+ }
+ css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXRadioButton* /*_pXWindow*/ ) override
+ {
+ return nullptr;
+ }
+ css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXListBox* /*_pXWindow*/ ) override
+ {
+ return nullptr;
+ }
+ css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXFixedHyperlink* /*_pXWindow*/ ) override
+ {
+ return nullptr;
+ }
+ css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXFixedText* /*_pXWindow*/ ) override
+ {
+ return nullptr;
+ }
+ css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXScrollBar* /*_pXWindow*/ ) override
+ {
+ return nullptr;
+ }
+ css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXEdit* /*_pXWindow*/ ) override
+ {
+ return nullptr;
+ }
+ css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXMultiLineEdit* /*_pXWindow*/ ) override
+ {
+ return nullptr;
+ }
+ css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXComboBox* /*_pXWindow*/ ) override
+ {
+ return nullptr;
+ }
+ css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXToolBox* /*_pXWindow*/ ) override
+ {
+ return nullptr;
+ }
+ css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXHeaderBar* /*_pXWindow*/ ) override
+ {
+ return nullptr;
+ }
+ css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( SVTXNumericField* /*_pXWindow*/ ) override
+ {
+ return nullptr;
+ }
+ css::uno::Reference< css::accessibility::XAccessibleContext >
+ createAccessibleContext( VCLXWindow* /*_pXWindow*/ ) override
+ {
+ return nullptr;
+ }
+ css::uno::Reference< css::accessibility::XAccessible >
+ createAccessible( Menu* /*_pMenu*/, bool /*_bIsMenuBar*/ ) override
+ {
+ return nullptr;
+ }
+ };
+
+ }
+
+ AccessibleDummyFactory::AccessibleDummyFactory()
+ {
+ }
+
+
+ AccessibleDummyFactory::~AccessibleDummyFactory()
+ {
+ }
+
+
+ //= AccessibilityClient
+
+
+ AccessibilityClient::AccessibilityClient()
+ :m_bInitialized( false )
+ {
+ }
+
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+#if HAVE_FEATURE_DESKTOP
+#ifndef DISABLE_DYNLOADING
+ extern "C" { static void thisModule() {} }
+#else
+ extern "C" void *getStandardAccessibleFactory();
+#endif
+#endif // HAVE_FEATURE_DESKTOP
+#endif // ENABLE_WASM_STRIP_ACCESSIBILITY
+
+ void AccessibilityClient::ensureInitialized()
+ {
+ if ( m_bInitialized )
+ return;
+
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+
+#if !ENABLE_WASM_STRIP_ACCESSIBILITY
+#if HAVE_FEATURE_DESKTOP
+ // load the library implementing the factory
+ if (!s_pFactory)
+ {
+#ifndef DISABLE_DYNLOADING
+ s_hAccessibleImplementationModule = osl_loadModuleRelative( &thisModule, u"" SVLIBRARY( "acc" ) ""_ustr.pData, 0 );
+ if ( s_hAccessibleImplementationModule != nullptr )
+ {
+ s_pAccessibleFactoryFunc = reinterpret_cast<GetStandardAccComponentFactory>(
+ osl_getFunctionSymbol( s_hAccessibleImplementationModule, u"getStandardAccessibleFactory"_ustr.pData ));
+
+ }
+ OSL_ENSURE( s_pAccessibleFactoryFunc, "AccessibilityClient::ensureInitialized: could not load the library, or not retrieve the needed symbol!" );
+#else
+ s_pAccessibleFactoryFunc = getStandardAccessibleFactory;
+#endif // DISABLE_DYNLOADING
+
+ // get a factory instance
+ if ( s_pAccessibleFactoryFunc )
+ {
+ IAccessibleFactory* pFactory = static_cast< IAccessibleFactory* >( (*s_pAccessibleFactoryFunc)() );
+ OSL_ENSURE( pFactory, "AccessibilityClient::ensureInitialized: no factory provided by the A11Y lib!" );
+ if ( pFactory )
+ {
+ s_pFactory = pFactory;
+ pFactory->release();
+ }
+ }
+ }
+#endif // HAVE_FEATURE_DESKTOP
+#endif // ENABLE_WASM_STRIP_ACCESSIBILITY
+
+ if (!s_pFactory)
+ // the attempt to load the lib, or to create the factory, failed
+ // -> fall back to a dummy factory
+ s_pFactory = new AccessibleDummyFactory;
+
+ m_bInitialized = true;
+ }
+
+ IAccessibleFactory& AccessibilityClient::getFactory()
+ {
+ ensureInitialized();
+ OSL_ENSURE( s_pFactory.is(), "AccessibilityClient::getFactory: at least a dummy factory should have been created!" );
+ return *s_pFactory;
+ }
+
+
+} // namespace toolkit
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/helper/btndlg.cxx b/toolkit/source/helper/btndlg.cxx
new file mode 100644
index 0000000000..a2471c3f92
--- /dev/null
+++ b/toolkit/source/helper/btndlg.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 <vcl/toolkit/button.hxx>
+#include <vcl/stdtext.hxx>
+#include <helper/btndlg.hxx>
+#include <sal/log.hxx>
+#include <map>
+#include <memory>
+
+struct ImplBtnDlgItem
+{
+ sal_uInt16 mnId;
+ bool mbOwnButton;
+ tools::Long mnSepSize;
+ VclPtr<PushButton> mpPushButton;
+
+ ImplBtnDlgItem() : mnId(0), mbOwnButton(false), mnSepSize(0) {}
+};
+
+void ButtonDialog::ImplInitButtonDialogData()
+{
+ mnButtonSize = 0;
+ mnCurButtonId = 0;
+ mnFocusButtonId = BUTTONDIALOG_BUTTON_NOTFOUND;
+ mbFormat = true;
+}
+
+ButtonDialog::ButtonDialog( WindowType nType ) :
+ Dialog( nType )
+{
+ ImplInitButtonDialogData();
+}
+
+ButtonDialog::~ButtonDialog()
+{
+ disposeOnce();
+}
+
+void ButtonDialog::dispose()
+{
+ for (auto & it : m_ItemList)
+ {
+ if ( it->mbOwnButton )
+ it->mpPushButton.disposeAndClear();
+ }
+ m_ItemList.clear();
+ Dialog::dispose();
+}
+
+VclPtr<PushButton> ButtonDialog::ImplCreatePushButton( ButtonDialogFlags nBtnFlags )
+{
+ VclPtr<PushButton> pBtn;
+ WinBits nStyle = 0;
+
+ if ( nBtnFlags & ButtonDialogFlags::Default )
+ nStyle |= WB_DEFBUTTON;
+ if ( nBtnFlags & ButtonDialogFlags::Cancel )
+ pBtn = VclPtr<CancelButton>::Create( this, nStyle );
+ else if ( nBtnFlags & ButtonDialogFlags::OK )
+ pBtn = VclPtr<OKButton>::Create( this, nStyle );
+ else if ( nBtnFlags & ButtonDialogFlags::Help )
+ pBtn = VclPtr<HelpButton>::Create( this, nStyle );
+ else
+ pBtn = VclPtr<PushButton>::Create( this, nStyle );
+
+ if ( !(nBtnFlags & ButtonDialogFlags::Help) )
+ pBtn->SetClickHdl( LINK( this, ButtonDialog, ImplClickHdl ) );
+
+ return pBtn;
+}
+
+tools::Long ButtonDialog::ImplGetButtonSize()
+{
+ if ( !mbFormat )
+ return mnButtonSize;
+
+ // Calculate ButtonSize
+ tools::Long nLastSepSize = 0;
+ tools::Long nSepSize = 0;
+ maCtrlSize = Size( IMPL_MINSIZE_BUTTON_WIDTH, IMPL_MINSIZE_BUTTON_HEIGHT );
+
+ for (const auto & it : m_ItemList)
+ {
+ nSepSize += nLastSepSize;
+
+ tools::Long nTxtWidth = it->mpPushButton->GetOutDev()->GetCtrlTextWidth(it->mpPushButton->GetText());
+ nTxtWidth += IMPL_EXTRA_BUTTON_WIDTH;
+
+ if ( nTxtWidth > maCtrlSize.Width() )
+ maCtrlSize.setWidth( nTxtWidth );
+
+ tools::Long nTxtHeight = it->mpPushButton->GetTextHeight();
+ nTxtHeight += IMPL_EXTRA_BUTTON_HEIGHT;
+
+ if ( nTxtHeight > maCtrlSize.Height() )
+ maCtrlSize.setHeight( nTxtHeight );
+
+ nSepSize += it->mnSepSize;
+
+ if ( GetStyle() & WB_HORZ )
+ nLastSepSize = IMPL_SEP_BUTTON_X;
+ else
+ nLastSepSize = IMPL_SEP_BUTTON_Y;
+ }
+
+ size_t const nButtonCount = m_ItemList.size();
+
+ if ( GetStyle() & WB_HORZ )
+ mnButtonSize = nSepSize + (nButtonCount*maCtrlSize.Width());
+ else
+ mnButtonSize = nSepSize + (nButtonCount*maCtrlSize.Height());
+
+ return mnButtonSize;
+}
+
+void ButtonDialog::ImplPosControls()
+{
+ if ( !mbFormat )
+ return;
+
+ // Create PushButtons and determine Sizes
+ ImplGetButtonSize();
+
+ // determine dialog size
+ Size aDlgSize = maPageSize;
+ tools::Long nX;
+ tools::Long nY;
+ if ( GetStyle() & WB_HORZ )
+ {
+ if ( mnButtonSize+(IMPL_DIALOG_OFFSET*2) > aDlgSize.Width() )
+ aDlgSize.setWidth( mnButtonSize+(IMPL_DIALOG_OFFSET*2) );
+ if ( GetStyle() & WB_LEFT )
+ nX = IMPL_DIALOG_OFFSET;
+ else if ( GetStyle() & WB_RIGHT )
+ nX = aDlgSize.Width()-mnButtonSize-IMPL_DIALOG_OFFSET;
+ else
+ nX = (aDlgSize.Width()-mnButtonSize)/2;
+
+ aDlgSize.AdjustHeight(IMPL_DIALOG_OFFSET+maCtrlSize.Height() );
+ nY = aDlgSize.Height()-maCtrlSize.Height()-IMPL_DIALOG_OFFSET;
+ }
+ else
+ {
+ if ( mnButtonSize+(IMPL_DIALOG_OFFSET*2) > aDlgSize.Height() )
+ aDlgSize.setHeight( mnButtonSize+(IMPL_DIALOG_OFFSET*2) );
+ if ( GetStyle() & WB_BOTTOM )
+ nY = aDlgSize.Height()-mnButtonSize-IMPL_DIALOG_OFFSET;
+ else if ( GetStyle() & WB_VCENTER )
+ nY = (aDlgSize.Height()-mnButtonSize)/2;
+ else
+ nY = IMPL_DIALOG_OFFSET;
+
+ aDlgSize.AdjustWidth(IMPL_DIALOG_OFFSET+maCtrlSize.Width() );
+ nX = aDlgSize.Width()-maCtrlSize.Width()-IMPL_DIALOG_OFFSET;
+ }
+
+ // Arrange PushButtons
+ for (auto & it : m_ItemList)
+ {
+ if ( GetStyle() & WB_HORZ )
+ nX += it->mnSepSize;
+ else
+ nY += it->mnSepSize;
+
+ it->mpPushButton->SetPosSizePixel( Point( nX, nY ), maCtrlSize );
+ it->mpPushButton->Show();
+
+ if ( GetStyle() & WB_HORZ )
+ nX += maCtrlSize.Width()+IMPL_SEP_BUTTON_X;
+ else
+ nY += maCtrlSize.Height()+IMPL_SEP_BUTTON_Y;
+ }
+
+ SetOutputSizePixel(aDlgSize);
+ SetMinOutputSizePixel(aDlgSize);
+
+ mbFormat = false;
+}
+
+IMPL_LINK( ButtonDialog, ImplClickHdl, Button*, pBtn, void )
+{
+ for (const auto & it : m_ItemList)
+ {
+ if ( it->mpPushButton == pBtn )
+ {
+ mnCurButtonId = it->mnId;
+ if ( IsInExecute() )
+ EndDialog( mnCurButtonId );
+ break;
+ }
+ }
+}
+
+void ButtonDialog::Resize()
+{
+}
+
+void ButtonDialog::StateChanged( StateChangedType nType )
+{
+ if ( nType == StateChangedType::InitShow )
+ {
+ ImplPosControls();
+ for (auto & it : m_ItemList)
+ {
+ if ( it->mpPushButton && it->mbOwnButton )
+ it->mpPushButton->SetZOrder(nullptr, ZOrderFlags::Last);
+ }
+
+ // Set focus on default button.
+ if ( mnFocusButtonId != BUTTONDIALOG_BUTTON_NOTFOUND )
+ {
+ for (auto & it : m_ItemList)
+ {
+ if (it->mnId == mnFocusButtonId )
+ {
+ if (it->mpPushButton->IsVisible())
+ it->mpPushButton->GrabFocus();
+
+ break;
+ }
+ }
+ }
+ }
+
+ Dialog::StateChanged( nType );
+}
+
+void ButtonDialog::AddButton( StandardButtonType eType, sal_uInt16 nId,
+ ButtonDialogFlags nBtnFlags, tools::Long nSepPixel )
+{
+ // PageItem anlegen
+ std::unique_ptr<ImplBtnDlgItem> pItem(new ImplBtnDlgItem);
+ pItem->mnId = nId;
+ pItem->mbOwnButton = true;
+ pItem->mnSepSize = nSepPixel;
+
+ if ( eType == StandardButtonType::OK )
+ nBtnFlags |= ButtonDialogFlags::OK;
+ else if ( eType == StandardButtonType::Help )
+ nBtnFlags |= ButtonDialogFlags::Help;
+ else if ( (eType == StandardButtonType::Cancel) || (eType == StandardButtonType::Close) )
+ nBtnFlags |= ButtonDialogFlags::Cancel;
+ pItem->mpPushButton = ImplCreatePushButton( nBtnFlags );
+
+ // Standard-Buttons have the right text already
+ if ( !((eType == StandardButtonType::OK && pItem->mpPushButton->GetType() == WindowType::OKBUTTON) ||
+ (eType == StandardButtonType::Cancel && pItem->mpPushButton->GetType() == WindowType::CANCELBUTTON) ||
+ (eType == StandardButtonType::Help && pItem->mpPushButton->GetType() == WindowType::HELPBUTTON)) )
+ {
+ std::map<StandardButtonType, OUString> mapButtonTypeToID = {{StandardButtonType::Yes, "yes"},
+ {StandardButtonType::No, "no"}, {StandardButtonType::Retry, "retry"},
+ {StandardButtonType::Close, "close"}, {StandardButtonType::More, "more"},
+ {StandardButtonType::Ignore, "ignore"}, {StandardButtonType::Abort, "abort"},
+ {StandardButtonType::Less, "less"}, {StandardButtonType::Count, "count"}};
+ auto itr = mapButtonTypeToID.find(eType);
+ if (itr != mapButtonTypeToID.end())
+ pItem->mpPushButton->set_id(itr->second);
+ pItem->mpPushButton->SetText( GetStandardText( eType ) );
+ }
+
+ if ( nBtnFlags & ButtonDialogFlags::Focus )
+ mnFocusButtonId = nId;
+
+ m_ItemList.push_back(std::move(pItem));
+
+ mbFormat = true;
+}
+
+void ButtonDialog::RemoveButton( sal_uInt16 nId )
+{
+ auto it = std::find_if(m_ItemList.begin(), m_ItemList.end(),
+ [&nId](const std::unique_ptr<ImplBtnDlgItem>& rItem) { return rItem->mnId == nId; });
+ if (it != m_ItemList.end())
+ {
+ (*it)->mpPushButton->Hide();
+ if ((*it)->mbOwnButton)
+ (*it)->mpPushButton.disposeAndClear();
+ else
+ (*it)->mpPushButton.clear();
+ m_ItemList.erase(it);
+ return;
+ }
+
+ SAL_WARN( "vcl.window", "ButtonDialog::RemoveButton(): ButtonId invalid" );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/helper/imagealign.cxx b/toolkit/source/helper/imagealign.cxx
new file mode 100644
index 0000000000..43e7cb012c
--- /dev/null
+++ b/toolkit/source/helper/imagealign.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 <com/sun/star/awt/ImagePosition.hpp>
+#include <com/sun/star/awt/ImageAlign.hpp>
+
+#include <helper/imagealign.hxx>
+#include <osl/diagnose.h>
+
+namespace toolkit
+{
+
+
+ using namespace ::com::sun::star::awt::ImagePosition;
+ using namespace ::com::sun::star::awt::ImageAlign;
+
+ sal_Int16 translateImagePosition( ImageAlign _eVCLAlign )
+ {
+ sal_Int16 nReturn = AboveCenter;
+ switch ( _eVCLAlign )
+ {
+ case ImageAlign::Left: nReturn = LeftCenter; break;
+ case ImageAlign::Top: nReturn = AboveCenter; break;
+ case ImageAlign::Right: nReturn = RightCenter; break;
+ case ImageAlign::Bottom: nReturn = BelowCenter; break;
+ case ImageAlign::LeftTop: nReturn = LeftTop; break;
+ case ImageAlign::LeftBottom: nReturn = LeftBottom; break;
+ case ImageAlign::TopLeft: nReturn = AboveLeft; break;
+ case ImageAlign::TopRight: nReturn = AboveRight; break;
+ case ImageAlign::RightTop: nReturn = RightTop; break;
+ case ImageAlign::RightBottom: nReturn = RightBottom; break;
+ case ImageAlign::BottomLeft: nReturn = BelowLeft; break;
+ case ImageAlign::BottomRight: nReturn = BelowRight; break;
+ case ImageAlign::Center: nReturn = Centered; break;
+ default:
+ OSL_FAIL( "translateImagePosition: unknown IMAGEALIGN value!" );
+ }
+ return nReturn;
+ }
+
+ ImageAlign translateImagePosition( sal_Int16 _eUNOAlign )
+ {
+ ImageAlign nReturn = ImageAlign::Top;
+ switch ( _eUNOAlign )
+ {
+ case LeftCenter: nReturn = ImageAlign::Left; break;
+ case AboveCenter: nReturn = ImageAlign::Top; break;
+ case RightCenter: nReturn = ImageAlign::Right; break;
+ case BelowCenter: nReturn = ImageAlign::Bottom; break;
+ case LeftTop: nReturn = ImageAlign::LeftTop; break;
+ case LeftBottom: nReturn = ImageAlign::LeftBottom; break;
+ case AboveLeft: nReturn = ImageAlign::TopLeft; break;
+ case AboveRight: nReturn = ImageAlign::TopRight; break;
+ case RightTop: nReturn = ImageAlign::RightTop; break;
+ case RightBottom: nReturn = ImageAlign::RightBottom; break;
+ case BelowLeft: nReturn = ImageAlign::BottomLeft; break;
+ case BelowRight: nReturn = ImageAlign::BottomRight; break;
+ case Centered: nReturn = ImageAlign::Center; break;
+ default:
+ OSL_FAIL( "translateImagePosition: unknown css.awt.ImagePosition value!" );
+ }
+ return nReturn;
+ }
+
+ sal_Int16 getCompatibleImageAlign( ImageAlign _eAlign )
+ {
+ sal_Int16 nReturn = TOP;
+ switch ( _eAlign )
+ {
+ case ImageAlign::LeftTop:
+ case ImageAlign::Left:
+ case ImageAlign::LeftBottom: nReturn = LEFT; break;
+
+ case ImageAlign::TopLeft:
+ case ImageAlign::Top:
+ case ImageAlign::TopRight: nReturn = TOP; break;
+
+ case ImageAlign::RightTop:
+ case ImageAlign::Right:
+ case ImageAlign::RightBottom: nReturn = RIGHT; break;
+
+ case ImageAlign::BottomLeft:
+ case ImageAlign::Bottom:
+ case ImageAlign::BottomRight: nReturn = BOTTOM; break;
+
+ case ImageAlign::Center: nReturn = TOP; break;
+ default:
+ OSL_FAIL( "getCompatibleImageAlign: unknown IMAGEALIGN value!" );
+ }
+ return nReturn;
+ }
+
+ sal_Int16 getExtendedImagePosition( sal_Int16 _nImageAlign )
+ {
+ sal_Int16 nReturn = AboveCenter;
+ switch ( _nImageAlign )
+ {
+ case LEFT: nReturn = LeftCenter; break;
+ case TOP: nReturn = AboveCenter; break;
+ case RIGHT: nReturn = RightCenter; break;
+ case BOTTOM: nReturn = BelowCenter; break;
+ default:
+ OSL_FAIL( "getExtendedImagePosition: unknown ImageAlign value!" );
+ }
+ return nReturn;
+ }
+
+
+} // namespace toolkit
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/helper/listenermultiplexer.cxx b/toolkit/source/helper/listenermultiplexer.cxx
new file mode 100644
index 0000000000..1c3ac1de52
--- /dev/null
+++ b/toolkit/source/helper/listenermultiplexer.cxx
@@ -0,0 +1,247 @@
+/* -*- 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 <toolkit/helper/listenermultiplexer.hxx>
+#include <toolkit/helper/macros.hxx>
+#include <com/sun/star/lang/DisposedException.hpp>
+
+// class EventListenerMultiplexer
+
+EventListenerMultiplexer::EventListenerMultiplexer( ::cppu::OWeakObject& rSource )
+ : ListenerMultiplexerBase( rSource )
+{
+}
+
+void SAL_CALL EventListenerMultiplexer::acquire() noexcept
+{
+ return ListenerMultiplexerBase::acquire();
+}
+
+void SAL_CALL EventListenerMultiplexer::release() noexcept
+{
+ return ListenerMultiplexerBase::release();
+}
+
+// css::uno::XInterface
+css::uno::Any EventListenerMultiplexer::queryInterface( const css::uno::Type & rType )
+{
+ css::uno::Any aRet = ::cppu::queryInterface( rType,
+ static_cast< css::lang::XEventListener* >(this) );
+ return (aRet.hasValue() ? aRet : ListenerMultiplexerBase::queryInterface( rType ));
+}
+
+// css::lang::XEventListener
+void EventListenerMultiplexer::disposing( const css::lang::EventObject& )
+{
+}
+
+
+// class FocusListenerMultiplexer
+
+IMPL_LISTENERMULTIPLEXER_BASEMETHODS( FocusListenerMultiplexer, css::awt::XFocusListener )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( FocusListenerMultiplexer, css::awt::XFocusListener, focusGained, css::awt::FocusEvent )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( FocusListenerMultiplexer, css::awt::XFocusListener, focusLost, css::awt::FocusEvent )
+
+
+// class WindowListenerMultiplexer
+
+IMPL_LISTENERMULTIPLEXER_BASEMETHODS( WindowListenerMultiplexer, css::awt::XWindowListener )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( WindowListenerMultiplexer, css::awt::XWindowListener, windowResized, css::awt::WindowEvent )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( WindowListenerMultiplexer, css::awt::XWindowListener, windowMoved, css::awt::WindowEvent )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( WindowListenerMultiplexer, css::awt::XWindowListener, windowShown, css::lang::EventObject )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( WindowListenerMultiplexer, css::awt::XWindowListener, windowHidden, css::lang::EventObject )
+
+
+// class VclContainerListenerMultiplexer
+
+IMPL_LISTENERMULTIPLEXER_BASEMETHODS( VclContainerListenerMultiplexer, css::awt::XVclContainerListener )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( VclContainerListenerMultiplexer, css::awt::XVclContainerListener, windowAdded, css::awt::VclContainerEvent )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( VclContainerListenerMultiplexer, css::awt::XVclContainerListener, windowRemoved, css::awt::VclContainerEvent )
+
+
+// class KeyListenerMultiplexer
+
+IMPL_LISTENERMULTIPLEXER_BASEMETHODS( KeyListenerMultiplexer, css::awt::XKeyListener )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( KeyListenerMultiplexer, css::awt::XKeyListener, keyPressed, css::awt::KeyEvent )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( KeyListenerMultiplexer, css::awt::XKeyListener, keyReleased, css::awt::KeyEvent )
+
+
+// class MouseListenerMultiplexer
+
+IMPL_LISTENERMULTIPLEXER_BASEMETHODS( MouseListenerMultiplexer, css::awt::XMouseListener )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( MouseListenerMultiplexer, css::awt::XMouseListener, mousePressed, css::awt::MouseEvent )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( MouseListenerMultiplexer, css::awt::XMouseListener, mouseReleased, css::awt::MouseEvent )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( MouseListenerMultiplexer, css::awt::XMouseListener, mouseEntered, css::awt::MouseEvent )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( MouseListenerMultiplexer, css::awt::XMouseListener, mouseExited, css::awt::MouseEvent )
+
+
+// class MouseMotionListenerMultiplexer
+
+IMPL_LISTENERMULTIPLEXER_BASEMETHODS( MouseMotionListenerMultiplexer, css::awt::XMouseMotionListener )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( MouseMotionListenerMultiplexer, css::awt::XMouseMotionListener, mouseDragged, css::awt::MouseEvent )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( MouseMotionListenerMultiplexer, css::awt::XMouseMotionListener, mouseMoved, css::awt::MouseEvent )
+
+
+// class PaintListenerMultiplexer
+
+IMPL_LISTENERMULTIPLEXER_BASEMETHODS( PaintListenerMultiplexer, css::awt::XPaintListener )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( PaintListenerMultiplexer, css::awt::XPaintListener, windowPaint, css::awt::PaintEvent )
+
+
+// class TopWindowListenerMultiplexer
+
+IMPL_LISTENERMULTIPLEXER_BASEMETHODS( TopWindowListenerMultiplexer, css::awt::XTopWindowListener )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TopWindowListenerMultiplexer, css::awt::XTopWindowListener, windowOpened, css::lang::EventObject )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TopWindowListenerMultiplexer, css::awt::XTopWindowListener, windowClosing, css::lang::EventObject )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TopWindowListenerMultiplexer, css::awt::XTopWindowListener, windowClosed, css::lang::EventObject )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TopWindowListenerMultiplexer, css::awt::XTopWindowListener, windowMinimized, css::lang::EventObject )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TopWindowListenerMultiplexer, css::awt::XTopWindowListener, windowNormalized, css::lang::EventObject )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TopWindowListenerMultiplexer, css::awt::XTopWindowListener, windowActivated, css::lang::EventObject )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TopWindowListenerMultiplexer, css::awt::XTopWindowListener, windowDeactivated, css::lang::EventObject )
+
+
+// class TextListenerMultiplexer
+
+IMPL_LISTENERMULTIPLEXER_BASEMETHODS( TextListenerMultiplexer, css::awt::XTextListener )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TextListenerMultiplexer, css::awt::XTextListener, textChanged, css::awt::TextEvent )
+
+
+// class ActionListenerMultiplexer
+
+IMPL_LISTENERMULTIPLEXER_BASEMETHODS( ActionListenerMultiplexer, css::awt::XActionListener )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( ActionListenerMultiplexer, css::awt::XActionListener, actionPerformed, css::awt::ActionEvent )
+
+
+// class ItemListenerMultiplexer
+
+IMPL_LISTENERMULTIPLEXER_BASEMETHODS( ItemListenerMultiplexer, css::awt::XItemListener )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( ItemListenerMultiplexer, css::awt::XItemListener, itemStateChanged, css::awt::ItemEvent )
+
+
+// class TabListenerMultiplexer
+
+IMPL_LISTENERMULTIPLEXER_BASEMETHODS( TabListenerMultiplexer, css::awt::XTabListener )
+
+void TabListenerMultiplexer::inserted( sal_Int32 evt )
+IMPL_TABLISTENERMULTIPLEXER_LISTENERMETHOD_BODY_1PARAM( TabListenerMultiplexer, css::awt::XTabListener, inserted, ::sal_Int32 )
+
+void TabListenerMultiplexer::removed( sal_Int32 evt )
+IMPL_TABLISTENERMULTIPLEXER_LISTENERMETHOD_BODY_1PARAM( TabListenerMultiplexer, css::awt::XTabListener, removed, ::sal_Int32 )
+
+void TabListenerMultiplexer::changed( sal_Int32 evt, const css::uno::Sequence< css::beans::NamedValue >& evt2 )
+{
+ sal_Int32 aMulti( evt );
+ std::unique_lock g(m_aMutex);
+ ::comphelper::OInterfaceIteratorHelper4 aIt(g, maListeners);
+ g.unlock();
+ while( aIt.hasMoreElements() )
+ {
+ css::uno::Reference<css::awt::XTabListener> xListener(aIt.next());
+ try
+ {
+ xListener->changed( aMulti, evt2 );
+ }
+ catch(const css::lang::DisposedException& e)
+ {
+ OSL_ENSURE( e.Context.is(), "caught DisposedException with empty Context field" );
+ if ( e.Context == xListener || !e.Context.is() )
+ {
+ std::unique_lock g2(m_aMutex);
+ aIt.remove(g2);
+ }
+ }
+ catch(const css::uno::RuntimeException&)
+ {
+ DISPLAY_EXCEPTION( TabListenerMultiplexer, changed )
+ }
+ }
+}
+
+
+void TabListenerMultiplexer::activated( sal_Int32 evt )
+IMPL_TABLISTENERMULTIPLEXER_LISTENERMETHOD_BODY_1PARAM( TabListenerMultiplexer, css::awt::XTabListener, activated, ::sal_Int32 )
+
+void TabListenerMultiplexer::deactivated( sal_Int32 evt )
+IMPL_TABLISTENERMULTIPLEXER_LISTENERMETHOD_BODY_1PARAM( TabListenerMultiplexer, css::awt::XTabListener, deactivated, ::sal_Int32 )
+
+
+// class ContainerListenerMultiplexer
+
+IMPL_LISTENERMULTIPLEXER_BASEMETHODS( ContainerListenerMultiplexer, css::container::XContainerListener )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( ContainerListenerMultiplexer, css::container::XContainerListener, elementInserted, css::container::ContainerEvent )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( ContainerListenerMultiplexer, css::container::XContainerListener, elementRemoved, css::container::ContainerEvent )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( ContainerListenerMultiplexer, css::container::XContainerListener, elementReplaced, css::container::ContainerEvent )
+
+
+// class SpinListenerMultiplexer
+
+IMPL_LISTENERMULTIPLEXER_BASEMETHODS( SpinListenerMultiplexer, css::awt::XSpinListener )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( SpinListenerMultiplexer, css::awt::XSpinListener, up, css::awt::SpinEvent )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( SpinListenerMultiplexer, css::awt::XSpinListener, down, css::awt::SpinEvent )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( SpinListenerMultiplexer, css::awt::XSpinListener, first, css::awt::SpinEvent )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( SpinListenerMultiplexer, css::awt::XSpinListener, last, css::awt::SpinEvent )
+
+
+// class AdjustmentListenerMultiplexer
+
+IMPL_LISTENERMULTIPLEXER_BASEMETHODS( AdjustmentListenerMultiplexer, css::awt::XAdjustmentListener )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( AdjustmentListenerMultiplexer, css::awt::XAdjustmentListener, adjustmentValueChanged, css::awt::AdjustmentEvent )
+
+
+// class MenuListenerMultiplexer
+
+IMPL_LISTENERMULTIPLEXER_BASEMETHODS( MenuListenerMultiplexer, css::awt::XMenuListener )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( MenuListenerMultiplexer, css::awt::XMenuListener, itemHighlighted, css::awt::MenuEvent )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( MenuListenerMultiplexer, css::awt::XMenuListener, itemSelected, css::awt::MenuEvent )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( MenuListenerMultiplexer, css::awt::XMenuListener, itemActivated, css::awt::MenuEvent )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( MenuListenerMultiplexer, css::awt::XMenuListener, itemDeactivated, css::awt::MenuEvent )
+
+
+// class TreeSelectionListenerMultiplexer
+
+IMPL_LISTENERMULTIPLEXER_BASEMETHODS( TreeSelectionListenerMultiplexer, css::view::XSelectionChangeListener )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TreeSelectionListenerMultiplexer, css::view::XSelectionChangeListener, selectionChanged, css::lang::EventObject )
+
+
+// class TreeSelectionListenerMultiplexer
+
+IMPL_LISTENERMULTIPLEXER_BASEMETHODS( TreeExpansionListenerMultiplexer, css::awt::tree::XTreeExpansionListener )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TreeExpansionListenerMultiplexer, css::awt::tree::XTreeExpansionListener, requestChildNodes, css::awt::tree::TreeExpansionEvent )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD_EXCEPTION( TreeExpansionListenerMultiplexer, css::awt::tree::XTreeExpansionListener, treeExpanding, css::awt::tree::TreeExpansionEvent, css::awt::tree::ExpandVetoException )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD_EXCEPTION( TreeExpansionListenerMultiplexer, css::awt::tree::XTreeExpansionListener, treeCollapsing, css::awt::tree::TreeExpansionEvent, css::awt::tree::ExpandVetoException )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TreeExpansionListenerMultiplexer, css::awt::tree::XTreeExpansionListener, treeExpanded, css::awt::tree::TreeExpansionEvent )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TreeExpansionListenerMultiplexer, css::awt::tree::XTreeExpansionListener, treeCollapsed, css::awt::tree::TreeExpansionEvent )
+
+
+// class TreeEditListenerMultiplexer
+
+IMPL_LISTENERMULTIPLEXER_BASEMETHODS( TreeEditListenerMultiplexer, css::awt::tree::XTreeEditListener )
+
+
+// class SelectionListenerMultiplexer
+
+IMPL_LISTENERMULTIPLEXER_BASEMETHODS( SelectionListenerMultiplexer, css::awt::grid::XGridSelectionListener )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( SelectionListenerMultiplexer, css::awt::grid::XGridSelectionListener, selectionChanged, css::awt::grid::GridSelectionEvent )
+
+
+// class SelectionListenerMultiplexer
+
+IMPL_LISTENERMULTIPLEXER_BASEMETHODS( TabPageListenerMultiplexer, css::awt::tab::XTabPageContainerListener )
+IMPL_LISTENERMULTIPLEXER_LISTENERMETHOD( TabPageListenerMultiplexer, css::awt::tab::XTabPageContainerListener, tabPageActivated, css::awt::tab::TabPageActivatedEvent )
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/helper/property.cxx b/toolkit/source/helper/property.cxx
new file mode 100644
index 0000000000..945c4b016a
--- /dev/null
+++ b/toolkit/source/helper/property.cxx
@@ -0,0 +1,335 @@
+/* -*- 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 <helper/property.hxx>
+
+#include <tools/debug.hxx>
+#include <com/sun/star/awt/FontDescriptor.hpp>
+#include <com/sun/star/awt/XDevice.hpp>
+#include <com/sun/star/awt/tree/XTreeDataModel.hpp>
+#include <com/sun/star/awt/grid/XGridDataModel.hpp>
+#include <com/sun/star/awt/grid/XGridColumnModel.hpp>
+#include <com/sun/star/view/SelectionType.hpp>
+#include <com/sun/star/style/VerticalAlignment.hpp>
+#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
+#include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/util/Time.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <algorithm>
+#include <string_view>
+#include <utility>
+#include <unordered_map>
+
+using ::com::sun::star::uno::Any;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::awt::XDevice;
+using ::com::sun::star::awt::FontDescriptor;
+using ::com::sun::star::style::VerticalAlignment;
+using ::com::sun::star::graphic::XGraphic;
+
+using namespace com::sun::star;
+
+namespace {
+
+struct ImplPropertyInfo
+{
+ css::uno::Type aType;
+ sal_uInt16 nPropId;
+ sal_Int16 nAttribs;
+ bool bDependsOnOthers; // eg. VALUE depends on MIN/MAX and must be set after MIN/MAX.
+
+ ImplPropertyInfo( sal_uInt16 nId, const css::uno::Type& rType,
+ sal_Int16 nAttrs, bool bDepends = false )
+ : aType(rType)
+ , nPropId(nId)
+ , nAttribs(nAttrs)
+ , bDependsOnOthers(bDepends)
+ {
+ }
+
+};
+
+}
+
+#define DECL_PROP_1( asciiname, id, type, attrib1 ) \
+ { asciiname, ImplPropertyInfo( BASEPROPERTY_##id, cppu::UnoType<type>::get(), css::beans::PropertyAttribute::attrib1 ) }
+#define DECL_PROP_2( asciiname, id, type, attrib1, attrib2 ) \
+ { asciiname, ImplPropertyInfo( BASEPROPERTY_##id, cppu::UnoType<type>::get(), css::beans::PropertyAttribute::attrib1 | css::beans::PropertyAttribute::attrib2 ) }
+#define DECL_PROP_3( asciiname, id, type, attrib1, attrib2, attrib3 ) \
+ { asciiname, ImplPropertyInfo( BASEPROPERTY_##id, cppu::UnoType<type>::get(), css::beans::PropertyAttribute::attrib1 | css::beans::PropertyAttribute::attrib2 | css::beans::PropertyAttribute::attrib3 ) }
+
+#define DECL_DEP_PROP_2( asciiname, id, type, attrib1, attrib2 ) \
+ { asciiname, ImplPropertyInfo( BASEPROPERTY_##id, cppu::UnoType<type>::get(), css::beans::PropertyAttribute::attrib1 | css::beans::PropertyAttribute::attrib2, true ) }
+#define DECL_DEP_PROP_3( asciiname, id, type, attrib1, attrib2, attrib3 ) \
+ { asciiname, ImplPropertyInfo( BASEPROPERTY_##id, cppu::UnoType<type>::get(), css::beans::PropertyAttribute::attrib1 | css::beans::PropertyAttribute::attrib2 | css::beans::PropertyAttribute::attrib3, true ) }
+
+typedef std::unordered_map<OUString, ImplPropertyInfo> ImpPropertyInfoMap;
+static const ImpPropertyInfoMap & ImplGetPropertyInfos()
+{
+ static const ImpPropertyInfoMap aImplPropertyInfos {
+ DECL_PROP_2 ( "AccessibleName", ACCESSIBLENAME, OUString, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_3 ( "Align", ALIGN, sal_Int16, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_2 ( "Autocomplete", AUTOCOMPLETE, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "AutoHScroll", AUTOHSCROLL, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_1 ( "AutoMnemonics", AUTOMNEMONICS, bool, BOUND ),
+ DECL_PROP_2 ( "AutoToggle", AUTOTOGGLE, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "AutoVScroll", AUTOVSCROLL, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_3 ( "BackgroundColor", BACKGROUNDCOLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_DEP_PROP_2 ( "BlockIncrement", BLOCKINCREMENT, sal_Int32, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_3 ( "Border", BORDER, sal_Int16, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_DEP_PROP_3 ( "BorderColor", BORDERCOLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_2 ( "Closeable", CLOSEABLE, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "CurrencySymbol", CURRENCYSYMBOL, OUString, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "CustomUnitText", CUSTOMUNITTEXT, OUString, BOUND, MAYBEDEFAULT ),
+ DECL_DEP_PROP_3 ( "Date", DATE, util::Date, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_2 ( "DateFormat", EXTDATEFORMAT, sal_Int16, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "DateMax", DATEMAX, util::Date, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "DateMin", DATEMIN, util::Date, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_3 ( "DateShowCentury", DATESHOWCENTURY, bool, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_2 ( "DecimalAccuracy", DECIMALACCURACY, sal_Int16, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "DefaultButton", DEFAULTBUTTON, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "DefaultControl", DEFAULTCONTROL, OUString, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "DesktopAsParent", DESKTOP_AS_PARENT, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "DisplayBackgroundColor", DISPLAYBACKGROUNDCOLOR, sal_Int32, BOUND, MAYBEVOID ),
+ DECL_PROP_2 ( "Dropdown", DROPDOWN, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "EchoChar", ECHOCHAR, sal_Int16, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "EditMask", EDITMASK, OUString, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_3 ( "EffectiveDefault", EFFECTIVE_DEFAULT, Any, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_3 ( "EffectiveMax", EFFECTIVE_MAX, double, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_3 ( "EffectiveMin", EFFECTIVE_MIN, double, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_DEP_PROP_3 ( "EffectiveValue", EFFECTIVE_VALUE, Any, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_2 ( "Enabled", ENABLED, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "EnforceFormat", ENFORCE_FORMAT, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_3 ( "FillColor", FILLCOLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_2 ( "FocusOnClick", FOCUSONCLICK, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "FontRelief", FONTRELIEF, sal_Int16, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "FontEmphasisMark", FONTEMPHASISMARK, sal_Int16, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "FontDescriptor", FONTDESCRIPTOR, FontDescriptor, BOUND, MAYBEDEFAULT ),
+
+ // parts of css::awt::FontDescriptor
+ DECL_PROP_2 ( "FontName", FONTDESCRIPTORPART_NAME, OUString, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "FontStyleName", FONTDESCRIPTORPART_STYLENAME, OUString, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "FontFamily", FONTDESCRIPTORPART_FAMILY, sal_Int16, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "FontCharset", FONTDESCRIPTORPART_CHARSET, sal_Int16, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "FontHeight", FONTDESCRIPTORPART_HEIGHT, float, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "FontWidth", FONTDESCRIPTORPART_WIDTH, sal_Int16, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "FontPitch", FONTDESCRIPTORPART_PITCH, sal_Int16, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "FontWeight", FONTDESCRIPTORPART_WEIGHT, float, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "FontCharWidth", FONTDESCRIPTORPART_CHARWIDTH, float, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "FontOrientation", FONTDESCRIPTORPART_ORIENTATION, float, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "FontSlant", FONTDESCRIPTORPART_SLANT, sal_Int16, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "FontUnderline", FONTDESCRIPTORPART_UNDERLINE, sal_Int16, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "FontStrikeout", FONTDESCRIPTORPART_STRIKEOUT, sal_Int16, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "FontKerning", FONTDESCRIPTORPART_KERNING, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "FontWordLineMode", FONTDESCRIPTORPART_WORDLINEMODE, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "FontType", FONTDESCRIPTORPART_TYPE, sal_Int16, BOUND, MAYBEDEFAULT ),
+
+ DECL_PROP_3 ( "FormatKey", FORMATKEY, sal_Int32, BOUND, MAYBEVOID, TRANSIENT ),
+ DECL_PROP_3 ( "FormatsSupplier", FORMATSSUPPLIER, Reference< css::util::XNumberFormatsSupplier >, BOUND, MAYBEVOID, TRANSIENT ),
+
+ DECL_PROP_2 ( "Graphic", GRAPHIC, Reference< XGraphic >, BOUND, TRANSIENT ),
+ DECL_PROP_2 ( "GroupName", GROUPNAME, OUString, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "HelpText", HELPTEXT, OUString, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "HelpURL", HELPURL, OUString, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "HideInactiveSelection", HIDEINACTIVESELECTION, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "HighContrastMode", HIGHCONTRASTMODE, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "HScroll", HSCROLL, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "HardLineBreaks", HARDLINEBREAKS, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_3 ( "HighlightColor", HIGHLIGHT_COLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID),
+ DECL_PROP_3 ( "HighlightTextColor", HIGHLIGHT_TEXT_COLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID),
+ DECL_PROP_2 ( "ImageAlign", IMAGEALIGN, sal_Int16, BOUND, MAYBEDEFAULT),
+ DECL_PROP_2 ( "ImagePosition", IMAGEPOSITION, sal_Int16, BOUND, MAYBEDEFAULT),
+ DECL_PROP_2 ( "ImageURL", IMAGEURL, css::uno::Any, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_3 ( "ItemSeparatorPos", ITEM_SEPARATOR_POS, sal_Int16, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_2 ( "Label", LABEL, OUString, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_3 ( "LineColor", LINECOLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_2 ( "LineCount", LINECOUNT, sal_Int16, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "LineEndFormat", LINE_END_FORMAT, sal_Int16, BOUND, MAYBEDEFAULT ),
+ DECL_DEP_PROP_2 ( "LineIncrement", LINEINCREMENT, sal_Int32, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "LiteralMask", LITERALMASK, OUString, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "LiveScroll", LIVE_SCROLL, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "MaxTextLen", MAXTEXTLEN, sal_Int16, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "Moveable", MOVEABLE, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_1 ( "MouseTransparent", MOUSETRANSPARENT, bool, BOUND ),
+ DECL_PROP_2 ( "MultiLine", MULTILINE, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "MultiSelection", MULTISELECTION, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "MultiSelectionSimpleMode", MULTISELECTION_SIMPLEMODE, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "NativeWidgetLook", NATIVE_WIDGET_LOOK, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "NoLabel", NOLABEL, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "Orientation", ORIENTATION, sal_Int32, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "PaintTransparent", PAINTTRANSPARENT, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "PluginParent", PLUGINPARENT, sal_Int64, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "PrependCurrencySymbol", CURSYM_POSITION, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "Printable", PRINTABLE, bool, BOUND, MAYBEDEFAULT ),
+ DECL_DEP_PROP_3 ( "ProgressValue", PROGRESSVALUE, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_2 ( "ProgressValueMax", PROGRESSVALUE_MAX, sal_Int32, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "ProgressValueMin", PROGRESSVALUE_MIN, sal_Int32, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "PushButtonType", PUSHBUTTONTYPE, sal_Int16, BOUND, MAYBEDEFAULT),
+ DECL_PROP_2 ( "ReadOnly", READONLY, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "Repeat", REPEAT, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "AutoRepeat", AUTO_REPEAT, sal_Bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "RepeatDelay", REPEAT_DELAY, sal_Int32, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "ScaleImage", SCALEIMAGE, bool, BOUND, MAYBEDEFAULT ),
+ DECL_DEP_PROP_2 ( "ScaleMode", IMAGE_SCALE_MODE, sal_Int16, BOUND, MAYBEDEFAULT ),
+ DECL_DEP_PROP_3 ( "ScrollValue", SCROLLVALUE, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_2 ( "ScrollValueMax", SCROLLVALUE_MAX, sal_Int32, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "ScrollValueMin", SCROLLVALUE_MIN, sal_Int32, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "ScrollWidth", SCROLLWIDTH, sal_Int32, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "ScrollHeight", SCROLLHEIGHT, sal_Int32, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "ScrollTop", SCROLLTOP, sal_Int32, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "ScrollLeft", SCROLLLEFT, sal_Int32, BOUND, MAYBEDEFAULT ),
+ DECL_DEP_PROP_2 ( "SelectedItems", SELECTEDITEMS, Sequence<sal_Int16>, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "ShowThousandsSeparator", NUMSHOWTHOUSANDSEP, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "Sizeable", SIZEABLE, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "Spin", SPIN, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "SpinIncrement", SPININCREMENT, sal_Int32, BOUND, MAYBEDEFAULT ),
+ DECL_DEP_PROP_2 ( "SpinValue", SPINVALUE, sal_Int32, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "SpinValueMax", SPINVALUE_MAX, sal_Int32, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "SpinValueMin", SPINVALUE_MIN, sal_Int32, BOUND, MAYBEDEFAULT ),
+ DECL_DEP_PROP_2 ( "State", STATE, sal_Int16, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "StrictFormat", STRICTFORMAT, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "StringItemList", STRINGITEMLIST, Sequence< OUString >, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "TypedItemList", TYPEDITEMLIST, Sequence< Any >, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "VisualEffect", VISUALEFFECT, sal_Int16, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_3 ( "SymbolColor", SYMBOL_COLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_3 ( "Tabstop", TABSTOP, bool, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_2 ( "Text", TEXT, OUString, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_3 ( "TextColor", TEXTCOLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_3 ( "TextLineColor", TEXTLINECOLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_DEP_PROP_3 ( "Time", TIME, util::Time, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_2 ( "TimeFormat", EXTTIMEFORMAT, sal_Int16, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "TimeMax", TIMEMAX, util::Time, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "TimeMin", TIMEMIN, util::Time, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "Title", TITLE, OUString, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "Toggle", TOGGLE, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_3 ( "TreatAsNumber", TREATASNUMBER, bool, BOUND, MAYBEDEFAULT,TRANSIENT ),
+ DECL_PROP_2 ( "TriState", TRISTATE, bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "Unit", UNIT, sal_Int16, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "VScroll", VSCROLL, bool, BOUND, MAYBEDEFAULT ),
+ DECL_DEP_PROP_3 ( "Value", VALUE_DOUBLE, double, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_2 ( "ValueMax", VALUEMAX_DOUBLE, double, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "ValueMin", VALUEMIN_DOUBLE, double, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "ValueStep", VALUESTEP_DOUBLE, double, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_3 ( "VerticalAlign", VERTICALALIGN, VerticalAlignment, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_DEP_PROP_3 ( "VisibleSize", VISIBLESIZE, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_2 ( "Activated", ACTIVATED, sal_Bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "Complete", COMPLETE, sal_Bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "CurrentItemID", CURRENTITEMID, sal_Int16, BOUND, MAYBEDEFAULT ),
+
+ DECL_PROP_2 ( "MouseWheelBehavior", MOUSE_WHEEL_BEHAVIOUR, sal_Int16, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "StepTime", STEP_TIME, sal_Int32, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "Decoration", DECORATION, sal_Bool, BOUND, MAYBEDEFAULT ),
+
+ DECL_PROP_2 ( "SelectionType", TREE_SELECTIONTYPE, css::view::SelectionType, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "Editable", TREE_EDITABLE, sal_Bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_3 ( "DataModel", TREE_DATAMODEL, Reference< css::awt::tree::XTreeDataModel >,BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_2 ( "RootDisplayed", TREE_ROOTDISPLAYED, sal_Bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "ShowsHandles", TREE_SHOWSHANDLES, sal_Bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "ShowsRootHandles", TREE_SHOWSROOTHANDLES, sal_Bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_3 ( "RowHeight", ROW_HEIGHT, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_2 ( "InvokesStopNodeEditing", TREE_INVOKESSTOPNODEEDITING, sal_Bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "DialogSourceURL", DIALOGSOURCEURL, OUString, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "URL", URL, OUString, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "WritingMode", WRITING_MODE, sal_Int16, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_3 ( "ContextWritingMode", CONTEXT_WRITING_MODE, sal_Int16, BOUND, MAYBEDEFAULT, TRANSIENT ),
+ DECL_PROP_2 ( "ShowRowHeader", GRID_SHOWROWHEADER, sal_Bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "RowHeaderWidth", ROW_HEADER_WIDTH, sal_Int32, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_2 ( "ShowColumnHeader", GRID_SHOWCOLUMNHEADER, sal_Bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_3 ( "ColumnHeaderHeight", COLUMN_HEADER_HEIGHT, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_1 ( "GridDataModel", GRID_DATAMODEL, Reference< css::awt::grid::XGridDataModel >, BOUND ),
+ DECL_PROP_1 ( "ColumnModel", GRID_COLUMNMODEL, Reference< css::awt::grid::XGridColumnModel >, BOUND ),
+ DECL_PROP_3 ( "SelectionModel", GRID_SELECTIONMODE, css::view::SelectionType, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_2 ( "EnableVisible", ENABLEVISIBLE, sal_Bool, BOUND, MAYBEDEFAULT ),
+ DECL_PROP_3 ( "ReferenceDevice", REFERENCE_DEVICE, Reference< XDevice >,BOUND, MAYBEDEFAULT, TRANSIENT ),
+ DECL_PROP_3 ( "HeaderBackgroundColor", GRID_HEADER_BACKGROUND, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_3 ( "HeaderTextColor", GRID_HEADER_TEXT_COLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_3 ( "GridLineColor", GRID_LINE_COLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_3 ( "RowBackgroundColors", GRID_ROW_BACKGROUND_COLORS, Sequence< sal_Int32 >, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_2 ( "UseGridLines", USE_GRID_LINES, sal_Bool, BOUND, MAYBEDEFAULT ),
+ DECL_DEP_PROP_3 ( "MultiPageValue", MULTIPAGEVALUE, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_3 ( "AllDialogChildren", USERFORMCONTAINEES, Reference< css::container::XNameContainer >, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_3 ( "ActiveSelectionBackgroundColor", ACTIVE_SEL_BACKGROUND_COLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_3 ( "InactiveSelectionBackgroundColor", INACTIVE_SEL_BACKGROUND_COLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_3 ( "ActiveSelectionTextColor", ACTIVE_SEL_TEXT_COLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ DECL_PROP_3 ( "InactiveSelectionTextColor", INACTIVE_SEL_TEXT_COLOR, sal_Int32, BOUND, MAYBEDEFAULT, MAYBEVOID ),
+ };
+ return aImplPropertyInfos;
+}
+
+sal_uInt16 GetPropertyId( const OUString& rPropertyName )
+{
+ const ImpPropertyInfoMap & rMap = ImplGetPropertyInfos();
+ auto it = rMap.find(rPropertyName);
+ return it != rMap.end() ? it->second.nPropId : 0;
+}
+
+static const ImplPropertyInfo* ImplGetImplPropertyInfo( sal_uInt16 nPropertyId )
+{
+ const ImpPropertyInfoMap & rMap = ImplGetPropertyInfos();
+
+ for (auto const & rPair : rMap)
+ if (rPair.second.nPropId == nPropertyId)
+ return &rPair.second;
+ return nullptr;
+}
+
+const OUString& GetPropertyName( sal_uInt16 nPropertyId )
+{
+ const ImpPropertyInfoMap & rMap = ImplGetPropertyInfos();
+
+ for (auto const & rPair : rMap)
+ if (rPair.second.nPropId == nPropertyId)
+ return rPair.first;
+
+ assert(false && "Invalid PropertyId!");
+ static const OUString EMPTY;
+ return EMPTY;
+}
+
+const css::uno::Type* GetPropertyType( sal_uInt16 nPropertyId )
+{
+ const ImplPropertyInfo* pImplPropertyInfo = ImplGetImplPropertyInfo( nPropertyId );
+ DBG_ASSERT( pImplPropertyInfo, "Invalid PropertyId!" );
+ return pImplPropertyInfo ? &pImplPropertyInfo->aType : nullptr;
+}
+
+sal_Int16 GetPropertyAttribs( sal_uInt16 nPropertyId )
+{
+ const ImplPropertyInfo* pImplPropertyInfo = ImplGetImplPropertyInfo( nPropertyId );
+ DBG_ASSERT( pImplPropertyInfo, "Invalid PropertyId!" );
+ return pImplPropertyInfo ? pImplPropertyInfo->nAttribs : 0;
+}
+
+bool DoesDependOnOthers( sal_uInt16 nPropertyId )
+{
+ const ImplPropertyInfo* pImplPropertyInfo = ImplGetImplPropertyInfo( nPropertyId );
+ DBG_ASSERT( pImplPropertyInfo, "Invalid PropertyId!" );
+ return pImplPropertyInfo && pImplPropertyInfo->bDependsOnOthers;
+}
+
+bool CompareProperties( const css::uno::Any& r1, const css::uno::Any& r2 )
+{
+ return r1 == r2;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/helper/servicenames.cxx b/toolkit/source/helper/servicenames.cxx
new file mode 100644
index 0000000000..825672fd20
--- /dev/null
+++ b/toolkit/source/helper/servicenames.cxx
@@ -0,0 +1,24 @@
+/* -*- 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 <helper/servicenames.hxx>
+
+const char szServiceName_UnoControlDialog[] = "stardiv.vcl.control.Dialog";
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/helper/tkresmgr.cxx b/toolkit/source/helper/tkresmgr.cxx
new file mode 100644
index 0000000000..3a687f5236
--- /dev/null
+++ b/toolkit/source/helper/tkresmgr.cxx
@@ -0,0 +1,57 @@
+/* -*- 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 <comphelper/processfactory.hxx>
+#include <comphelper/namedvaluecollection.hxx>
+#include <com/sun/star/graphic/GraphicProvider.hpp>
+#include <com/sun/star/graphic/XGraphicProvider.hpp>
+#include <comphelper/diagnose_ex.hxx>
+
+#include <vcl/image.hxx>
+
+#include <helper/tkresmgr.hxx>
+
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::graphic::XGraphic;
+using ::com::sun::star::graphic::XGraphicProvider;
+using namespace ::com::sun::star;
+
+Image TkResMgr::getImageFromURL(const OUString& i_rImageURL)
+{
+ if (i_rImageURL.isEmpty())
+ return Image();
+
+ try
+ {
+ Reference<uno::XComponentContext> xContext(::comphelper::getProcessComponentContext());
+ Reference<XGraphicProvider> xProvider(graphic::GraphicProvider::create(xContext));
+ ::comphelper::NamedValueCollection aMediaProperties;
+ aMediaProperties.put("URL", i_rImageURL);
+ Reference<XGraphic> xGraphic
+ = xProvider->queryGraphic(aMediaProperties.getPropertyValues());
+ return Image(xGraphic);
+ }
+ catch (const uno::Exception&)
+ {
+ DBG_UNHANDLED_EXCEPTION("toolkit");
+ }
+ return Image();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/helper/unopropertyarrayhelper.cxx b/toolkit/source/helper/unopropertyarrayhelper.cxx
new file mode 100644
index 0000000000..bc0f996d3d
--- /dev/null
+++ b/toolkit/source/helper/unopropertyarrayhelper.cxx
@@ -0,0 +1,148 @@
+/* -*- 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 <helper/property.hxx>
+#include <map>
+
+#include <helper/unopropertyarrayhelper.hxx>
+
+
+
+UnoPropertyArrayHelper::UnoPropertyArrayHelper( const css::uno::Sequence<sal_Int32>& rIDs )
+{
+ for ( const sal_Int32 nID : rIDs )
+ maIDs.insert( nID );
+}
+
+UnoPropertyArrayHelper::UnoPropertyArrayHelper( const std::vector< sal_uInt16 > &rIDs )
+{
+ for (const auto& rId : rIDs)
+ maIDs.insert( rId );
+}
+
+bool UnoPropertyArrayHelper::ImplHasProperty( sal_uInt16 nPropId ) const
+{
+ if ( ( nPropId >= BASEPROPERTY_FONTDESCRIPTORPART_START ) && ( nPropId <= BASEPROPERTY_FONTDESCRIPTORPART_END ) )
+ nPropId = BASEPROPERTY_FONTDESCRIPTOR;
+
+ return maIDs.find( nPropId ) != maIDs.end();
+}
+
+// ::cppu::IPropertyArrayHelper
+sal_Bool UnoPropertyArrayHelper::fillPropertyMembersByHandle( OUString * pPropName, sal_Int16 * pAttributes, sal_Int32 nPropId )
+{
+ sal_uInt16 id = sal::static_int_cast< sal_uInt16 >(nPropId);
+ bool bValid = ImplHasProperty( id );
+ if ( bValid )
+ {
+ if ( pPropName )
+ *pPropName = GetPropertyName( id );
+ if ( pAttributes )
+ *pAttributes = GetPropertyAttribs( id );
+ }
+ return bValid;
+}
+
+css::uno::Sequence< css::beans::Property > UnoPropertyArrayHelper::getProperties()
+{
+ // Sort by names ...
+
+ std::map<OUString, sal_uInt16> aSortedPropsIds;
+ for (const auto& rId : maIDs)
+ {
+ sal_uInt16 nId = sal::static_int_cast< sal_uInt16 >(rId);
+ aSortedPropsIds.emplace(GetPropertyName( nId ), nId);
+
+ if ( nId == BASEPROPERTY_FONTDESCRIPTOR )
+ {
+ // single properties ...
+ for ( sal_uInt16 i = BASEPROPERTY_FONTDESCRIPTORPART_START; i <= BASEPROPERTY_FONTDESCRIPTORPART_END; i++ )
+ aSortedPropsIds.emplace(GetPropertyName( i ), i);
+ }
+ }
+
+ sal_uInt32 nProps = aSortedPropsIds.size(); // could be more now
+ css::uno::Sequence< css::beans::Property> aProps( nProps );
+ css::beans::Property* pProps = aProps.getArray();
+
+ sal_uInt32 n = 0;
+ for ( const auto& rPropIds : aSortedPropsIds )
+ {
+ sal_uInt16 nId = rPropIds.second;
+ pProps[n].Name = rPropIds.first;
+ pProps[n].Handle = nId;
+ pProps[n].Type = *GetPropertyType( nId );
+ pProps[n].Attributes = GetPropertyAttribs( nId );
+ ++n;
+ }
+
+ return aProps;
+}
+
+css::beans::Property UnoPropertyArrayHelper::getPropertyByName(const OUString& rPropertyName)
+{
+ css::beans::Property aProp;
+ sal_uInt16 nId = GetPropertyId( rPropertyName );
+ if ( ImplHasProperty( nId ) )
+ {
+ aProp.Name = rPropertyName;
+ aProp.Handle = -1;
+ aProp.Type = *GetPropertyType( nId );
+ aProp.Attributes = GetPropertyAttribs( nId );
+ }
+
+ return aProp;
+}
+
+sal_Bool UnoPropertyArrayHelper::hasPropertyByName(const OUString& rPropertyName)
+{
+ return ImplHasProperty( GetPropertyId( rPropertyName ) );
+}
+
+sal_Int32 UnoPropertyArrayHelper::getHandleByName( const OUString & rPropertyName )
+{
+ sal_Int32 nId = static_cast<sal_Int32>(GetPropertyId( rPropertyName ));
+ return nId ? nId : -1;
+}
+
+sal_Int32 UnoPropertyArrayHelper::fillHandles( sal_Int32* pHandles, const css::uno::Sequence< OUString > & rPropNames )
+{
+ const OUString* pNames = rPropNames.getConstArray();
+ sal_Int32 nValues = rPropNames.getLength();
+ sal_Int32 nValidHandles = 0;
+
+ for ( sal_Int32 n = 0; n < nValues; n++ )
+ {
+ sal_uInt16 nPropId = GetPropertyId( pNames[n] );
+ if ( nPropId && ImplHasProperty( nPropId ) )
+ {
+ pHandles[n] = nPropId;
+ nValidHandles++;
+ }
+ else
+ {
+ pHandles[n] = -1;
+ }
+ }
+ return nValidHandles;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/helper/unowrapper.cxx b/toolkit/source/helper/unowrapper.cxx
new file mode 100644
index 0000000000..82b4dd1733
--- /dev/null
+++ b/toolkit/source/helper/unowrapper.cxx
@@ -0,0 +1,321 @@
+/* -*- 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 <toolkit/helper/vclunohelper.hxx>
+#include <toolkit/awt/vclxwindow.hxx>
+#include <toolkit/awt/vclxwindows.hxx>
+#include <toolkit/awt/vclxmenu.hxx>
+#include <awt/vclxcontainer.hxx>
+#include <awt/vclxgraphics.hxx>
+#include <awt/vclxtopwindow.hxx>
+#include <awt/vclxwindows.hxx>
+
+#include <toolkit/dllapi.h>
+#include <vcl/menu.hxx>
+
+#include <helper/unowrapper.hxx>
+
+using namespace ::com::sun::star;
+
+static rtl::Reference<VCLXWindow> CreateXWindow( vcl::Window const * pWindow )
+{
+ switch ( pWindow->GetType() )
+ {
+ case WindowType::IMAGEBUTTON:
+ case WindowType::SPINBUTTON:
+ case WindowType::MENUBUTTON:
+ case WindowType::MOREBUTTON:
+ case WindowType::PUSHBUTTON:
+ case WindowType::HELPBUTTON:
+ case WindowType::OKBUTTON:
+ case WindowType::CANCELBUTTON: return new VCLXButton;
+ case WindowType::CHECKBOX: return new VCLXCheckBox;
+ // #i95042#
+ // A Window of type <MetricBox> is inherited from type <ComboBox>.
+ // Thus, it does make more sense to return a <VCLXComboBox> instance
+ // instead of only a <VCLXWindow> instance, especially regarding its
+ // corresponding accessibility API.
+ case WindowType::METRICBOX:
+ case WindowType::COMBOBOX: return new VCLXComboBox;
+ case WindowType::FORMATTEDFIELD: return new SVTXNumericField;
+ case WindowType::SPINFIELD:
+ case WindowType::CURRENCYFIELD: return new VCLXNumericField;
+ case WindowType::DATEFIELD: return new VCLXDateField;
+ case WindowType::MULTILINEEDIT:
+ case WindowType::EDIT: return new VCLXEdit;
+ case WindowType::METRICFIELD: return new VCLXSpinField;
+ case WindowType::MESSBOX:
+ case WindowType::INFOBOX:
+ case WindowType::WARNINGBOX:
+ case WindowType::QUERYBOX:
+ case WindowType::ERRORBOX: return new VCLXMessageBox;
+ case WindowType::FIXEDIMAGE: return new VCLXImageControl;
+ case WindowType::FIXEDTEXT: return new VCLXFixedText;
+ case WindowType::MULTILISTBOX:
+ case WindowType::LISTBOX: return new VCLXListBox;
+ case WindowType::DIALOG:
+ case WindowType::TABDIALOG:
+ case WindowType::BUTTONDIALOG:
+ case WindowType::MODELESSDIALOG: return new VCLXDialog;
+ case WindowType::PATTERNFIELD: return new VCLXPatternField;
+ case WindowType::RADIOBUTTON: return new VCLXRadioButton;
+ case WindowType::SCROLLBAR: return new VCLXScrollBar;
+ case WindowType::TIMEFIELD: return new VCLXTimeField;
+
+ case WindowType::WORKWINDOW:
+ case WindowType::DOCKINGWINDOW:
+ case WindowType::FLOATINGWINDOW:
+ case WindowType::HELPTEXTWINDOW: return new VCLXTopWindow;
+
+ case WindowType::WINDOW:
+ case WindowType::TABPAGE: return new VCLXContainer;
+
+ case WindowType::TOOLBOX: return new VCLXToolBox;
+ case WindowType::TABCONTROL: return new VCLXMultiPage;
+
+ case WindowType::HEADERBAR: return new VCLXHeaderBar;
+
+ case WindowType::BORDERWINDOW:
+ {
+ if (pWindow->IsNativeFrame())
+ return new VCLXTopWindow;
+ return new VCLXWindow(true);
+ }
+
+ // case WindowType::FIXEDLINE:
+ // case WindowType::FIXEDBITMAP:
+ // case WindowType::DATEBOX:
+ // case WindowType::GROUPBOX:
+ // case WindowType::LONGCURRENCYBOX:
+ // case WindowType::SPLITTER:
+ // case WindowType::STATUSBAR:
+ // case WindowType::TABCONTROL:
+ // case WindowType::NUMERICBOX:
+ // case WindowType::TRISTATEBOX:
+ // case WindowType::TIMEBOX:
+ // case WindowType::SPLITWINDOW:
+ // case WindowType::SCROLLBARBOX:
+ // case WindowType::PATTERNBOX:
+ // case WindowType::CURRENCYBOX:
+ default: return new VCLXWindow( true );
+ }
+}
+
+
+
+
+extern "C" {
+
+TOOLKIT_DLLPUBLIC UnoWrapperBase* CreateUnoWrapper()
+{
+ return new UnoWrapper( nullptr );
+}
+
+} // extern "C"
+
+
+UnoWrapper::UnoWrapper( const css::uno::Reference< css::awt::XToolkit>& rxToolkit )
+{
+ mxToolkit = rxToolkit;
+}
+
+void UnoWrapper::Destroy()
+{
+ delete this;
+}
+
+UnoWrapper::~UnoWrapper()
+{
+}
+
+css::uno::Reference< css::awt::XToolkit> UnoWrapper::GetVCLToolkit()
+{
+ if ( !mxToolkit.is() )
+ mxToolkit = VCLUnoHelper::CreateToolkit();
+ return mxToolkit;
+}
+
+css::uno::Reference< css::awt::XVclWindowPeer> UnoWrapper::GetWindowInterface( vcl::Window* pWindow )
+{
+ css::uno::Reference< css::awt::XVclWindowPeer> xPeer = pWindow->GetWindowPeer();
+ if ( xPeer )
+ return xPeer;
+
+ rtl::Reference<VCLXWindow> xVCLXWindow = CreateXWindow( pWindow );
+ xVCLXWindow->SetWindow( pWindow );
+ pWindow->SetWindowPeer( xVCLXWindow, xVCLXWindow.get() );
+ return xVCLXWindow;
+}
+
+VclPtr<vcl::Window> UnoWrapper::GetWindow(const css::uno::Reference<css::awt::XWindow>& rWindow)
+{
+ return VCLUnoHelper::GetWindow(rWindow);
+}
+
+void UnoWrapper::SetWindowInterface( vcl::Window* pWindow, const css::uno::Reference< css::awt::XVclWindowPeer> & xIFace )
+{
+ VCLXWindow* pVCLXWindow = dynamic_cast<VCLXWindow*>( xIFace.get() );
+
+ assert( pVCLXWindow && "must be a VCLXWindow subclass" );
+ if ( !pVCLXWindow )
+ return;
+
+ if (!pWindow)
+ {
+ // we are disconnecting a peer from a window
+ pVCLXWindow->SetWindow( nullptr );
+ }
+ else
+ {
+ css::uno::Reference< css::awt::XVclWindowPeer> xPeer = pWindow->GetWindowPeer();
+ if( xPeer.is() )
+ {
+ bool bSameInstance( pVCLXWindow == dynamic_cast< VCLXWindow* >( xPeer.get() ));
+ SAL_WARN_IF( !bSameInstance, "toolkit.helper", "UnoWrapper::SetWindowInterface: there is already a WindowPeer/ComponentInterface for this VCL window" );
+ if ( bSameInstance )
+ return;
+ }
+ pVCLXWindow->SetWindow( pWindow );
+ pWindow->SetWindowPeer( xIFace, pVCLXWindow );
+ }
+}
+
+css::uno::Reference<css::awt::XPopupMenu> UnoWrapper::CreateMenuInterface( PopupMenu* pPopupMenu )
+{
+ return new VCLXPopupMenu(pPopupMenu);
+}
+
+css::uno::Reference< css::awt::XGraphics> UnoWrapper::CreateGraphics( OutputDevice* pOutDev )
+{
+ rtl::Reference<VCLXGraphics> pGrf = new VCLXGraphics;
+ pGrf->Init( pOutDev );
+ return pGrf;
+}
+
+void UnoWrapper::ReleaseAllGraphics( OutputDevice* pOutDev )
+{
+ std::vector< VCLXGraphics* > *pLst = pOutDev->GetUnoGraphicsList();
+ if ( pLst )
+ {
+ for (VCLXGraphics* pGrf : *pLst)
+ {
+ pGrf->SetOutputDevice( nullptr );
+ }
+ }
+
+}
+
+static bool lcl_ImplIsParent( vcl::Window const * pParentWindow, vcl::Window* pPossibleChild )
+{
+ vcl::Window* pWindow = ( pPossibleChild != pParentWindow ) ? pPossibleChild : nullptr;
+ while ( pWindow && ( pWindow != pParentWindow ) )
+ pWindow = pWindow->GetParent();
+
+ return pWindow != nullptr;
+}
+
+void UnoWrapper::WindowDestroyed( vcl::Window* pWindow )
+{
+ // their still might be some children created with css::loader::Java
+ // that would otherwise not be destroyed until the garbage collector cleans up
+ VclPtr< vcl::Window > pChild = pWindow->GetWindow( GetWindowType::FirstChild );
+ while ( pChild )
+ {
+ VclPtr< vcl::Window > pNextChild = pChild->GetWindow( GetWindowType::Next );
+
+ VclPtr< vcl::Window > pClient = pChild->GetWindow( GetWindowType::Client );
+ if ( pClient && pClient->GetWindowPeer() )
+ {
+ css::uno::Reference< css::lang::XComponent > xComp = pClient->GetComponentInterface( false );
+ xComp->dispose();
+ }
+ else
+ {
+ // We need it to dispose the child windows properly (even without window peer),
+ // otherwise the vcl::Window will be leaked.
+ pClient.disposeAndClear();
+ }
+
+ pChild = pNextChild;
+ }
+
+ // find system windows...
+ VclPtr< vcl::Window > pOverlap = pWindow->GetWindow( GetWindowType::Overlap );
+ if ( pOverlap )
+ {
+ pOverlap = pOverlap->GetWindow( GetWindowType::FirstOverlap );
+ while ( pOverlap )
+ {
+ VclPtr< vcl::Window > pNextOverlap = pOverlap->GetWindow( GetWindowType::Next );
+ VclPtr< vcl::Window > pClient = pOverlap->GetWindow( GetWindowType::Client );
+
+ if ( pClient && pClient->GetWindowPeer() && lcl_ImplIsParent( pWindow, pClient ) )
+ {
+ css::uno::Reference< css::lang::XComponent > xComp = pClient->GetComponentInterface( false );
+ xComp->dispose();
+ }
+
+ pOverlap = pNextOverlap;
+ }
+ }
+
+ {
+ VclPtr< vcl::Window > pParent = pWindow->GetParent();
+ if ( pParent && pParent->GetWindowPeer() )
+ pParent->GetWindowPeer()->notifyWindowRemoved( *pWindow );
+ }
+
+ VCLXWindow* pWindowPeer = pWindow->GetWindowPeer();
+ uno::Reference< lang::XComponent > xWindowPeerComp = pWindow->GetComponentInterface( false );
+ OSL_ENSURE( ( pWindowPeer != nullptr ) == xWindowPeerComp.is(),
+ "UnoWrapper::WindowDestroyed: inconsistency in the window's peers!" );
+ if ( pWindowPeer )
+ {
+ pWindowPeer->SetWindow( nullptr );
+ pWindow->SetWindowPeer( nullptr, nullptr );
+ }
+ if ( xWindowPeerComp.is() )
+ xWindowPeerComp->dispose();
+
+ // #102132# Iterate over frames after setting Window peer to NULL,
+ // because while destroying other frames, we get into the method again and try
+ // to destroy this window again...
+ // #i42462#/#116855# no, don't loop: Instead, just ensure that all our top-window-children
+ // are disposed, too (which should also be a valid fix for #102132#, but doesn't have the extreme
+ // performance penalties)
+ VclPtr< vcl::Window > pTopWindowChild = pWindow->GetWindow( GetWindowType::FirstTopWindowChild );
+ while ( pTopWindowChild )
+ {
+ OSL_ENSURE( pTopWindowChild->GetParent() == pWindow,
+ "UnoWrapper::WindowDestroyed: inconsistency in the SystemWindow relationship!" );
+
+ VclPtr< vcl::Window > pNextTopChild = pTopWindowChild->GetWindow( GetWindowType::NextTopWindowSibling );
+
+ pTopWindowChild.disposeAndClear();
+ pTopWindowChild = pNextTopChild;
+ }
+}
+
+
+css::uno::Reference< css::accessibility::XAccessible > UnoWrapper::CreateAccessible( Menu* pMenu, bool bIsMenuBar )
+{
+ return maAccessibleFactoryAccess.getFactory().createAccessible( pMenu, bIsMenuBar );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/source/helper/vclunohelper.cxx b/toolkit/source/helper/vclunohelper.cxx
new file mode 100644
index 0000000000..9f05ae7070
--- /dev/null
+++ b/toolkit/source/helper/vclunohelper.cxx
@@ -0,0 +1,604 @@
+/* -*- 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 <tools/stream.hxx>
+#include <vcl/dibtools.hxx>
+#include <vcl/event.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/metric.hxx>
+#include <vcl/ptrstyle.hxx>
+#include <vcl/unohelp.hxx>
+#include <vcl/window.hxx>
+#include <com/sun/star/util/MeasureUnit.hpp>
+#include <com/sun/star/awt/XBitmap.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/awt/XDevice.hpp>
+#include <com/sun/star/awt/SimpleFontMetric.hpp>
+#include <com/sun/star/awt/FontDescriptor.hpp>
+#include <com/sun/star/awt/XControlContainer.hpp>
+#include <com/sun/star/awt/KeyModifier.hpp>
+#include <com/sun/star/awt/MouseButton.hpp>
+#include <com/sun/star/embed/EmbedMapUnits.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <toolkit/helper/convert.hxx>
+#include <awt/vclxbitmap.hxx>
+#include <awt/vclxregion.hxx>
+#include <toolkit/awt/vclxwindow.hxx>
+#include <awt/vclxgraphics.hxx>
+#include <toolkit/awt/vclxfont.hxx>
+#include <controls/unocontrolcontainer.hxx>
+#include <controls/unocontrolcontainermodel.hxx>
+#include <comphelper/processfactory.hxx>
+
+#include <com/sun/star/awt/Toolkit.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/awt/Point.hpp>
+
+using namespace ::com::sun::star;
+
+
+uno::Reference< css::awt::XToolkit> VCLUnoHelper::CreateToolkit()
+{
+ uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
+ uno::Reference< awt::XToolkit> xToolkit( awt::Toolkit::create(xContext), uno::UNO_QUERY_THROW );
+ return xToolkit;
+}
+
+BitmapEx VCLUnoHelper::GetBitmap( const css::uno::Reference< css::awt::XBitmap>& rxBitmap )
+{
+ BitmapEx aBmp;
+
+ css::uno::Reference< css::graphic::XGraphic > xGraphic( rxBitmap, css::uno::UNO_QUERY );
+ if( xGraphic.is() )
+ {
+ Graphic aGraphic( xGraphic );
+ aBmp = aGraphic.GetBitmapEx();
+ }
+ else if ( rxBitmap.is() )
+ {
+ VCLXBitmap* pVCLBitmap = dynamic_cast<VCLXBitmap*>( rxBitmap.get() );
+ if ( pVCLBitmap )
+ aBmp = pVCLBitmap->GetBitmap();
+ else
+ {
+ Bitmap aDIB, aMask;
+ {
+ css::uno::Sequence<sal_Int8> aBytes = rxBitmap->getDIB();
+ SvMemoryStream aMem( aBytes.getArray(), aBytes.getLength(), StreamMode::READ );
+ ReadDIB(aDIB, aMem, true);
+ }
+ {
+ css::uno::Sequence<sal_Int8> aBytes = rxBitmap->getMaskDIB();
+ SvMemoryStream aMem( aBytes.getArray(), aBytes.getLength(), StreamMode::READ );
+ ReadDIB(aMask, aMem, true);
+ }
+ aMask.Invert(); // Convert from transparency to alpha
+ aBmp = BitmapEx( aDIB, aMask );
+ }
+ }
+ return aBmp;
+}
+
+css::uno::Reference< css::awt::XBitmap> VCLUnoHelper::CreateBitmap( const BitmapEx& rBitmap )
+{
+ Graphic aGraphic( rBitmap );
+ css::uno::Reference< css::awt::XBitmap> xBmp( aGraphic.GetXGraphic(), css::uno::UNO_QUERY );
+ return xBmp;
+}
+
+vcl::Window* VCLUnoHelper::GetWindow( const css::uno::Reference< css::awt::XWindow>& rxWindow )
+{
+ VCLXWindow* pVCLXWindow = dynamic_cast<VCLXWindow*>( rxWindow.get() );
+ return pVCLXWindow ? pVCLXWindow->GetWindow() : nullptr;
+}
+
+vcl::Window* VCLUnoHelper::GetWindow( const css::uno::Reference< css::awt::XWindow2>& rxWindow )
+{
+ VCLXWindow* pVCLXWindow = dynamic_cast<VCLXWindow*>( rxWindow.get() );
+ return pVCLXWindow ? pVCLXWindow->GetWindow() : nullptr;
+}
+
+vcl::Window* VCLUnoHelper::GetWindow( const css::uno::Reference< css::awt::XWindowPeer>& rxWindow )
+{
+ VCLXWindow* pVCLXWindow = dynamic_cast<VCLXWindow*>( rxWindow.get() );
+ return pVCLXWindow ? pVCLXWindow->GetWindow() : nullptr;
+}
+
+vcl::Region VCLUnoHelper::GetRegion( const css::uno::Reference< css::awt::XRegion >& rxRegion )
+{
+ vcl::Region aRegion;
+ VCLXRegion* pVCLRegion = dynamic_cast<VCLXRegion*>( rxRegion.get() );
+ if ( pVCLRegion )
+ aRegion = pVCLRegion->GetRegion();
+ else
+ {
+ const css::uno::Sequence< css::awt::Rectangle > aRects = rxRegion->getRectangles();
+ for ( const auto& rRect : aRects )
+ aRegion.Union( VCLRectangle( rRect ) );
+ }
+ return aRegion;
+}
+
+css::uno::Reference< css::awt::XWindow> VCLUnoHelper::GetInterface( vcl::Window* pWindow )
+{
+ css::uno::Reference< css::awt::XWindow > xWin;
+ if ( pWindow )
+ {
+ css::uno::Reference< css::awt::XWindowPeer> xPeer = pWindow->GetComponentInterface();
+ xWin.set(xPeer, css::uno::UNO_QUERY);
+ }
+ return xWin;
+}
+
+OutputDevice* VCLUnoHelper::GetOutputDevice( const css::uno::Reference< css::awt::XDevice>& rxDevice )
+{
+ VclPtr<OutputDevice> pOutDev;
+ VCLXDevice* pDev = dynamic_cast<VCLXDevice*>( rxDevice.get() );
+ if ( pDev )
+ pOutDev = pDev->GetOutputDevice();
+ return pOutDev;
+}
+
+OutputDevice* VCLUnoHelper::GetOutputDevice( const css::uno::Reference< css::awt::XGraphics>& rxGraphics )
+{
+ OutputDevice* pOutDev = nullptr;
+ VCLXGraphics* pGrf = dynamic_cast<VCLXGraphics*>( rxGraphics.get() );
+ if ( pGrf )
+ pOutDev = pGrf->GetOutputDevice();
+ return pOutDev;
+}
+
+tools::Polygon VCLUnoHelper::CreatePolygon( const css::uno::Sequence< sal_Int32 >& DataX,
+ const css::uno::Sequence< sal_Int32 >& DataY )
+{
+ sal_Int32 nLen = DataX.getLength();
+ const sal_Int32* pDataX = DataX.getConstArray();
+ const sal_Int32* pDataY = DataY.getConstArray();
+ tools::Polygon aPoly( static_cast<sal_uInt16>(nLen) );
+ for ( sal_Int32 n = 0; n < nLen; n++ )
+ {
+ Point aPnt;
+ aPnt.setX( pDataX[n] );
+ aPnt.setY( pDataY[n] );
+ aPoly[n] = aPnt;
+ }
+ return aPoly;
+}
+
+css::uno::Reference< css::awt::XControlContainer> VCLUnoHelper::CreateControlContainer( vcl::Window* pWindow )
+{
+ rtl::Reference<UnoControlContainer> pContainer = new UnoControlContainer( pWindow->GetComponentInterface() );
+
+ rtl::Reference<UnoControlModel> pContainerModel = new UnoControlContainerModel( ::comphelper::getProcessComponentContext() );
+ pContainer->setModel( pContainerModel );
+
+ return pContainer;
+}
+
+css::awt::FontDescriptor VCLUnoHelper::CreateFontDescriptor( const vcl::Font& rFont )
+{
+ css::awt::FontDescriptor aFD;
+ aFD.Name = rFont.GetFamilyName();
+ aFD.StyleName = rFont.GetStyleName();
+ aFD.Height = static_cast<sal_Int16>(rFont.GetFontSize().Height());
+ aFD.Width = static_cast<sal_Int16>(rFont.GetFontSize().Width());
+ aFD.Family = sal::static_int_cast< sal_Int16 >(rFont.GetFamilyType());
+ aFD.CharSet = rFont.GetCharSet();
+ aFD.Pitch = sal::static_int_cast< sal_Int16 >(rFont.GetPitch());
+ aFD.CharacterWidth = vcl::unohelper::ConvertFontWidth(rFont.GetWidthType());
+ aFD.Weight = vcl::unohelper::ConvertFontWeight(rFont.GetWeight());
+ aFD.Slant = vcl::unohelper::ConvertFontSlant(rFont.GetItalic());
+ aFD.Underline = sal::static_int_cast< sal_Int16 >(rFont.GetUnderline());
+ aFD.Strikeout = sal::static_int_cast< sal_Int16 >(rFont.GetStrikeout());
+ aFD.Orientation = rFont.GetOrientation().get() / 10.0;
+ aFD.Kerning = rFont.IsKerning();
+ aFD.WordLineMode = rFont.IsWordLineMode();
+ aFD.Type = 0; // ??? => Only in Metric...
+ return aFD;
+}
+
+vcl::Font VCLUnoHelper::CreateFont( const css::awt::FontDescriptor& rDescr, const vcl::Font& rInitFont )
+{
+ vcl::Font aFont( rInitFont );
+ if ( !rDescr.Name.isEmpty() )
+ aFont.SetFamilyName( rDescr.Name );
+ if ( !rDescr.StyleName.isEmpty() )
+ aFont.SetStyleName( rDescr.StyleName );
+ if ( rDescr.Height )
+ aFont.SetFontSize( Size( rDescr.Width, rDescr.Height ) );
+ if ( static_cast<FontFamily>(rDescr.Family) != FAMILY_DONTKNOW )
+ aFont.SetFamily( static_cast<FontFamily>(rDescr.Family) );
+ if ( static_cast<rtl_TextEncoding>(rDescr.CharSet) != RTL_TEXTENCODING_DONTKNOW )
+ aFont.SetCharSet( static_cast<rtl_TextEncoding>(rDescr.CharSet) );
+ if ( static_cast<FontPitch>(rDescr.Pitch) != PITCH_DONTKNOW )
+ aFont.SetPitch( static_cast<FontPitch>(rDescr.Pitch) );
+ if ( rDescr.CharacterWidth )
+ aFont.SetWidthType(vcl::unohelper::ConvertFontWidth(rDescr.CharacterWidth));
+ if ( rDescr.Weight )
+ aFont.SetWeight(vcl::unohelper::ConvertFontWeight(rDescr.Weight));
+ if ( rDescr.Slant != css::awt::FontSlant_DONTKNOW )
+ aFont.SetItalic(vcl::unohelper::ConvertFontSlant(rDescr.Slant));
+ if ( static_cast<FontLineStyle>(rDescr.Underline) != LINESTYLE_DONTKNOW )
+ aFont.SetUnderline( static_cast<FontLineStyle>(rDescr.Underline) );
+ if ( static_cast<FontStrikeout>(rDescr.Strikeout) != STRIKEOUT_DONTKNOW )
+ aFont.SetStrikeout( static_cast<FontStrikeout>(rDescr.Strikeout) );
+
+ // Not DONTKNOW
+ aFont.SetOrientation( Degree10(static_cast<sal_Int16>(rDescr.Orientation * 10)) );
+ aFont.SetKerning( static_cast<FontKerning>(rDescr.Kerning) );
+ aFont.SetWordLineMode( rDescr.WordLineMode );
+
+ return aFont;
+}
+
+vcl::Font VCLUnoHelper::CreateFont( const css::uno::Reference< css::awt::XFont >& rxFont )
+{
+ vcl::Font aFont;
+ VCLXFont* pVCLXFont = dynamic_cast<VCLXFont*>( rxFont.get() );
+ if ( pVCLXFont )
+ aFont = pVCLXFont->GetFont();
+ return aFont;
+}
+
+
+css::awt::SimpleFontMetric VCLUnoHelper::CreateFontMetric( const FontMetric& rFontMetric )
+{
+ css::awt::SimpleFontMetric aFM;
+ aFM.Ascent = static_cast<sal_Int16>(rFontMetric.GetAscent());
+ aFM.Descent = static_cast<sal_Int16>(rFontMetric.GetDescent());
+ aFM.Leading = static_cast<sal_Int16>(rFontMetric.GetInternalLeading());
+ aFM.Slant = static_cast<sal_Int16>(rFontMetric.GetSlant());
+ aFM.FirstChar = 0x0020;
+ aFM.LastChar = 0xFFFD;
+ return aFM;
+}
+
+bool VCLUnoHelper::IsZero(const css::awt::Rectangle& rRect)
+{
+ return ( !rRect.X && !rRect.Y && !rRect.Width && !rRect.Height );
+}
+
+MapUnit VCLUnoHelper::UnoEmbed2VCLMapUnit( sal_Int32 nUnoEmbedMapUnit )
+{
+ switch( nUnoEmbedMapUnit )
+ {
+ case css::embed::EmbedMapUnits::ONE_100TH_MM:
+ return MapUnit::Map100thMM;
+ case css::embed::EmbedMapUnits::ONE_10TH_MM:
+ return MapUnit::Map10thMM;
+ case css::embed::EmbedMapUnits::ONE_MM:
+ return MapUnit::MapMM;
+ case css::embed::EmbedMapUnits::ONE_CM:
+ return MapUnit::MapCM;
+ case css::embed::EmbedMapUnits::ONE_1000TH_INCH:
+ return MapUnit::Map1000thInch;
+ case css::embed::EmbedMapUnits::ONE_100TH_INCH:
+ return MapUnit::Map100thInch;
+ case css::embed::EmbedMapUnits::ONE_10TH_INCH:
+ return MapUnit::Map10thInch;
+ case css::embed::EmbedMapUnits::ONE_INCH:
+ return MapUnit::MapInch;
+ case css::embed::EmbedMapUnits::POINT:
+ return MapUnit::MapPoint;
+ case css::embed::EmbedMapUnits::TWIP:
+ return MapUnit::MapTwip;
+ case css::embed::EmbedMapUnits::PIXEL:
+ return MapUnit::MapPixel;
+ }
+
+ OSL_FAIL( "Unexpected UNO map mode is provided!" );
+ return MapUnit::LASTENUMDUMMY;
+}
+
+sal_Int32 VCLUnoHelper::VCL2UnoEmbedMapUnit( MapUnit nVCLMapUnit )
+{
+ switch( nVCLMapUnit )
+ {
+ case MapUnit::Map100thMM:
+ return css::embed::EmbedMapUnits::ONE_100TH_MM;
+ case MapUnit::Map10thMM:
+ return css::embed::EmbedMapUnits::ONE_10TH_MM;
+ case MapUnit::MapMM:
+ return css::embed::EmbedMapUnits::ONE_MM;
+ case MapUnit::MapCM:
+ return css::embed::EmbedMapUnits::ONE_CM;
+ case MapUnit::Map1000thInch:
+ return css::embed::EmbedMapUnits::ONE_1000TH_INCH;
+ case MapUnit::Map100thInch:
+ return css::embed::EmbedMapUnits::ONE_100TH_INCH;
+ case MapUnit::Map10thInch:
+ return css::embed::EmbedMapUnits::ONE_10TH_INCH;
+ case MapUnit::MapInch:
+ return css::embed::EmbedMapUnits::ONE_INCH;
+ case MapUnit::MapPoint:
+ return css::embed::EmbedMapUnits::POINT;
+ case MapUnit::MapTwip:
+ return css::embed::EmbedMapUnits::TWIP;
+ case MapUnit::MapPixel:
+ return css::embed::EmbedMapUnits::PIXEL;
+ default: ; // avoid compiler warning
+ }
+
+ OSL_FAIL( "Unexpected VCL map mode is provided!" );
+ return -1;
+}
+
+using namespace ::com::sun::star::util;
+
+
+namespace
+{
+ enum UnitConversionDirection
+ {
+ FieldUnitToMeasurementUnit,
+ MeasurementUnitToFieldUnit
+ };
+
+ sal_Int16 convertMeasurementUnit( sal_Int16 _nUnit, UnitConversionDirection eDirection, sal_Int16& _rFieldToUNOValueFactor )
+ {
+ static struct _unit_table
+ {
+ FieldUnit eFieldUnit;
+ sal_Int16 nMeasurementUnit;
+ sal_Int16 nFieldToMeasureFactor;
+ } const aUnits[] = {
+ { FieldUnit::NONE, -1 , -1},
+ { FieldUnit::MM, MeasureUnit::MM, 1 }, // must precede MM_10TH
+ { FieldUnit::MM, MeasureUnit::MM_10TH, 10 },
+ { FieldUnit::MM_100TH, MeasureUnit::MM_100TH, 1 },
+ { FieldUnit::CM, MeasureUnit::CM, 1 },
+ { FieldUnit::M, MeasureUnit::M, 1 },
+ { FieldUnit::KM, MeasureUnit::KM, 1 },
+ { FieldUnit::TWIP, MeasureUnit::TWIP, 1 },
+ { FieldUnit::POINT, MeasureUnit::POINT, 1 },
+ { FieldUnit::PICA, MeasureUnit::PICA, 1 },
+ { FieldUnit::INCH, MeasureUnit::INCH, 1 }, // must precede INCH_*TH
+ { FieldUnit::INCH, MeasureUnit::INCH_10TH, 10 },
+ { FieldUnit::INCH, MeasureUnit::INCH_100TH, 100 },
+ { FieldUnit::INCH, MeasureUnit::INCH_1000TH, 1000 },
+ { FieldUnit::FOOT, MeasureUnit::FOOT, 1 },
+ { FieldUnit::MILE, MeasureUnit::MILE, 1 },
+ };
+ for (auto & aUnit : aUnits)
+ {
+ if ( eDirection == FieldUnitToMeasurementUnit )
+ {
+ if ( ( aUnit.eFieldUnit == static_cast<FieldUnit>(_nUnit) ) && ( aUnit.nFieldToMeasureFactor == _rFieldToUNOValueFactor ) )
+ return aUnit.nMeasurementUnit;
+ }
+ else
+ {
+ if ( aUnit.nMeasurementUnit == _nUnit )
+ {
+ _rFieldToUNOValueFactor = aUnit.nFieldToMeasureFactor;
+ return static_cast<sal_Int16>(aUnit.eFieldUnit);
+ }
+ }
+ }
+ if ( eDirection == FieldUnitToMeasurementUnit )
+ return -1;
+
+ _rFieldToUNOValueFactor = 1;
+ return sal_Int16(FieldUnit::NONE);
+ }
+}
+
+//= MeasurementUnitConversion
+
+
+sal_Int16 VCLUnoHelper::ConvertToMeasurementUnit( FieldUnit _nFieldUnit, sal_Int16 _nUNOToFieldValueFactor )
+{
+ return convertMeasurementUnit( static_cast<sal_Int16>(_nFieldUnit), FieldUnitToMeasurementUnit, _nUNOToFieldValueFactor );
+}
+
+
+FieldUnit VCLUnoHelper::ConvertToFieldUnit( sal_Int16 _nMeasurementUnit, sal_Int16& _rFieldToUNOValueFactor )
+{
+ return static_cast<FieldUnit>(convertMeasurementUnit( _nMeasurementUnit, MeasurementUnitToFieldUnit, _rFieldToUNOValueFactor ));
+}
+
+
+MapUnit /* MapModeUnit */ VCLUnoHelper::ConvertToMapModeUnit(sal_Int16 /* com.sun.star.util.MeasureUnit.* */ _nMeasureUnit)
+{
+ MapUnit eMode;
+ switch(_nMeasureUnit)
+ {
+ case css::util::MeasureUnit::MM_100TH:
+ eMode = MapUnit::Map100thMM;
+ break;
+
+ case css::util::MeasureUnit::MM_10TH:
+ eMode = MapUnit::Map10thMM;
+ break;
+
+ case css::util::MeasureUnit::MM:
+ eMode = MapUnit::MapMM;
+ break;
+
+ case css::util::MeasureUnit::CM:
+ eMode = MapUnit::MapCM;
+ break;
+
+ case css::util::MeasureUnit::INCH_1000TH:
+ eMode = MapUnit::Map1000thInch;
+ break;
+
+ case css::util::MeasureUnit::INCH_100TH:
+ eMode = MapUnit::Map100thInch;
+ break;
+
+ case css::util::MeasureUnit::INCH_10TH:
+ eMode = MapUnit::Map10thInch;
+ break;
+
+ case css::util::MeasureUnit::INCH:
+ eMode = MapUnit::MapInch;
+ break;
+
+ case css::util::MeasureUnit::POINT:
+ eMode = MapUnit::MapPoint;
+ break;
+
+ case css::util::MeasureUnit::TWIP:
+ eMode = MapUnit::MapTwip;
+ break;
+
+ case css::util::MeasureUnit::PIXEL:
+ eMode = MapUnit::MapPixel;
+ break;
+
+ case css::util::MeasureUnit::APPFONT:
+ eMode = MapUnit::MapAppFont;
+ break;
+
+ case css::util::MeasureUnit::SYSFONT:
+ eMode = MapUnit::MapSysFont;
+ break;
+
+ default:
+ throw css::lang::IllegalArgumentException("Unsupported measure unit.", nullptr, 1 );
+ }
+ return eMode;
+}
+
+::Size VCLUnoHelper::ConvertToVCLSize(css::awt::Size const& _aSize)
+{
+ ::Size aVCLSize(_aSize.Width, _aSize.Height);
+ return aVCLSize;
+}
+
+css::awt::Size VCLUnoHelper::ConvertToAWTSize(::Size /* VCLSize */ const& _aSize)
+{
+ css::awt::Size aAWTSize(_aSize.Width(), _aSize.Height());
+ return aAWTSize;
+}
+
+
+::Point VCLUnoHelper::ConvertToVCLPoint(css::awt::Point const& _aPoint)
+{
+ ::Point aVCLPoint(_aPoint.X, _aPoint.Y);
+ return aVCLPoint;
+}
+
+css::awt::Point VCLUnoHelper::ConvertToAWTPoint(::Point /* VCLPoint */ const& _aPoint)
+{
+ css::awt::Point aAWTPoint(_aPoint.X(), _aPoint.Y());
+ return aAWTPoint;
+}
+
+::tools::Rectangle VCLUnoHelper::ConvertToVCLRect( css::awt::Rectangle const & _rRect )
+{
+ return ::tools::Rectangle( _rRect.X, _rRect.Y, _rRect.X + _rRect.Width - 1, _rRect.Y + _rRect.Height - 1 );
+}
+
+css::awt::Rectangle VCLUnoHelper::ConvertToAWTRect( ::tools::Rectangle const & _rRect )
+{
+ return css::awt::Rectangle( _rRect.Left(), _rRect.Top(), _rRect.GetWidth(), _rRect.GetHeight() );
+}
+
+awt::MouseEvent VCLUnoHelper::createMouseEvent( const ::MouseEvent& _rVclEvent, const uno::Reference< uno::XInterface >& _rxContext )
+{
+ awt::MouseEvent aMouseEvent;
+ aMouseEvent.Source = _rxContext;
+
+ aMouseEvent.Modifiers = 0;
+ if ( _rVclEvent.IsShift() )
+ aMouseEvent.Modifiers |= css::awt::KeyModifier::SHIFT;
+ if ( _rVclEvent.IsMod1() )
+ aMouseEvent.Modifiers |= css::awt::KeyModifier::MOD1;
+ if ( _rVclEvent.IsMod2() )
+ aMouseEvent.Modifiers |= css::awt::KeyModifier::MOD2;
+
+ aMouseEvent.Buttons = 0;
+ if ( _rVclEvent.IsLeft() )
+ aMouseEvent.Buttons |= css::awt::MouseButton::LEFT;
+ if ( _rVclEvent.IsRight() )
+ aMouseEvent.Buttons |= css::awt::MouseButton::RIGHT;
+ if ( _rVclEvent.IsMiddle() )
+ aMouseEvent.Buttons |= css::awt::MouseButton::MIDDLE;
+
+ aMouseEvent.X = _rVclEvent.GetPosPixel().X();
+ aMouseEvent.Y = _rVclEvent.GetPosPixel().Y();
+ aMouseEvent.ClickCount = _rVclEvent.GetClicks();
+ aMouseEvent.PopupTrigger = false;
+
+ return aMouseEvent;
+}
+
+::MouseEvent VCLUnoHelper::createVCLMouseEvent( const awt::MouseEvent& _rAwtEvent )
+{
+ ::MouseEvent aMouseEvent( Point( _rAwtEvent.X, _rAwtEvent.Y ), _rAwtEvent.ClickCount,
+ ::MouseEventModifiers::NONE, _rAwtEvent.Buttons, _rAwtEvent.Modifiers );
+
+ return aMouseEvent;
+}
+
+awt::KeyEvent VCLUnoHelper::createKeyEvent( const ::KeyEvent& _rVclEvent, const uno::Reference< uno::XInterface >& _rxContext )
+{
+ awt::KeyEvent aKeyEvent;
+ aKeyEvent.Source = _rxContext;
+
+ aKeyEvent.Modifiers = 0;
+ if ( _rVclEvent.GetKeyCode().IsShift() )
+ aKeyEvent.Modifiers |= awt::KeyModifier::SHIFT;
+ if ( _rVclEvent.GetKeyCode().IsMod1() )
+ aKeyEvent.Modifiers |= awt::KeyModifier::MOD1;
+ if ( _rVclEvent.GetKeyCode().IsMod2() )
+ aKeyEvent.Modifiers |= awt::KeyModifier::MOD2;
+ if ( _rVclEvent.GetKeyCode().IsMod3() )
+ aKeyEvent.Modifiers |= awt::KeyModifier::MOD3;
+
+ aKeyEvent.KeyCode = _rVclEvent.GetKeyCode().GetCode();
+ aKeyEvent.KeyChar = _rVclEvent.GetCharCode();
+ aKeyEvent.KeyFunc = ::sal::static_int_cast< sal_Int16 >( _rVclEvent.GetKeyCode().GetFunction());
+
+ return aKeyEvent;
+}
+
+::KeyEvent VCLUnoHelper::createVCLKeyEvent( const awt::KeyEvent& _rAwtEvent )
+{
+ sal_Unicode nChar = _rAwtEvent.KeyChar;
+ vcl::KeyCode aKeyCode( _rAwtEvent.KeyCode, _rAwtEvent.Modifiers & awt::KeyModifier::SHIFT,
+ _rAwtEvent.Modifiers & awt::KeyModifier::MOD1,
+ _rAwtEvent.Modifiers & awt::KeyModifier::MOD2,
+ _rAwtEvent.Modifiers & awt::KeyModifier::MOD3 );
+
+ return ::KeyEvent (nChar, aKeyCode);
+
+}
+
+::PointerStyle VCLUnoHelper::getMousePointer(const css::uno::Reference<css::awt::XWindowPeer>& rWindowPeer)
+{
+ ::PointerStyle eType = ::PointerStyle::Arrow; // default ?
+ VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(rWindowPeer);
+ if (pWindow)
+ eType = pWindow->GetPointer();
+ return eType;
+}
+
+void VCLUnoHelper::setMousePointer(const css::uno::Reference<css::awt::XWindowPeer>& rWindowPeer, ::PointerStyle ePointer)
+{
+ VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(rWindowPeer);
+ if (!pWindow)
+ return;
+ pWindow->SetPointer(ePointer);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */