summaryrefslogtreecommitdiffstats
path: root/toolkit
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
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')
-rw-r--r--toolkit/CppunitTest_toolkit.mk58
-rw-r--r--toolkit/CppunitTest_toolkit_a11y.mk54
-rw-r--r--toolkit/IwyuFilter_toolkit.yaml103
-rw-r--r--toolkit/JunitTest_toolkit_complex.mk44
-rw-r--r--toolkit/JunitTest_toolkit_unoapi_1.mk24
-rw-r--r--toolkit/JunitTest_toolkit_unoapi_2.mk24
-rw-r--r--toolkit/JunitTest_toolkit_unoapi_3.mk24
-rw-r--r--toolkit/JunitTest_toolkit_unoapi_4.mk24
-rw-r--r--toolkit/Library_tk.mk151
-rw-r--r--toolkit/Makefile7
-rw-r--r--toolkit/Module_toolkit.mk44
-rw-r--r--toolkit/README.md15
-rw-r--r--toolkit/inc/awt/animatedimagespeer.hxx103
-rw-r--r--toolkit/inc/awt/vclxbitmap.hxx62
-rw-r--r--toolkit/inc/awt/vclxcontainer.hxx53
-rw-r--r--toolkit/inc/awt/vclxgraphics.hxx117
-rw-r--r--toolkit/inc/awt/vclxpointer.hxx58
-rw-r--r--toolkit/inc/awt/vclxprinter.hxx194
-rw-r--r--toolkit/inc/awt/vclxregion.hxx62
-rw-r--r--toolkit/inc/awt/vclxspinbutton.hxx88
-rw-r--r--toolkit/inc/awt/vclxsystemdependentwindow.hxx40
-rw-r--r--toolkit/inc/awt/vclxtabpagecontainer.hxx73
-rw-r--r--toolkit/inc/awt/vclxtopwindow.hxx65
-rw-r--r--toolkit/inc/awt/vclxwindows.hxx605
-rw-r--r--toolkit/inc/controls/accessiblecontrolcontext.hxx116
-rw-r--r--toolkit/inc/controls/animatedimages.hxx89
-rw-r--r--toolkit/inc/controls/controlmodelcontainerbase.hxx270
-rw-r--r--toolkit/inc/controls/dialogcontrol.hxx299
-rw-r--r--toolkit/inc/controls/eventcontainer.hxx82
-rw-r--r--toolkit/inc/controls/filectrl.hxx70
-rw-r--r--toolkit/inc/controls/formattedcontrol.hxx124
-rw-r--r--toolkit/inc/controls/geometrycontrolmodel.hxx251
-rw-r--r--toolkit/inc/controls/geometrycontrolmodel_impl.hxx69
-rw-r--r--toolkit/inc/controls/roadmapcontrol.hxx185
-rw-r--r--toolkit/inc/controls/roadmapentry.hxx69
-rw-r--r--toolkit/inc/controls/stdtabcontroller.hxx86
-rw-r--r--toolkit/inc/controls/stdtabcontrollermodel.hxx123
-rw-r--r--toolkit/inc/controls/svmedit.hxx32
-rw-r--r--toolkit/inc/controls/table/defaultinputhandler.hxx57
-rw-r--r--toolkit/inc/controls/table/gridtablerenderer.hxx116
-rw-r--r--toolkit/inc/controls/table/mousefunction.hxx133
-rw-r--r--toolkit/inc/controls/table/tablecontrol.hxx174
-rw-r--r--toolkit/inc/controls/table/tablecontrolinterface.hxx234
-rw-r--r--toolkit/inc/controls/table/tableinputhandler.hxx63
-rw-r--r--toolkit/inc/controls/table/tablemodel.hxx454
-rw-r--r--toolkit/inc/controls/table/tablerenderer.hxx249
-rw-r--r--toolkit/inc/controls/table/tablesort.hxx79
-rw-r--r--toolkit/inc/controls/table/tabletypes.hxx52
-rw-r--r--toolkit/inc/controls/tabpagecontainer.hxx127
-rw-r--r--toolkit/inc/controls/tabpagemodel.hxx79
-rw-r--r--toolkit/inc/controls/tkscrollbar.hxx112
-rw-r--r--toolkit/inc/controls/treecontrolpeer.hxx166
-rw-r--r--toolkit/inc/controls/unocontrolcontainer.hxx151
-rw-r--r--toolkit/inc/controls/unocontrolcontainermodel.hxx51
-rw-r--r--toolkit/inc/helper/accessibilityclient.hxx57
-rw-r--r--toolkit/inc/helper/btndlg.hxx89
-rw-r--r--toolkit/inc/helper/imagealign.hxx52
-rw-r--r--toolkit/inc/helper/msgbox.hxx78
-rw-r--r--toolkit/inc/helper/property.hxx246
-rw-r--r--toolkit/inc/helper/scrollabledialog.hxx66
-rw-r--r--toolkit/inc/helper/servicenames.hxx24
-rw-r--r--toolkit/inc/helper/tkresmgr.hxx34
-rw-r--r--toolkit/inc/helper/unopropertyarrayhelper.hxx52
-rw-r--r--toolkit/inc/helper/unowrapper.hxx73
-rw-r--r--toolkit/qa/complex/toolkit/AccessibleStatusBarItem.java359
-rw-r--r--toolkit/qa/complex/toolkit/Assert.java185
-rw-r--r--toolkit/qa/complex/toolkit/GridControl.java746
-rw-r--r--toolkit/qa/complex/toolkit/accessibility/_XAccessibleComponent.java463
-rw-r--r--toolkit/qa/complex/toolkit/accessibility/_XAccessibleContext.java244
-rw-r--r--toolkit/qa/complex/toolkit/accessibility/_XAccessibleEventBroadcaster.java178
-rw-r--r--toolkit/qa/complex/toolkit/accessibility/_XAccessibleExtendedComponent.java75
-rw-r--r--toolkit/qa/complex/toolkit/accessibility/_XAccessibleText.java1001
-rw-r--r--toolkit/qa/complex/toolkit/awtgrid/DummyColumn.java167
-rw-r--r--toolkit/qa/complex/toolkit/awtgrid/GridDataListener.java107
-rw-r--r--toolkit/qa/complex/toolkit/awtgrid/TMutableGridDataModel.java449
-rw-r--r--toolkit/qa/cppunit/Dialog.cxx73
-rw-r--r--toolkit/qa/cppunit/EventContainer.cxx84
-rw-r--r--toolkit/qa/cppunit/UnitConversion.cxx215
-rw-r--r--toolkit/qa/cppunit/a11y/AccessibleStatusBarTest.cxx139
-rw-r--r--toolkit/qa/cppunit/a11y/XAccessibleComponentTester.cxx291
-rw-r--r--toolkit/qa/cppunit/a11y/XAccessibleComponentTester.hxx66
-rw-r--r--toolkit/qa/cppunit/a11y/XAccessibleContextTester.cxx164
-rw-r--r--toolkit/qa/cppunit/a11y/XAccessibleContextTester.hxx62
-rw-r--r--toolkit/qa/cppunit/a11y/XAccessibleEventBroadcasterTester.cxx185
-rw-r--r--toolkit/qa/cppunit/a11y/XAccessibleEventBroadcasterTester.hxx54
-rw-r--r--toolkit/qa/cppunit/a11y/XAccessibleExtendedComponentTester.cxx53
-rw-r--r--toolkit/qa/cppunit/a11y/XAccessibleExtendedComponentTester.hxx50
-rw-r--r--toolkit/qa/unoapi/knownissues.xcl259
-rw-r--r--toolkit/qa/unoapi/testdocuments/poliball.gifbin0 -> 945 bytes
-rw-r--r--toolkit/qa/unoapi/toolkit_1.sce40
-rw-r--r--toolkit/qa/unoapi/toolkit_2.sce36
-rw-r--r--toolkit/qa/unoapi/toolkit_3.sce37
-rw-r--r--toolkit/qa/unoapi/toolkit_4.sce31
-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
-rw-r--r--toolkit/test/accessibility/AWB.sxwbin0 -> 9257 bytes
-rw-r--r--toolkit/test/accessibility/AccTreeNode.java346
-rw-r--r--toolkit/test/accessibility/AccessibilityTree.java379
-rw-r--r--toolkit/test/accessibility/AccessibilityTreeModel.java471
-rw-r--r--toolkit/test/accessibility/AccessibilityTreeModelBase.java140
-rw-r--r--toolkit/test/accessibility/AccessibilityWorkBench.java591
-rw-r--r--toolkit/test/accessibility/AccessibleActionHandler.java91
-rw-r--r--toolkit/test/accessibility/AccessibleActionNode.java67
-rw-r--r--toolkit/test/accessibility/AccessibleCellHandler.java168
-rw-r--r--toolkit/test/accessibility/AccessibleComponentHandler.java121
-rw-r--r--toolkit/test/accessibility/AccessibleContextHandler.java88
-rw-r--r--toolkit/test/accessibility/AccessibleEditableTextHandler.java53
-rw-r--r--toolkit/test/accessibility/AccessibleExtendedComponentHandler.java93
-rw-r--r--toolkit/test/accessibility/AccessibleHyperlinkHandler.java53
-rw-r--r--toolkit/test/accessibility/AccessibleHypertextHandler.java53
-rw-r--r--toolkit/test/accessibility/AccessibleImageHandler.java70
-rw-r--r--toolkit/test/accessibility/AccessibleRelationHandler.java115
-rw-r--r--toolkit/test/accessibility/AccessibleSelectionHandler.java145
-rw-r--r--toolkit/test/accessibility/AccessibleTableHandler.java103
-rw-r--r--toolkit/test/accessibility/AccessibleTextHandler.java821
-rw-r--r--toolkit/test/accessibility/AccessibleTreeHandler.java130
-rw-r--r--toolkit/test/accessibility/AccessibleTreeNode.java113
-rw-r--r--toolkit/test/accessibility/AccessibleUNOHandler.java126
-rw-r--r--toolkit/test/accessibility/Canvas.java463
-rw-r--r--toolkit/test/accessibility/CanvasShape.java286
-rw-r--r--toolkit/test/accessibility/ChildEventHandler.java66
-rw-r--r--toolkit/test/accessibility/ContextEventHandler.java70
-rw-r--r--toolkit/test/accessibility/EventHandler.java75
-rw-r--r--toolkit/test/accessibility/EventListener.java108
-rw-r--r--toolkit/test/accessibility/EventQueue.java140
-rw-r--r--toolkit/test/accessibility/GeometryEventHandler.java71
-rw-r--r--toolkit/test/accessibility/HelpWindow.java189
-rw-r--r--toolkit/test/accessibility/MessageArea.java131
-rw-r--r--toolkit/test/accessibility/NodeFactory.java142
-rw-r--r--toolkit/test/accessibility/NodeHandler.java133
-rw-r--r--toolkit/test/accessibility/NodeMap.java117
-rw-r--r--toolkit/test/accessibility/OfficeConnection.java98
-rw-r--r--toolkit/test/accessibility/Options.java122
-rw-r--r--toolkit/test/accessibility/QueuedListener.java70
-rw-r--r--toolkit/test/accessibility/QueuedTopWindowListener.java97
-rw-r--r--toolkit/test/accessibility/SelectionDialog.java203
-rw-r--r--toolkit/test/accessibility/SimpleOffice.java139
-rw-r--r--toolkit/test/accessibility/StringNode.java36
-rw-r--r--toolkit/test/accessibility/TableEventHandler.java58
-rw-r--r--toolkit/test/accessibility/TopWindowListener.java175
-rw-r--r--toolkit/test/accessibility/VectorNode.java74
-rw-r--r--toolkit/test/accessibility/about.html8
-rw-r--r--toolkit/test/accessibility/help.html91
-rw-r--r--toolkit/test/accessibility/jawb.mf3
-rw-r--r--toolkit/test/accessibility/news.html36
-rw-r--r--toolkit/test/accessibility/ov/ContextView.java140
-rw-r--r--toolkit/test/accessibility/ov/FocusView.java140
-rw-r--r--toolkit/test/accessibility/ov/ListeningObjectView.java80
-rw-r--r--toolkit/test/accessibility/ov/ObjectView.java80
-rw-r--r--toolkit/test/accessibility/ov/ObjectViewContainer.java152
-rw-r--r--toolkit/test/accessibility/ov/TextView.java133
-rw-r--r--toolkit/test/accessibility/tools/NameProvider.java277
-rw-r--r--toolkit/util/tk.component394
247 files changed, 76136 insertions, 0 deletions
diff --git a/toolkit/CppunitTest_toolkit.mk b/toolkit/CppunitTest_toolkit.mk
new file mode 100644
index 0000000000..496ed0d7ba
--- /dev/null
+++ b/toolkit/CppunitTest_toolkit.mk
@@ -0,0 +1,58 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,toolkit))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,toolkit, \
+ toolkit/qa/cppunit/Dialog \
+ toolkit/qa/cppunit/EventContainer \
+ toolkit/qa/cppunit/UnitConversion \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,toolkit, \
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ sal \
+ salhelper \
+ test \
+ tk \
+ tl \
+ unotest \
+ vcl \
+))
+
+$(eval $(call gb_CppunitTest_use_api,toolkit,\
+ offapi \
+ udkapi \
+))
+
+$(eval $(call gb_CppunitTest_use_externals,toolkit,\
+ boost_headers \
+))
+
+$(eval $(call gb_CppunitTest_use_ure,toolkit))
+
+$(eval $(call gb_CppunitTest_use_configuration,toolkit))
+
+$(eval $(call gb_CppunitTest_use_vcl,toolkit))
+
+$(eval $(call gb_CppunitTest_use_components,toolkit,\
+ comphelper/util/comphelp \
+ configmgr/source/configmgr \
+ framework/util/fwk \
+ i18npool/util/i18npool \
+ sfx2/util/sfx \
+ toolkit/util/tk \
+ ucb/source/core/ucb1 \
+ ucb/source/ucp/file/ucpfile1 \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/toolkit/CppunitTest_toolkit_a11y.mk b/toolkit/CppunitTest_toolkit_a11y.mk
new file mode 100644
index 0000000000..4b8c60b0a6
--- /dev/null
+++ b/toolkit/CppunitTest_toolkit_a11y.mk
@@ -0,0 +1,54 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,toolkit_a11y))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,toolkit_a11y, \
+ toolkit/qa/cppunit/a11y/AccessibleStatusBarTest \
+ toolkit/qa/cppunit/a11y/XAccessibleComponentTester \
+ toolkit/qa/cppunit/a11y/XAccessibleContextTester \
+ toolkit/qa/cppunit/a11y/XAccessibleEventBroadcasterTester \
+ toolkit/qa/cppunit/a11y/XAccessibleExtendedComponentTester \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,toolkit_a11y, \
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ sal \
+ salhelper \
+ subsequenttest \
+ test \
+ tk \
+ tl \
+ unotest \
+ vcl \
+))
+
+$(eval $(call gb_CppunitTest_use_api,toolkit_a11y,\
+ offapi \
+ udkapi \
+))
+
+$(eval $(call gb_CppunitTest_use_externals,toolkit_a11y,\
+ boost_headers \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,toolkit_a11y))
+
+$(eval $(call gb_CppunitTest_use_ure,toolkit_a11y))
+
+$(eval $(call gb_CppunitTest_use_configuration,toolkit_a11y))
+
+$(eval $(call gb_CppunitTest_use_vcl,toolkit_a11y))
+
+$(eval $(call gb_CppunitTest_use_rdb,toolkit_a11y,services))
+
+# vim: set noet sw=4 ts=4:
diff --git a/toolkit/IwyuFilter_toolkit.yaml b/toolkit/IwyuFilter_toolkit.yaml
new file mode 100644
index 0000000000..6606014d29
--- /dev/null
+++ b/toolkit/IwyuFilter_toolkit.yaml
@@ -0,0 +1,103 @@
+---
+assumeFilename: toolkit/source/controls/unocontrol.cxx
+excludelist:
+ toolkit/source/awt/vclxmenu.cxx:
+ # Needed for direct member access
+ - vcl/window.hxx
+ toolkit/source/helper/servicenames.cxx:
+ # Needed for extern array declarations
+ - toolkit/helper/servicenames.hxx
+ toolkit/inc/awt/animatedimagespeer.hxx:
+ # base class has to be a complete type
+ - com/sun/star/awt/XAnimation.hpp
+ - com/sun/star/container/XContainerListener.hpp
+ - com/sun/star/util/XModifyListener.hpp
+ - toolkit/awt/vclxwindow.hxx
+ toolkit/inc/awt/vclxpointer.hxx:
+ # base class has to be a complete type
+ - com/sun/star/awt/XPointer.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ - com/sun/star/lang/XUnoTunnel.hpp
+ toolkit/inc/awt/vclxspinbutton.hxx:
+ # base class has to be a complete type
+ - com/sun/star/awt/XSpinValue.hpp
+ toolkit/inc/awt/vclxprinter.hxx:
+ # base class has to be a complete type
+ - com/sun/star/awt/XPrinterPropertySet.hpp
+ - com/sun/star/awt/XInfoPrinter.hpp
+ - com/sun/star/awt/XPrinterPropertySet.hpp
+ - com/sun/star/awt/XPrinterServer.hpp
+ - com/sun/star/lang/XServiceInfo.hpp
+ toolkit/inc/awt/vclxtabpagecontainer.hxx:
+ # base class has to be a complete type
+ - com/sun/star/awt/tab/XTabPageContainer.hpp
+ - com/sun/star/container/XContainerListener.hpp
+ - toolkit/awt/vclxcontainer.hxx
+ toolkit/inc/controls/accessiblecontrolcontext.hxx:
+ # base class has to be a complete type
+ - com/sun/star/lang/XEventListener.hpp
+ toolkit/inc/controls/animatedimages.hxx:
+ # base class has to be a complete type
+ - com/sun/star/awt/XAnimatedImages.hpp
+ - toolkit/controls/unocontrolmodel.hxx
+ toolkit/inc/controls/controlmodelcontainerbase.hxx:
+ # base class has to be a complete type
+ - com/sun/star/awt/tab/XTabPageModel.hpp
+ - com/sun/star/awt/XTabControllerModel.hpp
+ - com/sun/star/beans/XPropertyChangeListener.hpp
+ - com/sun/star/container/XContainer.hpp
+ - com/sun/star/container/XNameContainer.hpp
+ - com/sun/star/lang/XInitialization.hpp
+ - com/sun/star/lang/XMultiServiceFactory.hpp
+ - com/sun/star/util/XChangesListener.hpp
+ - com/sun/star/util/XChangesNotifier.hpp
+ - toolkit/controls/unocontrolcontainer.hxx
+ toolkit/inc/controls/dialogcontrol.hxx:
+ # base class has to be a complete type
+ - com/sun/star/awt/UnoControlDialog.hpp
+ toolkit/inc/controls/eventcontainer.hxx:
+ # base class has to be a complete type
+ - com/sun/star/container/XContainer.hpp
+ - com/sun/star/container/XNameContainer.hpp
+ toolkit/inc/controls/geometrycontrolmodel.hxx:
+ # base class has to be a complete type
+ - com/sun/star/script/XScriptEventsSupplier.hpp
+ - com/sun/star/util/XCloneable.hpp
+ # Needed for template classes
+ - controls/geometrycontrolmodel_impl.hxx
+ toolkit/inc/controls/roadmapcontrol.hxx:
+ # base class has to be a complete type
+ - com/sun/star/awt/XItemEventBroadcaster.hpp
+ - com/sun/star/awt/XItemListener.hpp
+ - com/sun/star/beans/XPropertyChangeListener.hpp
+ - com/sun/star/container/XContainerListener.hpp
+ toolkit/inc/controls/roadmapentry.hxx:
+ # base class has to be a complete type
+ - com/sun/star/lang/XServiceInfo.hpp
+ toolkit/inc/controls/tabpagecontainer.hxx:
+ # base class has to be a complete type
+ - com/sun/star/awt/tab/XTabPageContainer.hpp
+ - toolkit/controls/controlmodelcontainerbase.hxx
+ toolkit/inc/controls/tabpagemodel.hxx:
+ # base class has to be a complete type
+ - com/sun/star/awt/tab/XTabPage.hpp
+ - toolkit/controls/unocontrolcontainer.hxx
+ toolkit/inc/controls/unocontrolcontainer.hxx:
+ # base class has to be a complete type
+ - com/sun/star/awt/XControlContainer.hpp
+ - com/sun/star/awt/XUnoControlContainer.hpp
+ - com/sun/star/container/XContainer.hpp
+ - com/sun/star/container/XIdentifierContainer.hpp
+ - toolkit/controls/unocontrolbase.hxx
+ toolkit/source/controls/animatedimages.cxx:
+ # Actually used
+ - com/sun/star/beans/XPropertySetInfo.hpp
+ toolkit/source/awt/vclxwindow.cxx:
+ # Needed for rtl::math::round
+ - rtl/math.hxx
+ toolkit/source/hatchwindow/hatchwindow.cxx:
+ # Actually used
+ - com/sun/star/embed/XHatchWindowController.hpp
+ toolkit/source/helper/servicenames.cxx:
+ # Needed for extern
+ - helper/servicenames.hxx
diff --git a/toolkit/JunitTest_toolkit_complex.mk b/toolkit/JunitTest_toolkit_complex.mk
new file mode 100644
index 0000000000..4a06582a00
--- /dev/null
+++ b/toolkit/JunitTest_toolkit_complex.mk
@@ -0,0 +1,44 @@
+#
+# 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 .
+#
+
+$(eval $(call gb_JunitTest_JunitTest,toolkit_complex))
+
+$(eval $(call gb_JunitTest_use_jars,toolkit_complex,\
+ OOoRunner \
+ libreoffice \
+ test \
+))
+
+$(eval $(call gb_JunitTest_add_sourcefiles,toolkit_complex,\
+ toolkit/qa/complex/toolkit/accessibility/_XAccessibleComponent \
+ toolkit/qa/complex/toolkit/accessibility/_XAccessibleContext \
+ toolkit/qa/complex/toolkit/accessibility/_XAccessibleEventBroadcaster \
+ toolkit/qa/complex/toolkit/accessibility/_XAccessibleExtendedComponent \
+ toolkit/qa/complex/toolkit/accessibility/_XAccessibleText \
+ toolkit/qa/complex/toolkit/Assert \
+ toolkit/qa/complex/toolkit/awtgrid/GridDataListener \
+ toolkit/qa/complex/toolkit/awtgrid/TMutableGridDataModel \
+ toolkit/qa/complex/toolkit/awtgrid/DummyColumn \
+ toolkit/qa/complex/toolkit/GridControl \
+))
+
+$(eval $(call gb_JunitTest_add_classes,toolkit_complex,\
+ complex.toolkit.GridControl \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/toolkit/JunitTest_toolkit_unoapi_1.mk b/toolkit/JunitTest_toolkit_unoapi_1.mk
new file mode 100644
index 0000000000..ddd916107f
--- /dev/null
+++ b/toolkit/JunitTest_toolkit_unoapi_1.mk
@@ -0,0 +1,24 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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 .
+#
+
+$(eval $(call gb_JunitTest_JunitTest,toolkit_unoapi_1))
+
+$(eval $(call gb_JunitTest_set_unoapi_test_defaults,toolkit_unoapi_1))
+
+# vim: set noet sw=4 ts=4:
diff --git a/toolkit/JunitTest_toolkit_unoapi_2.mk b/toolkit/JunitTest_toolkit_unoapi_2.mk
new file mode 100644
index 0000000000..642829a23a
--- /dev/null
+++ b/toolkit/JunitTest_toolkit_unoapi_2.mk
@@ -0,0 +1,24 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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 .
+#
+
+$(eval $(call gb_JunitTest_JunitTest,toolkit_unoapi_2))
+
+$(eval $(call gb_JunitTest_set_unoapi_test_defaults,toolkit_unoapi_2))
+
+# vim: set noet sw=4 ts=4:
diff --git a/toolkit/JunitTest_toolkit_unoapi_3.mk b/toolkit/JunitTest_toolkit_unoapi_3.mk
new file mode 100644
index 0000000000..71c69d0a2e
--- /dev/null
+++ b/toolkit/JunitTest_toolkit_unoapi_3.mk
@@ -0,0 +1,24 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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 .
+#
+
+$(eval $(call gb_JunitTest_JunitTest,toolkit_unoapi_3))
+
+$(eval $(call gb_JunitTest_set_unoapi_test_defaults,toolkit_unoapi_3))
+
+# vim: set noet sw=4 ts=4:
diff --git a/toolkit/JunitTest_toolkit_unoapi_4.mk b/toolkit/JunitTest_toolkit_unoapi_4.mk
new file mode 100644
index 0000000000..e615716333
--- /dev/null
+++ b/toolkit/JunitTest_toolkit_unoapi_4.mk
@@ -0,0 +1,24 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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 .
+#
+
+$(eval $(call gb_JunitTest_JunitTest,toolkit_unoapi_4))
+
+$(eval $(call gb_JunitTest_set_unoapi_test_defaults,toolkit_unoapi_4))
+
+# vim: set noet sw=4 ts=4:
diff --git a/toolkit/Library_tk.mk b/toolkit/Library_tk.mk
new file mode 100644
index 0000000000..bcea9abb6d
--- /dev/null
+++ b/toolkit/Library_tk.mk
@@ -0,0 +1,151 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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 .
+#
+
+$(eval $(call gb_Library_Library,tk))
+
+$(eval $(call gb_Library_set_componentfile,tk,toolkit/util/tk,services))
+
+$(eval $(call gb_Library_use_externals,tk,\
+ boost_headers \
+))
+
+$(eval $(call gb_Library_set_include,tk,\
+ $$(INCLUDE) \
+ -I$(SRCDIR)/toolkit/inc \
+ -I$(SRCDIR)/toolkit/source \
+))
+
+$(eval $(call gb_Library_add_defs,tk,\
+ -DTOOLKIT_DLLIMPLEMENTATION \
+ -DSVT_DLL_NAME=\"$(call gb_Library_get_runtime_filename,$(call gb_Library__get_name,svt))\" \
+))
+
+$(eval $(call gb_Library_use_sdk_api,tk))
+
+$(eval $(call gb_Library_use_libraries,tk,\
+ comphelper \
+ cppu \
+ cppuhelper \
+ sal \
+ salhelper \
+ i18nlangtag \
+ svl \
+ tl \
+ utl \
+ vcl \
+))
+
+$(eval $(call gb_Library_add_exception_objects,tk,\
+ toolkit/source/awt/asynccallback \
+ toolkit/source/awt/stylesettings \
+ toolkit/source/awt/scrollabledialog \
+ toolkit/source/awt/vclxaccessiblecomponent \
+ toolkit/source/awt/vclxbitmap \
+ toolkit/source/awt/vclxcontainer \
+ toolkit/source/awt/vclxdevice \
+ toolkit/source/awt/vclxfont \
+ toolkit/source/awt/vclxgraphics \
+ toolkit/source/awt/vclxmenu \
+ toolkit/source/awt/vclxpointer \
+ toolkit/source/awt/vclxprinter \
+ toolkit/source/awt/vclxregion \
+ toolkit/source/awt/vclxspinbutton \
+ toolkit/source/awt/vclxsystemdependentwindow \
+ toolkit/source/awt/vclxtabpagecontainer \
+ toolkit/source/awt/animatedimagespeer \
+ toolkit/source/awt/vclxtoolkit \
+ toolkit/source/awt/vclxtopwindow \
+ toolkit/source/awt/vclxwindow \
+ toolkit/source/awt/vclxwindow1 \
+ toolkit/source/awt/vclxwindows \
+ toolkit/source/controls/accessiblecontrolcontext \
+ toolkit/source/controls/controlmodelcontainerbase \
+ toolkit/source/controls/dialogcontrol \
+ toolkit/source/controls/eventcontainer \
+ toolkit/source/controls/filectrl \
+ toolkit/source/controls/formattedcontrol \
+ toolkit/source/controls/geometrycontrolmodel \
+ toolkit/source/controls/grid/defaultgridcolumnmodel \
+ toolkit/source/controls/grid/defaultgriddatamodel \
+ toolkit/source/controls/grid/gridcolumn \
+ toolkit/source/controls/grid/grideventforwarder \
+ toolkit/source/controls/grid/sortablegriddatamodel \
+ toolkit/source/controls/grid/gridcontrol \
+ toolkit/source/controls/roadmapcontrol \
+ toolkit/source/controls/roadmapentry \
+ toolkit/source/controls/svtxgridcontrol \
+ toolkit/source/controls/svmedit \
+ toolkit/source/controls/tabpagecontainer \
+ toolkit/source/controls/tabpagemodel \
+ toolkit/source/controls/stdtabcontroller \
+ toolkit/source/controls/stdtabcontrollermodel \
+ toolkit/source/controls/tkscrollbar \
+ toolkit/source/controls/tkspinbutton \
+ toolkit/source/controls/animatedimages \
+ toolkit/source/controls/spinningprogress \
+ toolkit/source/controls/table/cellvalueconversion \
+ toolkit/source/controls/table/defaultinputhandler \
+ toolkit/source/controls/table/gridtablerenderer \
+ toolkit/source/controls/table/mousefunction \
+ toolkit/source/controls/table/tablecontrol \
+ toolkit/source/controls/table/tablecontrol_impl \
+ toolkit/source/controls/table/tabledatawindow \
+ toolkit/source/controls/table/tablegeometry \
+ toolkit/source/controls/tree/treecontrol \
+ toolkit/source/controls/tree/treecontrolpeer \
+ toolkit/source/controls/tree/treedatamodel \
+ toolkit/source/controls/unocontrol \
+ toolkit/source/controls/unocontrolbase \
+ toolkit/source/controls/unocontrolcontainer \
+ toolkit/source/controls/unocontrolcontainermodel \
+ toolkit/source/controls/unocontrolmodel \
+ toolkit/source/controls/unocontroltablemodel \
+ toolkit/source/controls/unocontrols \
+ toolkit/source/controls/unogridcolumnfacade \
+ toolkit/source/hatchwindow/documentcloser \
+ toolkit/source/hatchwindow/hatchwindow \
+ toolkit/source/hatchwindow/hatchwindowfactory \
+ toolkit/source/hatchwindow/ipwin \
+ toolkit/source/helper/accessibilityclient \
+ toolkit/source/helper/btndlg \
+ toolkit/source/helper/imagealign \
+ toolkit/source/helper/listenermultiplexer \
+ toolkit/source/helper/property \
+ toolkit/source/helper/servicenames \
+ toolkit/source/helper/tkresmgr \
+ toolkit/source/helper/unopropertyarrayhelper \
+ toolkit/source/helper/unowrapper \
+ toolkit/source/helper/vclunohelper \
+))
+
+ifeq ($(OS),MACOSX)
+$(eval $(call gb_Library_add_cxxflags,tk,\
+ $(gb_OBJCXXFLAGS) \
+))
+$(eval $(call gb_Library_add_libs,tk,\
+ -lobjc \
+))
+endif
+
+ifeq ($(OS),iOS)
+$(eval $(call gb_Library_add_cxxflags,tk,\
+ $(gb_OBJCXXFLAGS)))
+endif
+
+# vim: set noet sw=4 ts=4:
diff --git a/toolkit/Makefile b/toolkit/Makefile
new file mode 100644
index 0000000000..ccb1c85a04
--- /dev/null
+++ b/toolkit/Makefile
@@ -0,0 +1,7 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+
+module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST))))
+
+include $(module_directory)/../solenv/gbuild/partial_build.mk
+
+# vim: set noet sw=4 ts=4:
diff --git a/toolkit/Module_toolkit.mk b/toolkit/Module_toolkit.mk
new file mode 100644
index 0000000000..d039559316
--- /dev/null
+++ b/toolkit/Module_toolkit.mk
@@ -0,0 +1,44 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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 .
+#
+
+$(eval $(call gb_Module_Module,toolkit))
+
+$(eval $(call gb_Module_add_targets,toolkit,\
+ Library_tk \
+))
+
+# FIXME fails on some tinderboxes, needs investigation
+ifneq ($(OS),WNT)
+$(eval $(call gb_Module_add_check_targets,toolkit,\
+ CppunitTest_toolkit \
+ CppunitTest_toolkit_a11y \
+))
+endif
+
+ifneq ($(OOO_JUNIT_JAR),)
+$(eval $(call gb_Module_add_subsequentcheck_targets,toolkit,\
+ JunitTest_toolkit_complex \
+ JunitTest_toolkit_unoapi_1 \
+ JunitTest_toolkit_unoapi_2 \
+ JunitTest_toolkit_unoapi_3 \
+ JunitTest_toolkit_unoapi_4 \
+))
+endif
+
+# vim: set noet sw=4 ts=4:
diff --git a/toolkit/README.md b/toolkit/README.md
new file mode 100644
index 0000000000..f41fb3760c
--- /dev/null
+++ b/toolkit/README.md
@@ -0,0 +1,15 @@
+# Abstract Windowing Toolkit
+
+"Abstract" windowing thing. UNO implementations of windowing stuff so that it
+can be used from Basic or Java. But also stuff that has no connection to Basic
+or Java.
+
+## Notes
+
+The "awt" here has no relation to the Java AWT, as far as I know. It
+might be inspired by it API-wise, perhaps. (If you know differently, feel free
+to improve this `README.md` file.)
+
+Also note that `toolkit/` is itself not really a toolkit, it is at root a
+reasonably simple wrapper of `vcl/`. If you came here looking for a
+toolkit, please look at `vcl/` instead.
diff --git a/toolkit/inc/awt/animatedimagespeer.hxx b/toolkit/inc/awt/animatedimagespeer.hxx
new file mode 100644
index 0000000000..839e249b3f
--- /dev/null
+++ b/toolkit/inc/awt/animatedimagespeer.hxx
@@ -0,0 +1,103 @@
+/* -*- 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 <toolkit/awt/vclxwindow.hxx>
+#include <com/sun/star/container/XContainerListener.hpp>
+
+#include <com/sun/star/awt/XAnimatedImages.hpp>
+#include <com/sun/star/awt/XAnimation.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/util/XModifyListener.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+namespace toolkit
+{
+
+
+ //= AnimatedImagesPeer
+
+ struct AnimatedImagesPeer_Data;
+ typedef cppu::ImplInheritanceHelper< VCLXWindow,
+ css::awt::XAnimation,
+ css::container::XContainerListener,
+ css::util::XModifyListener
+ > AnimatedImagesPeer_Base;
+
+ class AnimatedImagesPeer final : public AnimatedImagesPeer_Base
+ {
+ public:
+ AnimatedImagesPeer();
+
+ private:
+ virtual ~AnimatedImagesPeer() override;
+
+ public:
+ // XAnimation
+ virtual void SAL_CALL startAnimation( ) override;
+ virtual void SAL_CALL stopAnimation( ) override;
+ virtual sal_Bool SAL_CALL isAnimationRunning( ) override;
+
+ // VclWindowPeer
+ virtual void SAL_CALL setProperty( const OUString& PropertyName, const css::uno::Any& Value ) override;
+ virtual css::uno::Any SAL_CALL getProperty( const OUString& PropertyName ) 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;
+
+ // XModifyListener
+ virtual void SAL_CALL modified( const css::lang::EventObject& i_event ) override;
+
+ // XComponent
+ void SAL_CALL dispose( ) override;
+
+ struct CachedImage
+ {
+ OUString sImageURL;
+ mutable css::uno::Reference< css::graphic::XGraphic > xGraphic;
+ };
+
+ private:
+ void ProcessWindowEvent( const VclWindowEvent& i_windowEvent ) override;
+
+ /** updates our images with the ones from the given XAnimatedImages component
+ */
+ void impl_updateImages_nolck( const css::uno::Reference< css::uno::XInterface >& i_animatedImages );
+
+ AnimatedImagesPeer(const AnimatedImagesPeer&) = delete;
+ AnimatedImagesPeer& operator=(const AnimatedImagesPeer&) = delete;
+
+ void updateImageList_nothrow();
+ void updateImageList_nothrow( const css::uno::Reference< css::awt::XAnimatedImages >& i_images );
+
+ std::vector< std::vector< CachedImage > > maCachedImageSets;
+ };
+
+
+} // namespace toolkit
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/awt/vclxbitmap.hxx b/toolkit/inc/awt/vclxbitmap.hxx
new file mode 100644
index 0000000000..9edf562c1d
--- /dev/null
+++ b/toolkit/inc/awt/vclxbitmap.hxx
@@ -0,0 +1,62 @@
+/* -*- 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/awt/XBitmap.hpp>
+#include <com/sun/star/awt/XDisplayBitmap.hpp>
+#include <com/sun/star/util/XAccounting.hpp>
+#include <comphelper/servicehelper.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <mutex>
+#include <vcl/bitmapex.hxx>
+
+
+
+
+class VCLXBitmap final : public cppu::WeakImplHelper<
+ css::awt::XBitmap,
+ css::awt::XDisplayBitmap,
+ css::util::XAccounting>
+{
+ std::mutex maMutex;
+ BitmapEx maBitmap;
+
+ std::mutex& GetMutex() { return maMutex; }
+
+
+public:
+ // inline constructors
+ VCLXBitmap() : maMutex(), maBitmap() {}
+ VCLXBitmap(const BitmapEx& rBitmapEx) : maMutex(), maBitmap(rBitmapEx) {}
+
+ void SetBitmap( const BitmapEx& rBmp ) { maBitmap = rBmp; }
+ const BitmapEx& GetBitmap() const { return maBitmap; }
+
+ // css::awt::XBitmap
+ css::awt::Size SAL_CALL getSize() override;
+ css::uno::Sequence< sal_Int8 > SAL_CALL getDIB() override;
+ css::uno::Sequence< sal_Int8 > SAL_CALL getMaskDIB() override;
+
+ // XAccounting
+ sal_Int64 SAL_CALL estimateUsage() override;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/awt/vclxcontainer.hxx b/toolkit/inc/awt/vclxcontainer.hxx
new file mode 100644
index 0000000000..248f2e6505
--- /dev/null
+++ b/toolkit/inc/awt/vclxcontainer.hxx
@@ -0,0 +1,53 @@
+/* -*- 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/awt/XVclContainer.hpp>
+#include <com/sun/star/awt/XVclContainerPeer.hpp>
+#include <cppuhelper/implbase.hxx>
+
+#include <toolkit/awt/vclxwindow.hxx>
+
+class VCLXContainer : public cppu::ImplInheritanceHelper<VCLXWindow,
+ css::awt::XVclContainer,
+ css::awt::XVclContainerPeer>
+{
+public:
+ VCLXContainer();
+ virtual ~VCLXContainer() override;
+
+ // css::awt::XVclContainer
+ void SAL_CALL addVclContainerListener( const css::uno::Reference< css::awt::XVclContainerListener >& l ) override;
+ void SAL_CALL removeVclContainerListener( const css::uno::Reference< css::awt::XVclContainerListener >& l ) override;
+ css::uno::Sequence< css::uno::Reference< css::awt::XWindow > > SAL_CALL getWindows( ) override;
+
+ // css::awt::XVclContainerPeer
+ void SAL_CALL enableDialogControl( sal_Bool bEnable ) override;
+ void SAL_CALL setTabOrder( const css::uno::Sequence< css::uno::Reference< css::awt::XWindow > >& WindowOrder, const css::uno::Sequence< css::uno::Any >& Tabs, sal_Bool GroupControl ) override;
+ void SAL_CALL setGroup( const css::uno::Sequence< css::uno::Reference< css::awt::XWindow > >& Windows ) override;
+
+ // css::awt::XVclWindowPeer
+ void SAL_CALL setProperty( const OUString& PropertyName, const css::uno::Any& Value ) override;
+
+ static void ImplGetPropertyIds( std::vector< sal_uInt16 > &aIds );
+ virtual void GetPropertyIds( std::vector< sal_uInt16 > &aIds ) override { return ImplGetPropertyIds( aIds ); }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/awt/vclxgraphics.hxx b/toolkit/inc/awt/vclxgraphics.hxx
new file mode 100644
index 0000000000..acf03dd178
--- /dev/null
+++ b/toolkit/inc/awt/vclxgraphics.hxx
@@ -0,0 +1,117 @@
+/* -*- 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 <comphelper/servicehelper.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <tools/color.hxx>
+#include <o3tl/typed_flags_set.hxx>
+#include <vcl/font.hxx>
+#include <vcl/rendercontext/RasterOp.hxx>
+#include <vcl/vclptr.hxx>
+
+#include <com/sun/star/awt/XGraphics2.hpp>
+
+#include <memory>
+
+class OutputDevice;
+namespace vcl { class Region; }
+namespace com::sun::star::graphic { class XGraphic; }
+
+
+enum class InitOutDevFlags
+{
+ NONE = 0x0000,
+ FONT = 0x0001,
+ COLORS = 0x0002,
+};
+namespace o3tl
+{
+ template<> struct typed_flags<InitOutDevFlags> : is_typed_flags<InitOutDevFlags, 0x03> {};
+}
+
+
+
+
+class VCLXGraphics final : public cppu::WeakImplHelper<
+ css::awt::XGraphics2>
+{
+private:
+ // used to return same reference on each call to getDevice()
+ css::uno::Reference< css::awt::XDevice> mxDevice;
+
+ VclPtr<OutputDevice> mpOutputDevice;
+ vcl::Font maFont;
+ Color maTextColor;
+ Color maTextFillColor;
+ Color maLineColor;
+ Color maFillColor;
+ RasterOp meRasterOp;
+ std::unique_ptr<vcl::Region> mpClipRegion;
+
+ void initAttrs();
+
+public:
+ VCLXGraphics();
+ virtual ~VCLXGraphics() override;
+
+ void Init( OutputDevice* pOutDev );
+ void InitOutputDevice( InitOutDevFlags nFlags );
+
+ void SetOutputDevice( OutputDevice* pOutDev );
+ OutputDevice* GetOutputDevice() const { return mpOutputDevice; }
+
+ // css::awt::XGraphics Attributes
+ virtual css::uno::Reference< css::awt::XDevice > SAL_CALL getDevice() override;
+ virtual void SAL_CALL setTextColor( ::sal_Int32 _textcolor ) override;
+ virtual void SAL_CALL setTextFillColor( ::sal_Int32 _textfillcolor ) override;
+ virtual void SAL_CALL setLineColor( ::sal_Int32 _linecolor ) override;
+ virtual void SAL_CALL setFillColor( ::sal_Int32 _fillcolor ) override;
+ virtual void SAL_CALL setRasterOp( css::awt::RasterOperation _rasterop ) override;
+ virtual void SAL_CALL setFont( const css::uno::Reference< css::awt::XFont >& _font ) override;
+ virtual css::awt::SimpleFontMetric SAL_CALL getFontMetric() override;
+
+ // css::awt::XGraphics Methods
+ virtual void SAL_CALL selectFont( const css::awt::FontDescriptor& aDescription ) override;
+ virtual void SAL_CALL setClipRegion( const css::uno::Reference< css::awt::XRegion >& Clipping ) override;
+ virtual void SAL_CALL intersectClipRegion( const css::uno::Reference< css::awt::XRegion >& xClipping ) override;
+ virtual void SAL_CALL push( ) override;
+ virtual void SAL_CALL pop( ) override;
+ virtual void SAL_CALL clear( const css::awt::Rectangle& aRect ) override;
+ virtual void SAL_CALL copy( const css::uno::Reference< css::awt::XDevice >& xSource, ::sal_Int32 nSourceX, ::sal_Int32 nSourceY, ::sal_Int32 nSourceWidth, ::sal_Int32 nSourceHeight, ::sal_Int32 nDestX, ::sal_Int32 nDestY, ::sal_Int32 nDestWidth, ::sal_Int32 nDestHeight ) override;
+ virtual void SAL_CALL draw( const css::uno::Reference< css::awt::XDisplayBitmap >& xBitmapHandle, ::sal_Int32 SourceX, ::sal_Int32 SourceY, ::sal_Int32 SourceWidth, ::sal_Int32 SourceHeight, ::sal_Int32 DestX, ::sal_Int32 DestY, ::sal_Int32 DestWidth, ::sal_Int32 DestHeight ) override;
+ virtual void SAL_CALL drawPixel( ::sal_Int32 X, ::sal_Int32 Y ) override;
+ virtual void SAL_CALL drawLine( ::sal_Int32 X1, ::sal_Int32 Y1, ::sal_Int32 X2, ::sal_Int32 Y2 ) override;
+ virtual void SAL_CALL drawRect( ::sal_Int32 X, ::sal_Int32 Y, ::sal_Int32 Width, ::sal_Int32 Height ) override;
+ virtual void SAL_CALL drawRoundedRect( ::sal_Int32 X, ::sal_Int32 Y, ::sal_Int32 Width, ::sal_Int32 Height, ::sal_Int32 nHorzRound, ::sal_Int32 nVertRound ) override;
+ virtual void SAL_CALL drawPolyLine( const css::uno::Sequence< ::sal_Int32 >& DataX, const css::uno::Sequence< ::sal_Int32 >& DataY ) override;
+ virtual void SAL_CALL drawPolygon( const css::uno::Sequence< ::sal_Int32 >& DataX, const css::uno::Sequence< ::sal_Int32 >& DataY ) override;
+ virtual void SAL_CALL drawPolyPolygon( const css::uno::Sequence< css::uno::Sequence< ::sal_Int32 > >& DataX, const css::uno::Sequence< css::uno::Sequence< ::sal_Int32 > >& DataY ) override;
+ virtual void SAL_CALL drawEllipse( ::sal_Int32 X, ::sal_Int32 Y, ::sal_Int32 Width, ::sal_Int32 Height ) override;
+ virtual void SAL_CALL 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 ) override;
+ virtual void SAL_CALL 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 ) override;
+ virtual void SAL_CALL drawChord( ::sal_Int32 nX, ::sal_Int32 nY, ::sal_Int32 nWidth, ::sal_Int32 nHeight, ::sal_Int32 nX1, ::sal_Int32 nY1, ::sal_Int32 nX2, ::sal_Int32 nY2 ) override;
+ virtual void SAL_CALL drawGradient( ::sal_Int32 nX, ::sal_Int32 nY, ::sal_Int32 nWidth, ::sal_Int32 Height, const css::awt::Gradient& aGradient ) override;
+ virtual void SAL_CALL drawText( ::sal_Int32 X, ::sal_Int32 Y, const OUString& Text ) override;
+ virtual void SAL_CALL drawTextArray( ::sal_Int32 X, ::sal_Int32 Y, const OUString& Text, const css::uno::Sequence< ::sal_Int32 >& Longs ) override;
+ virtual void SAL_CALL drawImage( ::sal_Int32 nX, ::sal_Int32 nY, ::sal_Int32 nWidth, ::sal_Int32 nHeight, ::sal_Int16 nStyle, const css::uno::Reference< css::graphic::XGraphic >& aGraphic ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/awt/vclxpointer.hxx b/toolkit/inc/awt/vclxpointer.hxx
new file mode 100644
index 0000000000..1030319269
--- /dev/null
+++ b/toolkit/inc/awt/vclxpointer.hxx
@@ -0,0 +1,58 @@
+/* -*- 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/awt/XPointer.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <comphelper/servicehelper.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <mutex>
+
+#include <vcl/ptrstyle.hxx>
+
+
+
+
+class VCLXPointer final : public cppu::WeakImplHelper<
+ css::awt::XPointer, css::lang::XServiceInfo>
+{
+ std::mutex maMutex;
+ PointerStyle maPointer;
+
+public:
+ VCLXPointer();
+ virtual ~VCLXPointer() override;
+
+ PointerStyle GetPointer() const { return maPointer; }
+
+ // css::awt::XPointer
+ void SAL_CALL setType( sal_Int32 nType ) override;
+ sal_Int32 SAL_CALL getType( ) override;
+
+ OUString SAL_CALL getImplementationName() override;
+
+ sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override;
+
+ css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/awt/vclxprinter.hxx b/toolkit/inc/awt/vclxprinter.hxx
new file mode 100644
index 0000000000..e5440f38aa
--- /dev/null
+++ b/toolkit/inc/awt/vclxprinter.hxx
@@ -0,0 +1,194 @@
+/* -*- 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/awt/XPrinterPropertySet.hpp>
+#include <com/sun/star/awt/XPrinterServer2.hpp>
+#include <com/sun/star/awt/XInfoPrinter.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <comphelper/broadcasthelper.hxx>
+#include <cppuhelper/propshlp.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/uno3.hxx>
+#include <vcl/vclptr.hxx>
+#include <vcl/jobset.hxx>
+
+#include <memory>
+
+namespace com::sun::star::awt { class XPrinter; }
+namespace vcl { class OldStylePrintAdaptor; }
+class Printer;
+
+// relevant properties for the printer:
+/*
+ sal_Bool Horizontal
+ sal_uInt16 CopyCount;
+ sal_Bool Collate;
+ String FormDescriptor;
+ sal_uInt16 Orientation; // PORTRAIT, LANDSCAPE
+*/
+
+
+
+
+typedef ::cppu::WeakImplHelper < css::awt::XPrinterPropertySet
+ > VCLXPrinterPropertySet_Base;
+class VCLXPrinterPropertySet :public VCLXPrinterPropertySet_Base
+ ,public comphelper::OMutexAndBroadcastHelper
+ ,public ::cppu::OPropertySetHelper
+{
+protected:
+ VclPtr<Printer> mxPrinter;
+ css::uno::Reference< css::awt::XDevice > mxPrnDevice;
+
+ sal_Int16 mnOrientation;
+ bool mbHorizontal;
+public:
+ VCLXPrinterPropertySet( const OUString& rPrinterName );
+ virtual ~VCLXPrinterPropertySet() override;
+
+ Printer* GetPrinter() const { return mxPrinter.get(); }
+ css::uno::Reference< css::awt::XDevice > const & GetDevice();
+
+ // css::uno::XInterface
+ DECLARE_XINTERFACE();
+
+ // css::lang::XTypeProvider
+ DECLARE_XTYPEPROVIDER();
+
+ // css::beans::XPropertySet
+ css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+ void SAL_CALL setPropertyValue( const OUString& rPropertyName, const css::uno::Any& aValue ) override { OPropertySetHelper::setPropertyValue( rPropertyName, aValue ); }
+ css::uno::Any SAL_CALL getPropertyValue( const OUString& rPropertyName ) override { return OPropertySetHelper::getPropertyValue( rPropertyName ); }
+ void SAL_CALL addPropertyChangeListener( const OUString& rPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& rxListener ) override { OPropertySetHelper::addPropertyChangeListener( rPropertyName, rxListener ); }
+ void SAL_CALL removePropertyChangeListener( const OUString& rPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& rxListener ) override { OPropertySetHelper::removePropertyChangeListener( rPropertyName, rxListener ); }
+ void SAL_CALL addVetoableChangeListener( const OUString& rPropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& rxListener ) override { OPropertySetHelper::addVetoableChangeListener( rPropertyName, rxListener ); }
+ void SAL_CALL removeVetoableChangeListener( const OUString& rPropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& rxListener ) override { OPropertySetHelper::removeVetoableChangeListener( rPropertyName, rxListener ); }
+
+ // ::cppu::OPropertySetHelper
+ ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+ sal_Bool SAL_CALL convertFastPropertyValue( css::uno::Any & rConvertedValue, css::uno::Any & rOldValue, sal_Int32 nHandle, const css::uno::Any& rValue ) override;
+ void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const css::uno::Any& rValue ) override;
+ using cppu::OPropertySetHelper::getFastPropertyValue;
+ void SAL_CALL getFastPropertyValue( css::uno::Any& rValue, sal_Int32 nHandle ) const override;
+
+ // css::awt::XPrinterPropertySet
+ void SAL_CALL setHorizontal( sal_Bool bHorizontal ) override;
+ css::uno::Sequence< OUString > SAL_CALL getFormDescriptions( ) override;
+ void SAL_CALL selectForm( const OUString& aFormDescription ) override;
+ css::uno::Sequence< sal_Int8 > SAL_CALL getBinarySetup( ) override;
+ void SAL_CALL setBinarySetup( const css::uno::Sequence< sal_Int8 >& data ) override;
+};
+
+
+
+
+typedef ::cppu::ImplInheritanceHelper < VCLXPrinterPropertySet
+ , css::awt::XPrinter
+ > VCLXPrinter_Base;
+class VCLXPrinter final : public VCLXPrinter_Base
+{
+ std::shared_ptr<vcl::OldStylePrintAdaptor> mxListener;
+ JobSetup maInitJobSetup;
+public:
+ VCLXPrinter( const OUString& rPrinterName );
+ virtual ~VCLXPrinter() override;
+
+ // css::beans::XPropertySet
+ css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override { return VCLXPrinterPropertySet::getPropertySetInfo(); }
+ void SAL_CALL setPropertyValue( const OUString& rPropertyName, const css::uno::Any& aValue ) override { VCLXPrinterPropertySet::setPropertyValue( rPropertyName, aValue ); }
+ css::uno::Any SAL_CALL getPropertyValue( const OUString& rPropertyName ) override { return VCLXPrinterPropertySet::getPropertyValue( rPropertyName ); }
+ void SAL_CALL addPropertyChangeListener( const OUString& rPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& rxListener ) override { VCLXPrinterPropertySet::addPropertyChangeListener( rPropertyName, rxListener ); }
+ void SAL_CALL removePropertyChangeListener( const OUString& rPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& rxListener ) override { VCLXPrinterPropertySet::removePropertyChangeListener( rPropertyName, rxListener ); }
+ void SAL_CALL addVetoableChangeListener( const OUString& rPropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& rxListener ) override { VCLXPrinterPropertySet::addVetoableChangeListener( rPropertyName, rxListener ); }
+ void SAL_CALL removeVetoableChangeListener( const OUString& rPropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& rxListener ) override { VCLXPrinterPropertySet::removeVetoableChangeListener( rPropertyName, rxListener ); }
+
+ // css::awt::XPrinterPropertySet
+ void SAL_CALL setHorizontal( sal_Bool bHorizontal ) override { VCLXPrinterPropertySet::setHorizontal( bHorizontal ); }
+ css::uno::Sequence< OUString > SAL_CALL getFormDescriptions( ) override { return VCLXPrinterPropertySet::getFormDescriptions(); }
+ void SAL_CALL selectForm( const OUString& aFormDescription ) override { VCLXPrinterPropertySet::selectForm( aFormDescription ); }
+ css::uno::Sequence< sal_Int8 > SAL_CALL getBinarySetup( ) override { return VCLXPrinterPropertySet::getBinarySetup(); }
+ void SAL_CALL setBinarySetup( const css::uno::Sequence< sal_Int8 >& data ) override { VCLXPrinterPropertySet::setBinarySetup( data ); }
+
+ // css::awt::XPrinter
+ sal_Bool SAL_CALL start( const OUString& nJobName, sal_Int16 nCopies, sal_Bool nCollate ) override;
+ void SAL_CALL end( ) override;
+ void SAL_CALL terminate( ) override;
+ css::uno::Reference< css::awt::XDevice > SAL_CALL startPage( ) override;
+ void SAL_CALL endPage( ) override;
+};
+
+
+
+
+typedef ::cppu::ImplInheritanceHelper < VCLXPrinterPropertySet
+ , css::awt::XInfoPrinter
+ > VCLXInfoPrinter_Base;
+class VCLXInfoPrinter final : public VCLXInfoPrinter_Base
+{
+public:
+ VCLXInfoPrinter( const OUString& rPrinterName );
+ virtual ~VCLXInfoPrinter() override;
+
+ // css::beans::XPropertySet
+ css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override { return VCLXPrinterPropertySet::getPropertySetInfo(); }
+ void SAL_CALL setPropertyValue( const OUString& rPropertyName, const css::uno::Any& aValue ) override { VCLXPrinterPropertySet::setPropertyValue( rPropertyName, aValue ); }
+ css::uno::Any SAL_CALL getPropertyValue( const OUString& rPropertyName ) override { return VCLXPrinterPropertySet::getPropertyValue( rPropertyName ); }
+ void SAL_CALL addPropertyChangeListener( const OUString& rPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& rxListener ) override { VCLXPrinterPropertySet::addPropertyChangeListener( rPropertyName, rxListener ); }
+ void SAL_CALL removePropertyChangeListener( const OUString& rPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& rxListener ) override { VCLXPrinterPropertySet::removePropertyChangeListener( rPropertyName, rxListener ); }
+ void SAL_CALL addVetoableChangeListener( const OUString& rPropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& rxListener ) override { VCLXPrinterPropertySet::addVetoableChangeListener( rPropertyName, rxListener ); }
+ void SAL_CALL removeVetoableChangeListener( const OUString& rPropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& rxListener ) override { VCLXPrinterPropertySet::removeVetoableChangeListener( rPropertyName, rxListener ); }
+
+ // css::awt::XPrinterPropertySet
+ void SAL_CALL setHorizontal( sal_Bool bHorizontal ) override { VCLXPrinterPropertySet::setHorizontal( bHorizontal ); }
+ css::uno::Sequence< OUString > SAL_CALL getFormDescriptions( ) override { return VCLXPrinterPropertySet::getFormDescriptions(); }
+ void SAL_CALL selectForm( const OUString& aFormDescription ) override { VCLXPrinterPropertySet::selectForm( aFormDescription ); }
+ css::uno::Sequence< sal_Int8 > SAL_CALL getBinarySetup( ) override { return VCLXPrinterPropertySet::getBinarySetup(); }
+ void SAL_CALL setBinarySetup( const css::uno::Sequence< sal_Int8 >& data ) override { VCLXPrinterPropertySet::setBinarySetup( data ); }
+
+ // css::awt::XInfoPrinter
+ css::uno::Reference< css::awt::XDevice > SAL_CALL createDevice( ) override;
+};
+
+
+
+
+typedef ::cppu::WeakImplHelper < css::awt::XPrinterServer2,
+ css::lang::XServiceInfo
+ > VCLXPrinterServer_Base;
+class VCLXPrinterServer final : public VCLXPrinterServer_Base
+{
+public:
+ // css::awt::XPrinterServer2
+ css::uno::Sequence< OUString > SAL_CALL getPrinterNames( ) override;
+ OUString SAL_CALL getDefaultPrinterName() override;
+ css::uno::Reference< css::awt::XPrinter > SAL_CALL createPrinter( const OUString& printerName ) override;
+ css::uno::Reference< css::awt::XInfoPrinter > SAL_CALL createInfoPrinter( const OUString& printerName ) override;
+
+ OUString SAL_CALL getImplementationName() override;
+
+ sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override;
+
+ css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/awt/vclxregion.hxx b/toolkit/inc/awt/vclxregion.hxx
new file mode 100644
index 0000000000..c0c64d37a6
--- /dev/null
+++ b/toolkit/inc/awt/vclxregion.hxx
@@ -0,0 +1,62 @@
+/* -*- 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/awt/XRegion.hpp>
+#include <comphelper/servicehelper.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <mutex>
+
+#include <vcl/region.hxx>
+
+
+
+
+class VCLXRegion final : public cppu::WeakImplHelper<
+ css::awt::XRegion>
+{
+ std::mutex maMutex;
+ vcl::Region maRegion;
+
+public:
+ VCLXRegion();
+ virtual ~VCLXRegion() override;
+
+ const vcl::Region& GetRegion() const { return maRegion; }
+
+ // css::awt::XRegion
+ css::awt::Rectangle SAL_CALL getBounds() override;
+ void SAL_CALL clear() override;
+ void SAL_CALL move( sal_Int32 nHorzMove, sal_Int32 nVertMove ) override;
+ void SAL_CALL unionRectangle( const css::awt::Rectangle& rRect ) override;
+ void SAL_CALL intersectRectangle( const css::awt::Rectangle& rRect ) override;
+ void SAL_CALL excludeRectangle( const css::awt::Rectangle& rRect ) override;
+ void SAL_CALL xOrRectangle( const css::awt::Rectangle& rRect ) override;
+ void SAL_CALL unionRegion( const css::uno::Reference< css::awt::XRegion >& rxRegion ) override;
+ void SAL_CALL intersectRegion( const css::uno::Reference< css::awt::XRegion >& rxRegion ) override;
+ void SAL_CALL excludeRegion( const css::uno::Reference< css::awt::XRegion >& rxRegion ) override;
+ void SAL_CALL xOrRegion( const css::uno::Reference< css::awt::XRegion >& rxRegion ) override;
+ css::uno::Sequence< css::awt::Rectangle > SAL_CALL getRectangles() override;
+
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/awt/vclxspinbutton.hxx b/toolkit/inc/awt/vclxspinbutton.hxx
new file mode 100644
index 0000000000..acd7a68984
--- /dev/null
+++ b/toolkit/inc/awt/vclxspinbutton.hxx
@@ -0,0 +1,88 @@
+/* -*- 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 <toolkit/awt/vclxwindow.hxx>
+#include <toolkit/helper/listenermultiplexer.hxx>
+#include <cppuhelper/implbase1.hxx>
+#include <comphelper/uno3.hxx>
+#include <com/sun/star/awt/XSpinValue.hpp>
+
+
+namespace toolkit
+{
+
+
+ //= VCLXSpinButton
+
+ typedef ::cppu::ImplHelper1 < css::awt::XSpinValue
+ > VCLXSpinButton_Base;
+
+ class VCLXSpinButton final : public VCLXWindow
+ ,public VCLXSpinButton_Base
+ {
+ private:
+ AdjustmentListenerMultiplexer maAdjustmentListeners;
+
+ public:
+ VCLXSpinButton();
+
+ private:
+ virtual ~VCLXSpinButton( ) override;
+
+ // XInterface
+ DECLARE_XINTERFACE()
+
+ // XTypeProvider
+ DECLARE_XTYPEPROVIDER()
+
+ // XComponent
+ void SAL_CALL dispose( ) 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 n ) 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;
+
+ // VclWindowPeer
+ virtual void SAL_CALL setProperty( const OUString& PropertyName, const css::uno::Any& Value ) override;
+ virtual css::uno::Any SAL_CALL getProperty( const OUString& PropertyName ) override;
+
+ // VCLXWindow
+ void ProcessWindowEvent( const VclWindowEvent& _rVclWindowEvent ) override;
+
+ VCLXSpinButton( const VCLXSpinButton& ) = delete;
+ VCLXSpinButton& operator=( const VCLXSpinButton& ) = delete;
+ };
+
+
+} // namespacetoolkit
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/awt/vclxsystemdependentwindow.hxx b/toolkit/inc/awt/vclxsystemdependentwindow.hxx
new file mode 100644
index 0000000000..69eba013c6
--- /dev/null
+++ b/toolkit/inc/awt/vclxsystemdependentwindow.hxx
@@ -0,0 +1,40 @@
+/* -*- 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/awt/XSystemDependentWindowPeer.hpp>
+#include <cppuhelper/implbase.hxx>
+
+#include <toolkit/awt/vclxwindow.hxx>
+
+class VCLXSystemDependentWindow final :
+ public cppu::ImplInheritanceHelper<VCLXWindow, css::awt::XSystemDependentWindowPeer>
+{
+public:
+ VCLXSystemDependentWindow();
+ virtual ~VCLXSystemDependentWindow() override;
+
+ // css::awt::XSystemDependentWindowPeer
+ css::uno::Any SAL_CALL getWindowHandle( const css::uno::Sequence< sal_Int8 >& ProcessId, sal_Int16 SystemType ) override;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/awt/vclxtabpagecontainer.hxx b/toolkit/inc/awt/vclxtabpagecontainer.hxx
new file mode 100644
index 0000000000..e300e03aff
--- /dev/null
+++ b/toolkit/inc/awt/vclxtabpagecontainer.hxx
@@ -0,0 +1,73 @@
+/* -*- 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/container/XContainerListener.hpp>
+#include <com/sun/star/beans/XPropertiesChangeListener.hpp>
+#include <com/sun/star/awt/tab/XTabPageContainer.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <toolkit/helper/listenermultiplexer.hxx>
+#include <awt/vclxcontainer.hxx>
+
+
+typedef cppu::ImplInheritanceHelper< VCLXContainer,
+ css::awt::tab::XTabPageContainer,
+ css::beans::XPropertiesChangeListener,
+ css::container::XContainerListener
+ > VCLXTabPageContainer_Base;
+class VCLXTabPageContainer final : public VCLXTabPageContainer_Base
+{
+public:
+ VCLXTabPageContainer();
+ virtual ~VCLXTabPageContainer() override;
+
+ // css::awt::XView
+ void SAL_CALL draw( sal_Int32 nX, sal_Int32 nY ) override;
+
+ // css::awt::grid::XTabPageContainer
+ virtual ::sal_Int16 SAL_CALL getActiveTabPageID() override;
+ virtual void SAL_CALL setActiveTabPageID( ::sal_Int16 _activetabpageid ) override;
+ virtual ::sal_Int16 SAL_CALL getTabPageCount( ) override;
+ virtual sal_Bool SAL_CALL isTabPageActive( ::sal_Int16 tabPageIndex ) override;
+ virtual css::uno::Reference< css::awt::tab::XTabPage > SAL_CALL getTabPage( ::sal_Int16 tabPageIndex ) override;
+ virtual css::uno::Reference< css::awt::tab::XTabPage > SAL_CALL getTabPageByID( ::sal_Int16 tabPageID ) override;
+ virtual void SAL_CALL addTabPageContainerListener( const css::uno::Reference< css::awt::tab::XTabPageContainerListener >& listener ) override;
+ virtual void SAL_CALL removeTabPageContainerListener( const css::uno::Reference< css::awt::tab::XTabPageContainerListener >& listener ) override;
+
+ virtual void GetPropertyIds( std::vector< sal_uInt16 > &aIds ) override;
+
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+ 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;
+
+ // css::beans::XPropertiesChangeListener
+ virtual void SAL_CALL propertiesChange( const ::css::uno::Sequence< ::css::beans::PropertyChangeEvent >& aEvent ) override;
+
+ // css::awt::XVclWindowPeer
+ void SAL_CALL setProperty( const OUString& PropertyName, const css::uno::Any& Value ) override;
+private:
+ virtual void ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) override;
+
+ TabPageListenerMultiplexer m_aTabPageListeners;
+ ::std::vector< css::uno::Reference< css::awt::tab::XTabPage > > m_aTabPages;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/awt/vclxtopwindow.hxx b/toolkit/inc/awt/vclxtopwindow.hxx
new file mode 100644
index 0000000000..1913c4594f
--- /dev/null
+++ b/toolkit/inc/awt/vclxtopwindow.hxx
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef INCLUDED_TOOLKIT_AWT_VCLXTOPWINDOW_HXX
+#define INCLUDED_TOOLKIT_AWT_VCLXTOPWINDOW_HXX
+
+#include <com/sun/star/awt/XSystemDependentWindowPeer.hpp>
+#include <com/sun/star/awt/XTopWindow2.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+#include <awt/vclxcontainer.hxx>
+
+namespace com::sun::star::awt { class XMenuBar; }
+
+
+class VCLXTopWindow: public cppu::ImplInheritanceHelper<
+ VCLXContainer, css::awt::XTopWindow2, css::awt::XSystemDependentWindowPeer >
+{
+public:
+ VCLXTopWindow();
+ virtual ~VCLXTopWindow() override;
+
+ // css::awt::XSystemDependentWindowPeer
+ css::uno::Any SAL_CALL getWindowHandle( const css::uno::Sequence< sal_Int8 >& ProcessId, sal_Int16 SystemType ) override;
+
+ // css::awt::XTopWindow
+ void SAL_CALL addTopWindowListener( const css::uno::Reference< css::awt::XTopWindowListener >& rxListener ) override;
+ void SAL_CALL removeTopWindowListener( const css::uno::Reference< css::awt::XTopWindowListener >& rxListener ) override;
+ void SAL_CALL toFront() override;
+ void SAL_CALL toBack() override;
+ void SAL_CALL setMenuBar( const css::uno::Reference< css::awt::XMenuBar >& xMenu ) override;
+
+ // XTopWindow2
+ virtual sal_Bool SAL_CALL getIsMaximized() override;
+ virtual void SAL_CALL setIsMaximized( sal_Bool _ismaximized ) override;
+ virtual sal_Bool SAL_CALL getIsMinimized() override;
+ virtual void SAL_CALL setIsMinimized( sal_Bool _isminimized ) override;
+ virtual ::sal_Int32 SAL_CALL getDisplay() override;
+ virtual void SAL_CALL setDisplay( ::sal_Int32 _display ) override;
+
+ static void ImplGetPropertyIds( std::vector< sal_uInt16 > &aIds );
+ virtual void GetPropertyIds( std::vector< sal_uInt16 > &aIds ) override { return ImplGetPropertyIds( aIds ); }
+};
+
+
+#endif // INCLUDED_TOOLKIT_AWT_VCLXTOPWINDOW_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/awt/vclxwindows.hxx b/toolkit/inc/awt/vclxwindows.hxx
new file mode 100644
index 0000000000..22367ddcc0
--- /dev/null
+++ b/toolkit/inc/awt/vclxwindows.hxx
@@ -0,0 +1,605 @@
+/* -*- 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/awt/XCurrencyField.hpp>
+#include <com/sun/star/awt/XDateField.hpp>
+#include <com/sun/star/awt/XDialog2.hpp>
+#include <com/sun/star/awt/XMessageBox.hpp>
+#include <com/sun/star/awt/XMetricField.hpp>
+#include <com/sun/star/awt/XNumericField.hpp>
+#include <com/sun/star/awt/XPatternField.hpp>
+#include <com/sun/star/awt/XProgressBar.hpp>
+#include <com/sun/star/awt/XSimpleTabController.hpp>
+#include <com/sun/star/awt/XTimeField.hpp>
+#include <com/sun/star/awt/grid/XGridControl.hpp>
+#include <com/sun/star/awt/grid/XGridRowSelection.hpp>
+#include <com/sun/star/awt/grid/XGridDataListener.hpp>
+#include <com/sun/star/awt/grid/GridDataEvent.hpp>
+#include <com/sun/star/awt/grid/XGridSelectionListener.hpp>
+#include <com/sun/star/container/XContainerListener.hpp>
+#include <com/sun/star/util/Time.hpp>
+#include <com/sun/star/util/Date.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+#include <awt/vclxtopwindow.hxx>
+#include <toolkit/awt/vclxwindows.hxx>
+
+class FormatterBase;
+class TabControl;
+class TabPage;
+class Edit;
+
+// class VCLXImageControl
+class VCLXImageControl final : public VCLXGraphicControl
+{
+public:
+ VCLXImageControl();
+ virtual ~VCLXImageControl() override;
+
+ // css::awt::XLayoutConstrains
+ css::awt::Size SAL_CALL getMinimumSize( ) override;
+ css::awt::Size SAL_CALL getPreferredSize( ) override;
+ css::awt::Size SAL_CALL calcAdjustedSize( const css::awt::Size& rNewSize ) override;
+
+ // css::awt::VclWindowPeer
+ void SAL_CALL setProperty( const OUString& PropertyName, const css::uno::Any& Value ) override;
+ css::uno::Any SAL_CALL getProperty( const OUString& PropertyName ) override;
+
+ static void ImplGetPropertyIds( std::vector< sal_uInt16 > &aIds );
+ virtual void GetPropertyIds( std::vector< sal_uInt16 > &aIds ) override { return ImplGetPropertyIds( aIds ); }
+
+private:
+ virtual void ImplSetNewImage() override;
+};
+
+// class VCLXMessageBox
+class VCLXMessageBox final :
+ public cppu::ImplInheritanceHelper<VCLXTopWindow, css::awt::XMessageBox>
+{
+public:
+ VCLXMessageBox();
+ virtual ~VCLXMessageBox() override;
+
+
+ // css::awt::XMessageBox
+ void SAL_CALL setCaptionText( const OUString& aText ) override;
+ OUString SAL_CALL getCaptionText( ) override;
+ void SAL_CALL setMessageText( const OUString& aText ) override;
+ OUString SAL_CALL getMessageText( ) override;
+ sal_Int16 SAL_CALL execute( ) override;
+
+ // css::awt::XLayoutConstrains
+ css::awt::Size SAL_CALL getMinimumSize() override;
+
+ virtual void GetPropertyIds( std::vector< sal_uInt16 > &aIds ) override;
+};
+
+// class VCLXFrame
+class VCLXFrame final : public VCLXContainer
+{
+ void ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) override;
+
+public:
+ VCLXFrame();
+ virtual ~VCLXFrame() override;
+
+ // css::awt::XView
+ void SAL_CALL draw( sal_Int32 nX, sal_Int32 nY ) override;
+
+ // css::awt::XVclWindowPeer
+ void SAL_CALL setProperty( const OUString& PropertyName, const css::uno::Any& Value ) override;
+
+ static void ImplGetPropertyIds( std::vector< sal_uInt16 > &aIds );
+ virtual void GetPropertyIds( std::vector< sal_uInt16 > &aIds ) override { return ImplGetPropertyIds( aIds ); }
+};
+
+// class VCLXDialog
+class VCLXDialog final : public cppu::ImplInheritanceHelper<VCLXTopWindow, css::awt::XDialog2>
+{
+public:
+ VCLXDialog();
+ virtual ~VCLXDialog() override;
+
+ // css::awt::XDialog2
+ virtual void SAL_CALL endDialog( ::sal_Int32 Result ) override;
+ virtual void SAL_CALL setHelpId( const OUString& Id ) override;
+
+ // css::awt::XDialog
+ void SAL_CALL setTitle( const OUString& Title ) override;
+ OUString SAL_CALL getTitle( ) override;
+ sal_Int16 SAL_CALL execute( ) override;
+ void SAL_CALL endExecute( ) override;
+
+ // css::awt::XView
+ void SAL_CALL draw( sal_Int32 nX, sal_Int32 nY ) override;
+
+ // css::awt::XDevice,
+ css::awt::DeviceInfo SAL_CALL getInfo() override;
+
+ virtual void GetPropertyIds( std::vector< sal_uInt16 > &aIds ) override;
+
+ // css::awt::XVclWindowPeer
+ void SAL_CALL setProperty( const OUString& PropertyName, const css::uno::Any& Value ) override;
+
+};
+
+// class VCLXTabPage
+class VCLXTabPage final : public VCLXContainer
+{
+public:
+ VCLXTabPage();
+ virtual ~VCLXTabPage() override;
+
+ // css::awt::XView
+ void SAL_CALL draw( sal_Int32 nX, sal_Int32 nY ) override;
+
+ // css::awt::XVclWindowPeer
+ void SAL_CALL setProperty( const OUString& PropertyName, const css::uno::Any& Value ) override;
+
+ /// @throws css::uno::RuntimeException
+ TabPage* getTabPage() const;
+ static void ImplGetPropertyIds( std::vector< sal_uInt16 > &aIds );
+ virtual void GetPropertyIds( std::vector< sal_uInt16 > &aIds ) override { return ImplGetPropertyIds( aIds ); }
+};
+
+class VCLXMultiPage final :
+ public cppu::ImplInheritanceHelper<VCLXContainer, css::awt::XSimpleTabController>
+{
+ TabListenerMultiplexer maTabListeners;
+ sal_Int32 mTabId;
+
+ void ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) override;
+public:
+ VCLXMultiPage();
+ virtual ~VCLXMultiPage() override;
+
+ // css::lang::XComponent
+ void SAL_CALL dispose( ) override;
+
+ // css::awt::XView
+ void SAL_CALL draw( sal_Int32 nX, sal_Int32 nY ) override;
+
+ // 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;
+ // XSimpleTabController
+ virtual ::sal_Int32 SAL_CALL insertTab() override;
+ virtual void SAL_CALL removeTab( ::sal_Int32 ID ) override;
+
+ virtual void SAL_CALL setTabProps( ::sal_Int32 ID, const css::uno::Sequence< css::beans::NamedValue >& Properties ) override;
+ virtual css::uno::Sequence< css::beans::NamedValue > SAL_CALL getTabProps( ::sal_Int32 ID ) override;
+
+ virtual void SAL_CALL activateTab( ::sal_Int32 ID ) override;
+ virtual ::sal_Int32 SAL_CALL getActiveTabID() override;
+
+ virtual void SAL_CALL addTabListener( const css::uno::Reference< css::awt::XTabListener >& Listener ) override;
+ virtual void SAL_CALL removeTabListener( const css::uno::Reference< css::awt::XTabListener >& Listener ) override;
+ // C++
+ /// @throws css::uno::RuntimeException
+ TabControl* getTabControl() const;
+ sal_uInt16 insertTab( TabPage*, OUString const & sTitle );
+ static void ImplGetPropertyIds( std::vector< sal_uInt16 > &aIds );
+ virtual void GetPropertyIds( std::vector< sal_uInt16 > &aIds ) override { return ImplGetPropertyIds( aIds ); }
+};
+
+// class VCLXProgressBar
+class VCLXProgressBar final : public cppu::ImplInheritanceHelper<VCLXWindow, css::awt::XProgressBar>
+{
+private:
+ sal_Int32 m_nValue;
+ sal_Int32 m_nValueMin;
+ sal_Int32 m_nValueMax;
+
+ void ImplUpdateValue();
+
+public:
+ VCLXProgressBar();
+ virtual ~VCLXProgressBar() override;
+
+ // css::awt::XProgressBar
+ void SAL_CALL setForegroundColor( sal_Int32 nColor ) override;
+ void SAL_CALL setBackgroundColor( sal_Int32 nColor ) override;
+ void SAL_CALL setValue( sal_Int32 nValue ) override;
+ void SAL_CALL setRange( sal_Int32 nMin, sal_Int32 nMax ) override;
+ sal_Int32 SAL_CALL getValue() override;
+
+ // css::awt::VclWindowPeer
+ void SAL_CALL setProperty( const OUString& PropertyName, const css::uno::Any& Value ) override;
+ css::uno::Any SAL_CALL getProperty( const OUString& PropertyName ) override;
+
+ static void ImplGetPropertyIds( std::vector< sal_uInt16 > &aIds );
+ virtual void GetPropertyIds( std::vector< sal_uInt16 > &aIds ) override { return ImplGetPropertyIds( aIds ); }
+};
+
+
+// class VCLXFormattedSpinField
+class VCLXFormattedSpinField : public VCLXSpinField
+{
+private:
+ FormatterBase* mpFormatter;
+
+protected:
+ FormatterBase* GetFormatter() const { return GetWindow() ? mpFormatter : nullptr; }
+
+public:
+ VCLXFormattedSpinField();
+ virtual ~VCLXFormattedSpinField() override;
+
+ void SetFormatter( FormatterBase* pFormatter ) { mpFormatter = pFormatter; }
+
+ void setStrictFormat( bool bStrict );
+ bool isStrictFormat() const;
+
+ // css::awt::VclWindowPeer
+ void SAL_CALL setProperty( const OUString& PropertyName, const css::uno::Any& Value ) override;
+ css::uno::Any SAL_CALL getProperty( const OUString& PropertyName ) override;
+
+ static void ImplGetPropertyIds( std::vector< sal_uInt16 > &aIds );
+ virtual void GetPropertyIds( std::vector< sal_uInt16 > &aIds ) override { return ImplGetPropertyIds( aIds ); }
+};
+
+
+// class VCLXDateField
+
+class VCLXDateField :
+ public cppu::ImplInheritanceHelper<VCLXFormattedSpinField, css::awt::XDateField>
+{
+protected:
+ virtual css::uno::Reference< css::accessibility::XAccessibleContext > CreateAccessibleContext() override;
+public:
+ VCLXDateField();
+ virtual ~VCLXDateField() override;
+
+
+ // css::awt::XDateField
+ void SAL_CALL setDate( const css::util::Date& Date ) override;
+ css::util::Date SAL_CALL getDate( ) override;
+ void SAL_CALL setMin( const css::util::Date& Date ) override;
+ css::util::Date SAL_CALL getMin( ) override;
+ void SAL_CALL setMax( const css::util::Date& Date ) override;
+ css::util::Date SAL_CALL getMax( ) override;
+ void SAL_CALL setFirst( const css::util::Date& Date ) override;
+ css::util::Date SAL_CALL getFirst( ) override;
+ void SAL_CALL setLast( const css::util::Date& Date ) override;
+ css::util::Date SAL_CALL getLast( ) override;
+ void SAL_CALL setLongFormat( sal_Bool bLong ) override;
+ sal_Bool SAL_CALL isLongFormat( ) override;
+ void SAL_CALL setEmpty( ) override;
+ sal_Bool SAL_CALL isEmpty( ) override;
+ void SAL_CALL setStrictFormat( sal_Bool bStrict ) override;
+ sal_Bool SAL_CALL isStrictFormat( ) override;
+
+ // css::awt::VclWindowPeer
+ void SAL_CALL setProperty( const OUString& PropertyName, const css::uno::Any& Value ) override;
+ css::uno::Any SAL_CALL getProperty( const OUString& PropertyName ) override;
+
+ static void ImplGetPropertyIds( std::vector< sal_uInt16 > &aIds );
+ virtual void GetPropertyIds( std::vector< sal_uInt16 > &aIds ) override { return ImplGetPropertyIds( aIds ); }
+};
+
+
+// class VCLXTimeField
+
+class VCLXTimeField final :
+ public cppu::ImplInheritanceHelper<VCLXFormattedSpinField, css::awt::XTimeField>
+{
+ virtual css::uno::Reference< css::accessibility::XAccessibleContext > CreateAccessibleContext() override;
+public:
+ VCLXTimeField();
+ virtual ~VCLXTimeField() override;
+
+ // css::awt::XTimeField
+ void SAL_CALL setTime( const css::util::Time& Time ) override;
+ css::util::Time SAL_CALL getTime( ) override;
+ void SAL_CALL setMin( const css::util::Time& Time ) override;
+ css::util::Time SAL_CALL getMin( ) override;
+ void SAL_CALL setMax( const css::util::Time& Time ) override;
+ css::util::Time SAL_CALL getMax( ) override;
+ void SAL_CALL setFirst( const css::util::Time& Time ) override;
+ css::util::Time SAL_CALL getFirst( ) override;
+ void SAL_CALL setLast( const css::util::Time& Time ) override;
+ css::util::Time SAL_CALL getLast( ) override;
+ void SAL_CALL setEmpty( ) override;
+ sal_Bool SAL_CALL isEmpty( ) override;
+ void SAL_CALL setStrictFormat( sal_Bool bStrict ) override;
+ sal_Bool SAL_CALL isStrictFormat( ) override;
+
+ // css::awt::VclWindowPeer
+ void SAL_CALL setProperty( const OUString& PropertyName, const css::uno::Any& Value ) override;
+ css::uno::Any SAL_CALL getProperty( const OUString& PropertyName ) override;
+
+ static void ImplGetPropertyIds( std::vector< sal_uInt16 > &aIds );
+ virtual void GetPropertyIds( std::vector< sal_uInt16 > &aIds ) override { return ImplGetPropertyIds( aIds ); }
+};
+
+
+// class VCLXNumericField
+
+class VCLXNumericField final :
+ public cppu::ImplInheritanceHelper<VCLXFormattedSpinField, css::awt::XNumericField>
+{
+public:
+ VCLXNumericField();
+ virtual ~VCLXNumericField() override;
+
+ // css::awt::XNumericField
+ void SAL_CALL setValue( double Value ) override;
+ double SAL_CALL getValue( ) override;
+ void SAL_CALL setMin( double Value ) override;
+ double SAL_CALL getMin( ) override;
+ void SAL_CALL setMax( double Value ) override;
+ double SAL_CALL getMax( ) override;
+ void SAL_CALL setFirst( double Value ) override;
+ double SAL_CALL getFirst( ) override;
+ void SAL_CALL setLast( double Value ) override;
+ double SAL_CALL getLast( ) override;
+ void SAL_CALL setSpinSize( double Value ) override;
+ double SAL_CALL getSpinSize( ) override;
+ void SAL_CALL setDecimalDigits( sal_Int16 nDigits ) override;
+ sal_Int16 SAL_CALL getDecimalDigits( ) override;
+ void SAL_CALL setStrictFormat( sal_Bool bStrict ) override;
+ sal_Bool SAL_CALL isStrictFormat( ) override;
+
+ // css::awt::VclWindowPeer
+ void SAL_CALL setProperty( const OUString& PropertyName, const css::uno::Any& Value ) override;
+ css::uno::Any SAL_CALL getProperty( const OUString& PropertyName ) override;
+
+ static void ImplGetPropertyIds( std::vector< sal_uInt16 > &aIds );
+ virtual void GetPropertyIds( std::vector< sal_uInt16 > &aIds ) override { return ImplGetPropertyIds( aIds ); }
+};
+
+
+// class VCLXMetricField
+
+class MetricFormatter;
+class MetricField;
+class VCLXMetricField final :
+ public cppu::ImplInheritanceHelper<VCLXFormattedSpinField, css::awt::XMetricField>
+{
+ /// @throws css::uno::RuntimeException
+ MetricFormatter *GetMetricFormatter();
+ /// @throws css::uno::RuntimeException
+ MetricField *GetMetricField();
+ void CallListeners();
+public:
+ VCLXMetricField();
+ virtual ~VCLXMetricField() override;
+
+ // css::awt::XMetricField
+ virtual void SAL_CALL setValue( ::sal_Int64 Value, ::sal_Int16 Unit ) override;
+ virtual void SAL_CALL setUserValue( ::sal_Int64 Value, ::sal_Int16 Unit ) override;
+ virtual ::sal_Int64 SAL_CALL getValue( ::sal_Int16 Unit ) override;
+ virtual ::sal_Int64 SAL_CALL getCorrectedValue( ::sal_Int16 Unit ) override;
+ virtual void SAL_CALL setMin( ::sal_Int64 Value, ::sal_Int16 Unit ) override;
+ virtual ::sal_Int64 SAL_CALL getMin( ::sal_Int16 Unit ) override;
+ virtual void SAL_CALL setMax( ::sal_Int64 Value, ::sal_Int16 Unit ) override;
+ virtual ::sal_Int64 SAL_CALL getMax( ::sal_Int16 Unit ) override;
+ virtual void SAL_CALL setFirst( ::sal_Int64 Value, ::sal_Int16 Unit ) override;
+ virtual ::sal_Int64 SAL_CALL getFirst( ::sal_Int16 Unit ) override;
+ virtual void SAL_CALL setLast( ::sal_Int64 Value, ::sal_Int16 Unit ) override;
+ virtual ::sal_Int64 SAL_CALL getLast( ::sal_Int16 Unit ) override;
+ virtual void SAL_CALL setSpinSize( ::sal_Int64 Value ) override;
+ virtual ::sal_Int64 SAL_CALL getSpinSize( ) override;
+ virtual void SAL_CALL setDecimalDigits( ::sal_Int16 nDigits ) override;
+ virtual ::sal_Int16 SAL_CALL getDecimalDigits( ) override;
+ virtual void SAL_CALL setStrictFormat( sal_Bool bStrict ) override;
+ virtual sal_Bool SAL_CALL isStrictFormat( ) override;
+
+ // css::awt::VclWindowPeer
+ void SAL_CALL setProperty( const OUString& PropertyName, const css::uno::Any& Value ) override;
+ css::uno::Any SAL_CALL getProperty( const OUString& PropertyName ) override;
+
+ static void ImplGetPropertyIds( std::vector< sal_uInt16 > &aIds );
+ virtual void GetPropertyIds( std::vector< sal_uInt16 > &aIds ) override { return ImplGetPropertyIds( aIds ); }
+};
+
+// class VCLXPatternField
+class VCLXPatternField final :
+ public cppu::ImplInheritanceHelper<VCLXFormattedSpinField, css::awt::XPatternField>
+{
+public:
+ VCLXPatternField();
+ virtual ~VCLXPatternField() override;
+
+
+ // css::awt::XPatternField
+ void SAL_CALL setMasks( const OUString& EditMask, const OUString& LiteralMask ) override;
+ void SAL_CALL getMasks( OUString& EditMask, OUString& LiteralMask ) override;
+ void SAL_CALL setString( const OUString& Str ) override;
+ OUString SAL_CALL getString( ) override;
+ void SAL_CALL setStrictFormat( sal_Bool bStrict ) override;
+ sal_Bool SAL_CALL isStrictFormat( ) override;
+
+ // css::awt::VclWindowPeer
+ void SAL_CALL setProperty( const OUString& PropertyName, const css::uno::Any& Value ) override;
+ css::uno::Any SAL_CALL getProperty( const OUString& PropertyName ) override;
+
+ static void ImplGetPropertyIds( std::vector< sal_uInt16 > &aIds );
+ virtual void GetPropertyIds( std::vector< sal_uInt16 > &aIds ) override { return ImplGetPropertyIds( aIds ); }
+};
+
+
+class VCLXFileControl final : public cppu::ImplInheritanceHelper<VCLXWindow, css::awt::XTextComponent, css::awt::XTextLayoutConstrains>
+{
+ DECL_LINK(ModifyHdl, Edit&, void);
+ void ModifyHdl();
+ TextListenerMultiplexer maTextListeners;
+
+public:
+ VCLXFileControl();
+ virtual ~VCLXFileControl() override;
+
+ virtual void SetWindow( const VclPtr< vcl::Window > &pWindow ) override;
+
+ // css::awt::XTextComponent
+ void SAL_CALL addTextListener( const css::uno::Reference< css::awt::XTextListener >& l ) override;
+ void SAL_CALL removeTextListener( const css::uno::Reference< css::awt::XTextListener >& l ) override;
+ void SAL_CALL setText( const OUString& aText ) override;
+ void SAL_CALL insertText( const css::awt::Selection& Sel, const OUString& Text ) override;
+ OUString SAL_CALL getText( ) override;
+ OUString SAL_CALL getSelectedText( ) override;
+ void SAL_CALL setSelection( const css::awt::Selection& aSelection ) override;
+ css::awt::Selection SAL_CALL getSelection( ) override;
+ sal_Bool SAL_CALL isEditable( ) override;
+ void SAL_CALL setEditable( sal_Bool bEditable ) override;
+ void SAL_CALL setMaxTextLen( sal_Int16 nLen ) override;
+ sal_Int16 SAL_CALL getMaxTextLen( ) override;
+
+ // css::awt::XLayoutConstrains
+ css::awt::Size SAL_CALL getMinimumSize( ) override;
+ css::awt::Size SAL_CALL getPreferredSize( ) override;
+ css::awt::Size SAL_CALL calcAdjustedSize( const css::awt::Size& aNewSize ) override;
+
+ // css::awt::XTextLayoutConstrains
+ css::awt::Size SAL_CALL getMinimumSize( sal_Int16 nCols, sal_Int16 nLines ) override;
+ void SAL_CALL getColumnsAndLines( sal_Int16& nCols, sal_Int16& nLines ) override;
+
+ void SAL_CALL setProperty( const OUString& PropertyName, const css::uno::Any& Value) override;
+
+ static void ImplGetPropertyIds( std::vector< sal_uInt16 > &aIds );
+ virtual void GetPropertyIds( std::vector< sal_uInt16 > &aIds ) override { return ImplGetPropertyIds( aIds ); }
+};
+
+class SVTXCurrencyField final :
+ public cppu::ImplInheritanceHelper<SVTXFormattedField, css::awt::XCurrencyField>
+{
+public:
+ SVTXCurrencyField();
+ virtual ~SVTXCurrencyField() override;
+
+ // 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;
+
+ // css::awt::XCurrencyField
+ void SAL_CALL setValue( double Value ) override;
+ double SAL_CALL getValue( ) override;
+ void SAL_CALL setMin( double Value ) override;
+ double SAL_CALL getMin( ) override;
+ void SAL_CALL setMax( double Value ) override;
+ double SAL_CALL getMax( ) override;
+ void SAL_CALL setFirst( double Value ) override;
+ double SAL_CALL getFirst( ) override;
+ void SAL_CALL setLast( double Value ) override;
+ double SAL_CALL getLast( ) override;
+ void SAL_CALL setSpinSize( double Value ) override;
+ double SAL_CALL getSpinSize( ) override;
+ void SAL_CALL setDecimalDigits( sal_Int16 nDigits ) override;
+ sal_Int16 SAL_CALL getDecimalDigits( ) override;
+ void SAL_CALL setStrictFormat( sal_Bool bStrict ) override;
+ sal_Bool SAL_CALL isStrictFormat( ) override;
+
+ static void ImplGetPropertyIds( std::vector< sal_uInt16 > &aIds );
+ virtual void GetPropertyIds( std::vector< sal_uInt16 > &aIds ) override { return ImplGetPropertyIds( aIds ); }
+};
+
+
+class SVTXDateField final : public VCLXDateField
+{
+public:
+ SVTXDateField();
+ virtual ~SVTXDateField() override;
+
+ // css::awt::VclWindowPeer
+ void SAL_CALL setProperty( const OUString& PropertyName, const css::uno::Any& Value ) override;
+
+ static void ImplGetPropertyIds( std::vector< sal_uInt16 > &aIds );
+ virtual void GetPropertyIds( std::vector< sal_uInt16 > &aIds ) override { return ImplGetPropertyIds( aIds ); }
+};
+
+namespace svt::table {
+ class TableControl;
+ class UnoControlTableModel;
+}
+
+typedef ::cppu::ImplInheritanceHelper < VCLXWindow
+ , css::awt::grid::XGridControl
+ , css::awt::grid::XGridRowSelection
+ , css::awt::grid::XGridDataListener
+ , css::container::XContainerListener
+ > SVTXGridControl_Base;
+class SVTXGridControl final : public SVTXGridControl_Base
+{
+public:
+ SVTXGridControl();
+ virtual ~SVTXGridControl() 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& Source ) override;
+
+ // XGridControl
+ virtual ::sal_Int32 SAL_CALL getRowAtPoint(::sal_Int32 x, ::sal_Int32 y) override;
+ virtual ::sal_Int32 SAL_CALL getColumnAtPoint(::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;
+
+ // 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;
+
+ void SAL_CALL setProperty( const OUString& PropertyName, const css::uno::Any& Value ) override;
+ css::uno::Any SAL_CALL getProperty( const OUString& PropertyName ) override;
+
+ // css::lang::XComponent
+ void SAL_CALL dispose( ) override;
+
+ // XWindow
+ void SAL_CALL setEnable( sal_Bool bEnable ) override;
+
+private:
+ // VCLXWindow
+ virtual void SetWindow( const VclPtr< vcl::Window > &pWindow ) override;
+
+ void impl_updateColumnsFromModel_nothrow();
+ void impl_checkTableModelInit();
+
+ void impl_checkColumnIndex_throw( ::svt::table::TableControl const & i_table, sal_Int32 const i_columnIndex ) const;
+ void impl_checkRowIndex_throw( ::svt::table::TableControl const & i_table, sal_Int32 const i_rowIndex ) const;
+
+ virtual void ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) override;
+ void ImplCallItemListeners();
+
+ std::shared_ptr< ::svt::table::UnoControlTableModel > m_xTableModel;
+ bool m_bTableModelInitCompleted;
+ SelectionListenerMultiplexer m_aSelectionListeners;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/accessiblecontrolcontext.hxx b/toolkit/inc/controls/accessiblecontrolcontext.hxx
new file mode 100644
index 0000000000..416984c334
--- /dev/null
+++ b/toolkit/inc/controls/accessiblecontrolcontext.hxx
@@ -0,0 +1,116 @@
+/* -*- 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 <comphelper/accessiblecomponenthelper.hxx>
+#include <com/sun/star/lang/XEventListener.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <rtl/ref.hxx>
+
+namespace vcl { class Window; }
+namespace com::sun::star::awt { class XWindow; }
+namespace com::sun::star::beans { class XPropertySet; }
+namespace com::sun::star::beans { class XPropertySetInfo; }
+
+namespace toolkit
+{
+
+
+ //= OAccessibleControlContext
+
+
+ typedef ::comphelper::OAccessibleComponentHelper OAccessibleControlContext_Base;
+
+ /** class implementing the AccessibleContext for a UNO control - to be used in design mode of the control.
+ <p><b>life time control<b/><br/>
+ This control should be held weak by the creator (a UNO control), it itself holds a hard reference to the
+ control model, and a weak reference to the control. The reference to the model is freed when the model
+ is being disposed.</p>
+ */
+ class OAccessibleControlContext final
+ :public cppu::ImplInheritanceHelper<
+ OAccessibleControlContext_Base, css::lang::XEventListener>
+ {
+ public:
+ /** creates an accessible context for a uno control
+ @param _rxCreator
+ the uno control's XAccessible interface. This must be an XControl, from which an XControlModel
+ can be retrieved.
+ */
+ static rtl::Reference<OAccessibleControlContext> create(
+ const css::uno::Reference< css::accessibility::XAccessible >& _rxCreator
+ );
+
+ private:
+
+ // XAccessibleContext
+ virtual sal_Int64 SAL_CALL getAccessibleChildCount( ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int64 i ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleParent( ) override;
+ virtual sal_Int16 SAL_CALL getAccessibleRole( ) override;
+ virtual OUString SAL_CALL getAccessibleDescription( ) override;
+ virtual OUString SAL_CALL getAccessibleName( ) override;
+ virtual css::uno::Reference< css::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet( ) override;
+ virtual sal_Int64 SAL_CALL getAccessibleStateSet( ) override;
+
+ // XAccessibleComponent
+ virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const css::awt::Point& aPoint ) override;
+ virtual void SAL_CALL grabFocus( ) override;
+ virtual sal_Int32 SAL_CALL getForeground( ) override;
+ virtual sal_Int32 SAL_CALL getBackground( ) override;
+
+ // XEventListener
+ using comphelper::OCommonAccessibleComponent::disposing;
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ // retrieves the value of a string property from the model, if the property is present
+ OUString getModelStringProperty( const char* _pPropertyName );
+
+ // starts listening at the control model (currently for disposal only)
+ void startModelListening( );
+ // stops listening at the control model
+ void stopModelListening( );
+
+ vcl::Window* implGetWindow( css::uno::Reference< css::awt::XWindow >* _pxUNOWindow = nullptr ) const;
+
+ /// ctor. @see Init
+ OAccessibleControlContext();
+ virtual ~OAccessibleControlContext() override;
+
+ /** late ctor
+ */
+ void Init(
+ const css::uno::Reference< css::accessibility::XAccessible >& _rxCreator
+ );
+
+ // OCommonAccessibleComponent overridables
+ virtual css::awt::Rectangle implGetBounds( ) override;
+
+ css::uno::Reference< css::beans::XPropertySet >
+ m_xControlModel; // the model of the control which's context we implement
+ css::uno::Reference< css::beans::XPropertySetInfo >
+ m_xModelPropsInfo; // the cached property set info of the model
+ };
+
+
+} // namespace toolkit
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/animatedimages.hxx b/toolkit/inc/controls/animatedimages.hxx
new file mode 100644
index 0000000000..fca49bfa39
--- /dev/null
+++ b/toolkit/inc/controls/animatedimages.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 <toolkit/controls/unocontrolmodel.hxx>
+#include <com/sun/star/awt/XAnimatedImages.hpp>
+#include <cppuhelper/implbase1.hxx>
+
+namespace com::sun::star::container { class XContainerListener; }
+namespace com::sun::star::uno { class XComponentContext; }
+
+namespace toolkit
+{
+
+
+ typedef ::cppu::AggImplInheritanceHelper1 < UnoControlModel
+ , css::awt::XAnimatedImages
+ > AnimatedImagesControlModel_Base;
+ class AnimatedImagesControlModel : public AnimatedImagesControlModel_Base
+ {
+ public:
+ AnimatedImagesControlModel( css::uno::Reference< css::uno::XComponentContext > const & i_factory );
+ AnimatedImagesControlModel( const AnimatedImagesControlModel& i_copySource );
+
+ 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;
+
+ // XAnimatedImages
+ virtual ::sal_Int32 SAL_CALL getStepTime() override;
+ virtual void SAL_CALL setStepTime( ::sal_Int32 _steptime ) override;
+ virtual sal_Bool SAL_CALL getAutoRepeat() override;
+ virtual void SAL_CALL setAutoRepeat( sal_Bool _autorepeat ) override;
+ virtual ::sal_Int16 SAL_CALL getScaleMode() override;
+ virtual void SAL_CALL setScaleMode( ::sal_Int16 _scalemode ) override;
+ virtual ::sal_Int32 SAL_CALL getImageSetCount( ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getImageSet( ::sal_Int32 i_index ) override;
+ virtual void SAL_CALL insertImageSet( ::sal_Int32 i_index, const css::uno::Sequence< OUString >& i_imageURLs ) override;
+ virtual void SAL_CALL replaceImageSet( ::sal_Int32 i_index, const css::uno::Sequence< OUString >& i_imageURLs ) override;
+ virtual void SAL_CALL removeImageSet( ::sal_Int32 i_index ) override;
+
+ // XAnimatedImages::XContainer
+ virtual void SAL_CALL addContainerListener( const css::uno::Reference< css::container::XContainerListener >& i_listener ) override;
+ virtual void SAL_CALL removeContainerListener( const css::uno::Reference< css::container::XContainerListener >& i_listener ) override;
+
+ protected:
+ virtual ~AnimatedImagesControlModel() override;
+
+ css::uno::Any ImplGetDefaultValue( sal_uInt16 nPropId ) const override;
+ ::cppu::IPropertyArrayHelper& getInfoHelper() override;
+ void setFastPropertyValue_NoBroadcast(
+ std::unique_lock<std::mutex>& rGuard,
+ sal_Int32 nHandle, const css::uno::Any& rValue ) override;
+
+ private:
+ comphelper::OInterfaceContainerHelper4<css::container::XContainerListener> maContainerListeners;
+ std::vector< css::uno::Sequence< OUString > > maImageSets;
+ };
+
+
+} // namespace toolkit
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/controlmodelcontainerbase.hxx b/toolkit/inc/controls/controlmodelcontainerbase.hxx
new file mode 100644
index 0000000000..ae414346c7
--- /dev/null
+++ b/toolkit/inc/controls/controlmodelcontainerbase.hxx
@@ -0,0 +1,270 @@
+/* -*- 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/container/XNameContainer.hpp>
+#include <com/sun/star/container/XContainer.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/awt/XTabControllerModel.hpp>
+#include <com/sun/star/util/XChangesNotifier.hpp>
+#include <com/sun/star/util/XChangesListener.hpp>
+#include <com/sun/star/util/XModifyListener.hpp>
+#include <com/sun/star/beans/XPropertyChangeListener.hpp>
+#include <cppuhelper/implbase8.hxx>
+#include <cppuhelper/implbase3.hxx>
+#include <cppuhelper/weak.hxx>
+#include <toolkit/helper/listenermultiplexer.hxx>
+#include <toolkit/controls/unocontrolmodel.hxx>
+#include <controls/unocontrolcontainer.hxx>
+#include <cppuhelper/propshlp.hxx>
+#include <com/sun/star/awt/tab/XTabPageModel.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <comphelper/interfacecontainer4.hxx>
+#include <mutex>
+#include <vector>
+
+namespace com::sun::star::resource { class XStringResourceResolver; }
+namespace com::sun::star::uno { class XComponentContext; }
+
+
+typedef UnoControlModel ControlModel_Base;
+typedef ::cppu::AggImplInheritanceHelper8 < ControlModel_Base
+ , css::lang::XMultiServiceFactory
+ , css::container::XContainer
+ , css::container::XNameContainer
+ , css::awt::XTabControllerModel
+ , css::util::XChangesNotifier
+ , css::beans::XPropertyChangeListener
+ , css::awt::tab::XTabPageModel
+ , css::lang::XInitialization
+ > ControlModelContainer_IBase;
+
+class ControlModelContainerBase : public ControlModelContainer_IBase
+{
+public:
+ enum ChildOperation { Insert = 0, Remove };
+ // would like to make this typedef private, too, but the Forte 7 compiler does have
+ // problems with this...
+ typedef ::std::pair< css::uno::Reference< css::awt::XControlModel >, OUString >
+ UnoControlModelHolder;
+private:
+ typedef ::std::vector< UnoControlModelHolder > UnoControlModelHolderVector;
+
+public:
+ // for grouping control models (XTabControllerModel::getGroupXXX)
+ typedef ::std::vector< css::uno::Reference< css::awt::XControlModel > >
+ ModelGroup;
+ typedef ::std::vector< ModelGroup > AllGroups;
+
+ friend struct CloneControlModel;
+ friend struct CompareControlModel;
+
+protected:
+ ContainerListenerMultiplexer maContainerListeners;
+ ::comphelper::OInterfaceContainerHelper4<css::util::XChangesListener> maChangeListeners;
+ UnoControlModelHolderVector maModels;
+
+ AllGroups maGroups;
+ bool mbGroupsUpToDate;
+
+ OUString m_sImageURL;
+ OUString m_sTooltip;
+ sal_Int16 m_nTabPageId;
+
+ void Clone_Impl(ControlModelContainerBase& _rClone) const;
+protected:
+ css::uno::Any ImplGetDefaultValue( sal_uInt16 nPropId ) const override;
+ ::cppu::IPropertyArrayHelper& getInfoHelper() override;
+
+ UnoControlModelHolderVector::iterator ImplFindElement( std::u16string_view rName );
+
+ /// @throws css::lang::IllegalArgumentException
+ /// @throws css::container::ElementExistException
+ /// @throws css::lang::WrappedTargetException
+ /// @throws css::uno::RuntimeException
+ void updateUserFormChildren( const css::uno::Reference< css::container::XNameContainer >& xAllChildren, const OUString& aName, ChildOperation Operation, const css::uno::Reference< css::awt::XControlModel >& xTarget );
+public:
+ ControlModelContainerBase( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
+ ControlModelContainerBase( const ControlModelContainerBase& rModel );
+ virtual ~ControlModelContainerBase() override;
+
+ rtl::Reference<UnoControlModel> Clone() const override;
+
+ // css::container::XContainer
+ void SAL_CALL addContainerListener( const css::uno::Reference< css::container::XContainerListener >& xListener ) override;
+ void SAL_CALL removeContainerListener( const css::uno::Reference< css::container::XContainerListener >& xListener ) override;
+
+ // css::container::XElementAccess
+ css::uno::Type SAL_CALL getElementType( ) override;
+ sal_Bool SAL_CALL hasElements( ) override;
+
+ // css::container::XNameContainer, XNameReplace, XNameAccess
+ void SAL_CALL replaceByName( const OUString& aName, const css::uno::Any& aElement ) override;
+ css::uno::Any SAL_CALL getByName( const OUString& aName ) override;
+ css::uno::Sequence< OUString > SAL_CALL getElementNames( ) override;
+ sal_Bool SAL_CALL hasByName( const OUString& aName ) override;
+ void SAL_CALL insertByName( const OUString& aName, const css::uno::Any& aElement ) override;
+ void SAL_CALL removeByName( const OUString& Name ) override;
+
+ // css::beans::XMultiPropertySet
+ css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+
+ // css::lang::XMultiServiceFactory
+ css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance( const OUString& aServiceSpecifier ) override;
+ css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithArguments( const OUString& ServiceSpecifier, const css::uno::Sequence< css::uno::Any >& Arguments ) override;
+ css::uno::Sequence< OUString > SAL_CALL getAvailableServiceNames( ) override;
+
+ // XComponent
+ void SAL_CALL dispose( ) override;
+
+ // XTabControllerModel
+ virtual sal_Bool SAL_CALL getGroupControl( ) override;
+ virtual void SAL_CALL setGroupControl( sal_Bool GroupControl ) override;
+ virtual void SAL_CALL setControlModels( const css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > >& Controls ) override;
+ virtual css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > > SAL_CALL getControlModels( ) override;
+ virtual void SAL_CALL setGroup( const css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > >& Group, const OUString& GroupName ) override;
+ virtual sal_Int32 SAL_CALL getGroupCount( ) override;
+ virtual void SAL_CALL getGroup( sal_Int32 nGroup, css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > >& Group, OUString& Name ) override;
+ virtual void SAL_CALL getGroupByName( const OUString& Name, css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > >& Group ) override;
+
+ // XChangesNotifier
+ virtual void SAL_CALL addChangesListener( const css::uno::Reference< css::util::XChangesListener >& aListener ) override;
+ virtual void SAL_CALL removeChangesListener( const css::uno::Reference< css::util::XChangesListener >& aListener ) override;
+
+ // XPropertyChangeListener
+ virtual void SAL_CALL propertyChange( const css::beans::PropertyChangeEvent& evt ) override;
+
+ // XEventListener
+ using comphelper::OPropertySetHelper::disposing;
+ virtual void SAL_CALL disposing( const css::lang::EventObject& evt ) override;
+
+ // XServiceInfo
+ DECLIMPL_SERVICEINFO_DERIVED(ControlModelContainerBase, ControlModel_Base, "toolkit.ControlModelContainerBase" )
+
+ // XInitialization
+ virtual void SAL_CALL initialize (const css::uno::Sequence<css::uno::Any>& rArguments) override;
+
+ // css::awt::tab::XTabPageModel
+ virtual ::sal_Int16 SAL_CALL getTabPageID() override;
+ virtual sal_Bool SAL_CALL getEnabled() override;
+ virtual void SAL_CALL setEnabled( sal_Bool _enabled ) override;
+ virtual OUString SAL_CALL getTitle() override;
+ virtual void SAL_CALL setTitle( const OUString& _title ) override;
+ virtual OUString SAL_CALL getImageURL() override;
+ virtual void SAL_CALL setImageURL( const OUString& _imageurl ) override;
+ virtual OUString SAL_CALL getToolTip() override;
+ virtual void SAL_CALL setToolTip( const OUString& _tooltip ) override;
+
+protected:
+ void startControlListening( const css::uno::Reference< css::awt::XControlModel >& _rxChildModel );
+ void stopControlListening( const css::uno::Reference< css::awt::XControlModel >& _rxChildModel );
+
+ void implNotifyTabModelChange( const OUString& _rAccessor );
+
+ void implUpdateGroupStructure();
+};
+
+class ResourceListener final : public css::util::XModifyListener,
+ public ::cppu::OWeakObject
+{
+ public:
+ ResourceListener( const css::uno::Reference< css::util::XModifyListener >& xListener );
+ virtual ~ResourceListener() override;
+
+ void startListening( const css::uno::Reference< css::resource::XStringResourceResolver >& rResource );
+ void stopListening();
+
+ // XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override;
+ virtual void SAL_CALL acquire() noexcept override;
+ virtual void SAL_CALL release() noexcept override;
+
+ // XModifyListener
+ virtual void SAL_CALL modified( const css::lang::EventObject& aEvent ) override;
+
+ // XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ private:
+ std::mutex m_aMutex;
+ css::uno::Reference< css::resource::XStringResourceResolver > m_xResource;
+ css::uno::Reference< css::util::XModifyListener > m_xListener;
+ bool m_bListening;
+};
+
+typedef ::cppu::AggImplInheritanceHelper3 < UnoControlContainer
+ , css::container::XContainerListener
+ , css::util::XChangesListener
+ , css::util::XModifyListener
+ > ControlContainer_IBase;
+
+class ControlContainerBase : public ControlContainer_IBase
+{
+protected:
+ css::uno::Reference< css::uno::XComponentContext > m_xContext;
+ bool mbSizeModified;
+ bool mbPosModified;
+ css::uno::Reference< css::awt::XTabController > mxTabController;
+ css::uno::Reference< css::util::XModifyListener > mxListener;
+
+ void ImplInsertControl( css::uno::Reference< css::awt::XControlModel > const & rxModel, const OUString& rName );
+ void ImplRemoveControl( css::uno::Reference< css::awt::XControlModel > const & rxModel );
+ virtual void ImplSetPosSize( css::uno::Reference< css::awt::XControl >& rxCtrl );
+ void ImplUpdateResourceResolver();
+ void ImplStartListingForResourceEvents();
+
+#ifdef _MSC_VER
+ // just implemented to let the various FooImplInheritanceHelper compile
+ ControlContainerBase();
+#endif
+
+public:
+ ControlContainerBase( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
+ virtual ~ControlContainerBase() override;
+
+ DECLIMPL_SERVICEINFO_DERIVED( ControlContainerBase, UnoControlBase, "toolkit.ControlContainerBase" )
+
+ void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+ void SAL_CALL dispose() override;
+
+ void SAL_CALL createPeer( const css::uno::Reference< css::awt::XToolkit >& Toolkit, const css::uno::Reference< css::awt::XWindowPeer >& Parent ) override;
+
+ // css::container::XContainerListener
+ void SAL_CALL elementInserted( const css::container::ContainerEvent& Event ) override;
+ void SAL_CALL elementRemoved( const css::container::ContainerEvent& Event ) override;
+ void SAL_CALL elementReplaced( const css::container::ContainerEvent& Event ) override;
+
+ // XChangesListener
+ virtual void SAL_CALL changesOccurred( const css::util::ChangesEvent& Event ) override;
+
+ // css::awt::XControl
+ sal_Bool SAL_CALL setModel( const css::uno::Reference< css::awt::XControlModel >& Model ) override;
+ void SAL_CALL setDesignMode( sal_Bool bOn ) override;
+ // XModifyListener
+ // Using a dummy/no-op implementation here, not sure if every container control needs
+ // to implement this, certainly Dialog does, lets see about others
+ virtual void SAL_CALL modified( const css::lang::EventObject& ) override {}
+protected:
+ virtual void ImplModelPropertiesChanged( const css::uno::Sequence< css::beans::PropertyChangeEvent >& rEvents ) override;
+ virtual void removingControl( const css::uno::Reference< css::awt::XControl >& _rxControl ) override;
+ virtual void addingControl( const css::uno::Reference< css::awt::XControl >& _rxControl ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/dialogcontrol.hxx b/toolkit/inc/controls/dialogcontrol.hxx
new file mode 100644
index 0000000000..3aaf3e50b1
--- /dev/null
+++ b/toolkit/inc/controls/dialogcontrol.hxx
@@ -0,0 +1,299 @@
+/* -*- 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/controlmodelcontainerbase.hxx>
+#include <com/sun/star/awt/UnoControlDialog.hpp>
+#include <com/sun/star/awt/XSimpleTabController.hpp>
+#include <toolkit/helper/macros.hxx>
+#include <cppuhelper/implbase2.hxx>
+
+namespace com::sun::star::awt { class XTopWindowListener; }
+
+typedef ::cppu::AggImplInheritanceHelper2 < ControlContainerBase
+ , css::awt::XUnoControlDialog
+ , css::awt::XWindowListener
+ > UnoDialogControl_Base;
+class UnoDialogControl final : public UnoDialogControl_Base
+{
+private:
+ css::uno::Reference< css::awt::XMenuBar > mxMenuBar;
+ TopWindowListenerMultiplexer maTopWindowListeners;
+ bool mbWindowListener;
+
+public:
+
+ UnoDialogControl( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
+ virtual ~UnoDialogControl() override;
+ OUString GetComponentServiceName() const 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;
+ void SAL_CALL dispose() override;
+
+ // css::awt::XTopWindow
+ void SAL_CALL addTopWindowListener( const css::uno::Reference< css::awt::XTopWindowListener >& xListener ) override;
+ void SAL_CALL removeTopWindowListener( const css::uno::Reference< css::awt::XTopWindowListener >& xListener ) override;
+ void SAL_CALL toFront( ) override;
+ void SAL_CALL toBack( ) override;
+ void SAL_CALL setMenuBar( const css::uno::Reference< css::awt::XMenuBar >& xMenu ) override;
+
+ // css::awt::XWindowListener
+ virtual void SAL_CALL windowResized( const css::awt::WindowEvent& e ) override;
+ virtual void SAL_CALL windowMoved( const css::awt::WindowEvent& e ) override;
+ virtual void SAL_CALL windowShown( const css::lang::EventObject& e ) override;
+ virtual void SAL_CALL windowHidden( const css::lang::EventObject& e ) override;
+
+ // css::awt::XDialog2
+ virtual void SAL_CALL endDialog( ::sal_Int32 Result ) override;
+ virtual void SAL_CALL setHelpId( const OUString& Id ) override;
+
+ // css::awt::XDialog
+ void SAL_CALL setTitle( const OUString& Title ) override;
+ OUString SAL_CALL getTitle() override;
+ sal_Int16 SAL_CALL execute() override;
+ void SAL_CALL endExecute() override;
+
+ // css::awt::XControl
+ sal_Bool SAL_CALL setModel( const css::uno::Reference< css::awt::XControlModel >& Model ) override;
+
+ // XModifyListener
+ virtual void SAL_CALL modified( const css::lang::EventObject& aEvent ) override;
+
+ // resolve some ambiguous methods
+ virtual css::uno::Reference<css::awt::XWindowPeer> SAL_CALL getPeer() override
+ { return UnoDialogControl_Base::ControlContainerBase::getPeer(); }
+ virtual void SAL_CALL addWindowListener(const css::uno::Reference<css::awt::XWindowListener>& p1) override
+ { UnoDialogControl_Base::ControlContainerBase::addWindowListener(p1); }
+ virtual css::uno::Reference<css::awt::XControlModel> SAL_CALL getModel() override
+ { return UnoDialogControl_Base::ControlContainerBase::getModel(); }
+ virtual void SAL_CALL addEventListener(const css::uno::Reference<css::lang::XEventListener>& p1) override
+ { UnoDialogControl_Base::ControlContainerBase::addEventListener(p1); }
+ virtual void SAL_CALL removeEventListener(const css::uno::Reference<css::lang::XEventListener>& p1) override
+ { UnoDialogControl_Base::ControlContainerBase::removeEventListener(p1); }
+ virtual void SAL_CALL setContext(const css::uno::Reference<css::uno::XInterface>& p1) override
+ { UnoDialogControl_Base::ControlContainerBase::setContext(p1); }
+ virtual css::uno::Reference<css::uno::XInterface> SAL_CALL getContext() override
+ { return UnoDialogControl_Base::ControlContainerBase::getContext(); }
+ virtual css::uno::Reference<css::awt::XView> SAL_CALL getView() override
+ { return UnoDialogControl_Base::ControlContainerBase::getView(); }
+ virtual void SAL_CALL setDesignMode(sal_Bool p1) override
+ { UnoDialogControl_Base::ControlContainerBase::setDesignMode(p1); }
+ virtual sal_Bool SAL_CALL isDesignMode() override
+ { return UnoDialogControl_Base::ControlContainerBase::isDesignMode(); }
+ virtual sal_Bool SAL_CALL isTransparent() override
+ { return UnoDialogControl_Base::ControlContainerBase::isTransparent(); }
+ virtual void SAL_CALL setPosSize(sal_Int32 p1, sal_Int32 p2, sal_Int32 p3, sal_Int32 p4, sal_Int16 p5) override
+ { UnoDialogControl_Base::ControlContainerBase::setPosSize(p1, p2, p3, p4, p5); }
+ virtual css::awt::Rectangle SAL_CALL getPosSize() override
+ { return UnoDialogControl_Base::ControlContainerBase::getPosSize(); }
+ virtual void SAL_CALL setVisible(sal_Bool p1) override
+ { UnoDialogControl_Base::ControlContainerBase::setVisible(p1); }
+ virtual void SAL_CALL setEnable(sal_Bool p1) override
+ { UnoDialogControl_Base::ControlContainerBase::setEnable(p1); }
+ virtual void SAL_CALL setFocus() override
+ { UnoDialogControl_Base::ControlContainerBase::setFocus(); }
+ virtual void SAL_CALL removeWindowListener(const css::uno::Reference<css::awt::XWindowListener>& p1) override
+ { UnoDialogControl_Base::ControlContainerBase::removeWindowListener(p1); }
+ virtual void SAL_CALL addFocusListener(const css::uno::Reference<css::awt::XFocusListener>& p1) override
+ { UnoDialogControl_Base::ControlContainerBase::addFocusListener(p1); }
+ virtual void SAL_CALL removeFocusListener(const css::uno::Reference<css::awt::XFocusListener>& p1) override
+ { UnoDialogControl_Base::ControlContainerBase::removeFocusListener(p1); }
+ virtual void SAL_CALL addKeyListener(const css::uno::Reference<css::awt::XKeyListener>& p1) override
+ { UnoDialogControl_Base::ControlContainerBase::addKeyListener(p1); }
+ virtual void SAL_CALL removeKeyListener(const css::uno::Reference<css::awt::XKeyListener>& p1) override
+ { UnoDialogControl_Base::ControlContainerBase::removeKeyListener(p1); }
+ virtual void SAL_CALL addMouseListener(const css::uno::Reference<css::awt::XMouseListener>& p1) override
+ { UnoDialogControl_Base::ControlContainerBase::addMouseListener(p1); }
+ virtual void SAL_CALL removeMouseListener(const css::uno::Reference<css::awt::XMouseListener>& p1) override
+ { UnoDialogControl_Base::ControlContainerBase::removeMouseListener(p1); }
+ virtual void SAL_CALL addMouseMotionListener(const css::uno::Reference<css::awt::XMouseMotionListener>& p1) override
+ { UnoDialogControl_Base::ControlContainerBase::addMouseMotionListener(p1); }
+ virtual void SAL_CALL removeMouseMotionListener(const css::uno::Reference<css::awt::XMouseMotionListener>& p1) override
+ { UnoDialogControl_Base::ControlContainerBase::removeMouseMotionListener(p1); }
+ virtual void SAL_CALL addPaintListener(const css::uno::Reference<css::awt::XPaintListener>& p1) override
+ { UnoDialogControl_Base::ControlContainerBase::addPaintListener(p1); }
+ virtual void SAL_CALL removePaintListener(const css::uno::Reference<css::awt::XPaintListener>& p1) override
+ { UnoDialogControl_Base::ControlContainerBase::removePaintListener(p1); }
+ virtual void SAL_CALL setStatusText(const OUString& p1) override
+ { UnoDialogControl_Base::ControlContainerBase::setStatusText(p1); }
+ virtual css::uno::Sequence<css::uno::Reference<css::awt::XControl> > SAL_CALL getControls() override
+ { return UnoDialogControl_Base::ControlContainerBase::getControls(); }
+ virtual css::uno::Reference<css::awt::XControl> SAL_CALL getControl(const OUString& p1) override
+ { return UnoDialogControl_Base::ControlContainerBase::getControl(p1); }
+ virtual void SAL_CALL addControl(const OUString& p1, const css::uno::Reference<css::awt::XControl>& p2) override
+ { UnoDialogControl_Base::ControlContainerBase::addControl(p1, p2); }
+ virtual void SAL_CALL removeControl(const css::uno::Reference<css::awt::XControl>& p1) override
+ { UnoDialogControl_Base::ControlContainerBase::removeControl(p1); }
+
+
+ // css::lang::XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+
+ sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override;
+
+ css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+private:
+ virtual void PrepareWindowDescriptor( css::awt::WindowDescriptor& rDesc ) override;
+ virtual void ImplModelPropertiesChanged( const css::uno::Sequence< css::beans::PropertyChangeEvent >& rEvents ) override;
+};
+
+class UnoMultiPageModel final : public ControlModelContainerBase
+{
+public:
+ UnoMultiPageModel( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
+ UnoMultiPageModel(const UnoMultiPageModel& rOther) : ControlModelContainerBase(rOther) {}
+ virtual ~UnoMultiPageModel() override;
+
+ rtl::Reference<UnoControlModel> Clone() const override;
+
+ DECLIMPL_SERVICEINFO_DERIVED( UnoMultiPageModel, ControlModelContainerBase, "com.sun.star.awt.UnoMultiPageModel" )
+
+ virtual OUString SAL_CALL getServiceName() override;
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+ // XNamedContainer
+ void SAL_CALL insertByName( const OUString& aName, const css::uno::Any& aElement ) override;
+
+ // Override the method of parent class
+ virtual sal_Bool SAL_CALL getGroupControl( ) override;
+private:
+ virtual css::uno::Any ImplGetDefaultValue( sal_uInt16 nPropId ) const override;
+ ::cppu::IPropertyArrayHelper& getInfoHelper() override;
+
+};
+
+class UnoMultiPageControl final : public ControlContainerBase
+ ,public css::awt::XSimpleTabController
+ ,public css::awt::XTabListener
+{
+ TabListenerMultiplexer maTabListeners;
+ void bindPage( const css::uno::Reference< css::awt::XControl >& _rxControl );
+public:
+ UnoMultiPageControl( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
+ virtual ~UnoMultiPageControl() override;
+ OUString GetComponentServiceName() const override;
+
+ // css::lang::XServiceInfo
+ DECLIMPL_SERVICEINFO_DERIVED( UnoMultiPageControl, ControlContainerBase, "com.sun.star.awt.UnoControlMultiPage" )
+ css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override { return ControlContainerBase::queryInterface(rType); }
+ css::uno::Any SAL_CALL queryAggregation( const css::uno::Type & rType ) override;
+ void SAL_CALL acquire() noexcept override { OWeakAggObject::acquire(); }
+ void SAL_CALL release() noexcept override { OWeakAggObject::release(); }
+ // css::lang::XTypeProvider
+ css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+ void SAL_CALL createPeer( const css::uno::Reference< css::awt::XToolkit >& Toolkit, const css::uno::Reference< css::awt::XWindowPeer >& Parent ) override;
+ // css::awt::XSimpleTabController
+ virtual ::sal_Int32 SAL_CALL insertTab() override;
+ virtual void SAL_CALL removeTab( ::sal_Int32 ID ) override;
+
+ virtual void SAL_CALL setTabProps( ::sal_Int32 ID, const css::uno::Sequence< css::beans::NamedValue >& Properties ) override;
+ virtual css::uno::Sequence< css::beans::NamedValue > SAL_CALL getTabProps( ::sal_Int32 ID ) override;
+
+ virtual void SAL_CALL activateTab( ::sal_Int32 ID ) override;
+ virtual ::sal_Int32 SAL_CALL getActiveTabID() override;
+
+ virtual void SAL_CALL addTabListener( const css::uno::Reference< css::awt::XTabListener >& Listener ) override;
+ virtual void SAL_CALL removeTabListener( const css::uno::Reference< css::awt::XTabListener >& Listener ) override;
+ // XTabListener
+ virtual void SAL_CALL inserted( ::sal_Int32 ID ) override;
+ virtual void SAL_CALL removed( ::sal_Int32 ID ) override;
+ virtual void SAL_CALL changed( ::sal_Int32 ID, const css::uno::Sequence< css::beans::NamedValue >& Properties ) override;
+ virtual void SAL_CALL activated( ::sal_Int32 ID ) override;
+ virtual void SAL_CALL deactivated( ::sal_Int32 ID ) override;
+ virtual void SAL_CALL disposing( const css::lang::EventObject& evt ) override;
+ // XComponent
+ void SAL_CALL dispose( ) override;
+
+private:
+ virtual void impl_createControlPeerIfNecessary(
+ const css::uno::Reference< css::awt::XControl >& _rxControl
+ ) override;
+
+};
+
+
+class UnoPageModel final : public ControlModelContainerBase
+{
+public:
+ UnoPageModel( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
+ UnoPageModel(const UnoPageModel& rOther) : ControlModelContainerBase(rOther) {}
+ virtual ~UnoPageModel() override;
+
+ rtl::Reference<UnoControlModel> Clone() const override;
+
+ DECLIMPL_SERVICEINFO_DERIVED( UnoPageModel, ControlModelContainerBase, "com.sun.star.awt.UnoPageModel" )
+
+ virtual OUString SAL_CALL getServiceName() override;
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+
+ // Override the method of parent class
+ virtual sal_Bool SAL_CALL getGroupControl( ) override;
+private:
+ virtual css::uno::Any ImplGetDefaultValue( sal_uInt16 nPropId ) const override;
+ ::cppu::IPropertyArrayHelper& getInfoHelper() override;
+
+};
+
+class UnoPageControl final : public ControlContainerBase
+{
+public:
+ UnoPageControl( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
+ virtual ~UnoPageControl() override;
+ OUString GetComponentServiceName() const override;
+
+
+ // css::lang::XServiceInfo
+ DECLIMPL_SERVICEINFO_DERIVED( UnoPageControl, ControlContainerBase, "com.sun.star.awt.UnoControlPage" )
+};
+
+class UnoFrameModel final : public ControlModelContainerBase
+{
+public:
+ UnoFrameModel( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
+ UnoFrameModel(const UnoFrameModel& rOther) : ControlModelContainerBase(rOther) {}
+ virtual ~UnoFrameModel() override;
+
+ rtl::Reference<UnoControlModel> Clone() const override;
+
+ DECLIMPL_SERVICEINFO_DERIVED( UnoFrameModel, ControlModelContainerBase, "com.sun.star.awt.UnoFrameModel" )
+
+ virtual OUString SAL_CALL getServiceName() override;
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+
+private:
+ virtual css::uno::Any ImplGetDefaultValue( sal_uInt16 nPropId ) const override;
+ ::cppu::IPropertyArrayHelper& getInfoHelper() override;
+};
+
+class UnoFrameControl final : public ControlContainerBase
+{
+ virtual void ImplSetPosSize( css::uno::Reference< css::awt::XControl >& rxCtrl ) override;
+public:
+ UnoFrameControl( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
+ virtual ~UnoFrameControl() override;
+ OUString GetComponentServiceName() const override;
+
+// css::lang::XServiceInfo
+DECLIMPL_SERVICEINFO_DERIVED( UnoFrameControl, ControlContainerBase, "com.sun.star.awt.UnoControlFrame" )
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/eventcontainer.hxx b/toolkit/inc/controls/eventcontainer.hxx
new file mode 100644
index 0000000000..79a434a398
--- /dev/null
+++ b/toolkit/inc/controls/eventcontainer.hxx
@@ -0,0 +1,82 @@
+/* -*- 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/container/XNameContainer.hpp>
+#include <com/sun/star/container/XContainer.hpp>
+
+#include <toolkit/helper/listenermultiplexer.hxx>
+
+#include <cppuhelper/implbase.hxx>
+#include <unordered_map>
+
+namespace toolkit
+{
+
+// Hashtable to optimize
+typedef std::unordered_map
+<
+ OUString,
+ sal_Int32,
+ OUStringHash
+>
+NameContainerNameMap;
+
+class ScriptEventContainer final : public ::cppu::WeakImplHelper<
+ css::container::XNameContainer,
+ css::container::XContainer >
+{
+ // The map needs to keep the insertion order, otherwise Macro signatures would get broken
+ // if the order changes here (Dialog xml files are digitally signed too).
+ // Thus a std::map or std::unordered_map can't be used.
+ NameContainerNameMap mHashMap;
+ css::uno::Sequence< OUString > mNames;
+ std::vector< css::uno::Any > mValues;
+ css::uno::Type mType;
+
+ ContainerListenerMultiplexer maContainerListeners;
+
+public:
+ ScriptEventContainer();
+
+ // Methods XElementAccess
+ virtual css::uno::Type SAL_CALL getElementType( ) override;
+ virtual sal_Bool SAL_CALL hasElements( ) override;
+
+ // Methods XNameAccess
+ virtual css::uno::Any SAL_CALL getByName( const OUString& aName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getElementNames( ) override;
+ virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override;
+
+ // Methods XNameReplace
+ virtual void SAL_CALL replaceByName( const OUString& aName, const css::uno::Any& aElement ) override;
+
+ // Methods XNameContainer
+ virtual void SAL_CALL insertByName( const OUString& aName, const css::uno::Any& aElement ) override;
+ virtual void SAL_CALL removeByName( const OUString& Name ) override;
+
+ // Methods XContainer
+ void SAL_CALL addContainerListener( const css::uno::Reference< css::container::XContainerListener >& xListener ) override;
+ void SAL_CALL removeContainerListener( const css::uno::Reference< css::container::XContainerListener >& xListener ) override;
+};
+
+} // namespace toolkit_namecontainer
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/filectrl.hxx b/toolkit/inc/controls/filectrl.hxx
new file mode 100644
index 0000000000..1330d0ce7c
--- /dev/null
+++ b/toolkit/inc/controls/filectrl.hxx
@@ -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 .
+ */
+
+#pragma once
+
+#include <vcl/window.hxx>
+#include <vcl/toolkit/button.hxx>
+
+class Edit;
+
+// Flags for internal use of FileControl
+enum class FileControlMode_Internal
+{
+ INRESIZE = 0x0001,
+ ORIGINALBUTTONTEXT = 0x0002,
+};
+
+namespace o3tl
+{
+ template<> struct typed_flags<FileControlMode_Internal> : is_typed_flags<FileControlMode_Internal, 0x03> {};
+}
+
+
+class FileControl final : public vcl::Window
+{
+ VclPtr<Edit> maEdit;
+ VclPtr<PushButton> maButton;
+ OUString maButtonText;
+ FileControlMode_Internal mnInternalFlags;
+
+ void Resize() override;
+ void GetFocus() override;
+ void StateChanged( StateChangedType nType ) override;
+ WinBits ImplInitStyle( WinBits nStyle );
+ DECL_LINK( ButtonHdl, Button*, void );
+
+public:
+ FileControl( vcl::Window* pParent, WinBits nStyle );
+ virtual ~FileControl() override;
+ virtual void dispose() override;
+
+ Edit& GetEdit() { return *maEdit; }
+ PushButton& GetButton() { return *maButton; }
+
+ void Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags ) override;
+
+ void SetText( const OUString& rStr ) override;
+ OUString GetText() const override;
+
+ void SetEditModifyHdl( const Link<Edit&,void>& rLink );
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/formattedcontrol.hxx b/toolkit/inc/controls/formattedcontrol.hxx
new file mode 100644
index 0000000000..c614b42c74
--- /dev/null
+++ b/toolkit/inc/controls/formattedcontrol.hxx
@@ -0,0 +1,124 @@
+/* -*- 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 <toolkit/controls/unocontrols.hxx>
+#include <toolkit/controls/unocontrolmodel.hxx>
+
+namespace com::sun::star::util { class XNumberFormatter; }
+
+
+namespace toolkit
+{
+
+
+ // = UnoControlFormattedFieldModel
+
+ class UnoControlFormattedFieldModel final : public UnoControlModel
+ {
+ public:
+ UnoControlFormattedFieldModel( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
+ UnoControlFormattedFieldModel( const UnoControlFormattedFieldModel& rModel )
+ : UnoControlModel(rModel)
+ , m_bRevokedAsClient(false)
+ , m_bSettingValueAndText(false)
+ {
+ }
+
+ rtl::Reference<UnoControlModel> Clone() const override { return new UnoControlFormattedFieldModel( *this ); }
+
+ // css::io::XPersistObject
+ OUString SAL_CALL getServiceName() override;
+
+ // css::beans::XMultiPropertySet
+ css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+
+
+ // css::lang::XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+
+ css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+ private:
+ virtual ~UnoControlFormattedFieldModel() override;
+
+ // XComponent
+ void SAL_CALL dispose() override;
+
+ // XPropertySet
+ void SAL_CALL setPropertyValues( const css::uno::Sequence< OUString >& PropertyNames, const css::uno::Sequence< css::uno::Any >& Values ) override;
+
+ // UnoControlModel
+ virtual void ImplNormalizePropertySequence(
+ const sal_Int32 _nCount, /// the number of entries in the arrays
+ sal_Int32* _pHandles, /// the handles of the properties to set
+ css::uno::Any* _pValues, /// the values of the properties to set
+ sal_Int32* _pValidHandles /// pointer to the valid handles, allowed to be adjusted
+ ) const override;
+ void impl_updateTextFromValue_nothrow(std::unique_lock<std::mutex>& rGuard);
+ void impl_updateCachedFormatter_nothrow(std::unique_lock<std::mutex>& rGuard);
+ void impl_updateCachedFormatKey_nothrow(std::unique_lock<std::mutex>& rGuard);
+
+ css::uno::Any ImplGetDefaultValue( sal_uInt16 nPropId ) const override;
+ ::cppu::IPropertyArrayHelper& getInfoHelper() override;
+ bool convertFastPropertyValue(
+ std::unique_lock<std::mutex>& rGuard,
+ css::uno::Any& rConvertedValue,
+ css::uno::Any& rOldValue,
+ sal_Int32 nPropId,
+ const css::uno::Any& rValue
+ ) override;
+
+ void setFastPropertyValue_NoBroadcast(
+ std::unique_lock<std::mutex>& rGuard,
+ sal_Int32 nHandle,
+ const css::uno::Any& rValue
+ ) override;
+
+ css::uno::Any m_aCachedFormat;
+ bool m_bRevokedAsClient;
+ bool m_bSettingValueAndText;
+ css::uno::Reference< css::util::XNumberFormatter >
+ m_xCachedFormatter;
+ };
+
+
+ // = UnoFormattedFieldControl
+
+ class UnoFormattedFieldControl final : public UnoSpinFieldControl
+ {
+ public:
+ UnoFormattedFieldControl();
+ OUString GetComponentServiceName() const override;
+
+ // css::awt::XTextListener
+ void SAL_CALL textChanged( const css::awt::TextEvent& rEvent ) override;
+
+ // css::lang::XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+
+ css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+ };
+
+
+} // namespace toolkit
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/geometrycontrolmodel.hxx b/toolkit/inc/controls/geometrycontrolmodel.hxx
new file mode 100644
index 0000000000..c2dc13b49f
--- /dev/null
+++ b/toolkit/inc/controls/geometrycontrolmodel.hxx
@@ -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 .
+ */
+
+#pragma once
+
+#include <comphelper/broadcasthelper.hxx>
+#include <comphelper/propagg.hxx>
+#include <comphelper/proparrhlp.hxx>
+#include <comphelper/propertycontainer.hxx>
+#include <cppuhelper/compbase2.hxx>
+#include <com/sun/star/util/XCloneable.hpp>
+#include <com/sun/star/script/XScriptEventsSupplier.hpp>
+#include <comphelper/IdPropArrayHelper.hxx>
+#include <rtl/ref.hxx>
+
+namespace com::sun::star::resource { class XStringResourceResolver; }
+
+namespace com::sun::star {
+ namespace uno {
+ class XComponentContext;
+ }
+}
+
+
+// namespace toolkit
+// {
+
+
+ //= OGeometryControlModel_Base
+
+ typedef ::cppu::WeakAggComponentImplHelper2 < css::util::XCloneable
+ , css::script::XScriptEventsSupplier
+ > OGCM_Base;
+ class OGeometryControlModel_Base
+ :public ::comphelper::OMutexAndBroadcastHelper
+ ,public ::comphelper::OPropertySetAggregationHelper
+ ,public ::comphelper::OPropertyContainer
+ ,public OGCM_Base
+ {
+ protected:
+ css::uno::Reference< css::uno::XAggregation >
+ m_xAggregate;
+ css::uno::Reference< css::container::XNameContainer >
+ mxEventContainer;
+
+ // <properties>
+ sal_Int32 m_nPosX;
+ sal_Int32 m_nPosY;
+ sal_Int32 m_nWidth;
+ sal_Int32 m_nHeight;
+ OUString m_aName;
+ sal_Int16 m_nTabIndex;
+ sal_Int32 m_nStep;
+ OUString m_aTag;
+ css::uno::Reference< css::resource::XStringResourceResolver > m_xStrResolver;
+ // </properties>
+
+ bool m_bCloneable;
+
+ protected:
+ static css::uno::Any ImplGetDefaultValueByHandle(sal_Int32 nHandle);
+ css::uno::Any ImplGetPropertyValueByHandle(sal_Int32 nHandle) const;
+ void ImplSetPropertyValueByHandle(sal_Int32 nHandle, const css::uno::Any& aValue);
+
+ protected:
+ /**
+ @param _pAggregateInstance
+ the object to be aggregated. The refcount of the instance given MUST be 0!
+ */
+ OGeometryControlModel_Base(css::uno::XAggregation* _pAggregateInstance);
+
+ /**
+ @param _rxAggregateInstance
+ is the object to be aggregated. Must be acquired exactly once (by the reference object given).<br/>
+ Will be reset to NULL upon leaving
+ */
+ OGeometryControlModel_Base(css::uno::Reference< css::util::XCloneable >& _rxAggregateInstance);
+
+ /** releases the aggregation
+ <p>Can be used if in a derived class, an exception has to be thrown after this base class here already
+ did the aggregation</p>
+ */
+ void releaseAggregation();
+
+ protected:
+ virtual ~OGeometryControlModel_Base() override;
+
+ // XAggregation
+ css::uno::Any SAL_CALL queryAggregation( const css::uno::Type& _aType ) override;
+
+ public:
+ // XInterface
+ virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type& aType ) override;
+ virtual void SAL_CALL acquire( ) noexcept override;
+ virtual void SAL_CALL release( ) noexcept override;
+
+ protected:
+ // XTypeProvider
+ virtual css::uno::Sequence< css::uno::Type > SAL_CALL getTypes( ) override;
+
+ // OPropertySetHelper overridables
+ virtual sal_Bool SAL_CALL convertFastPropertyValue(
+ css::uno::Any& _rConvertedValue, css::uno::Any& _rOldValue,
+ sal_Int32 _nHandle, const css::uno::Any& _rValue ) override;
+
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast(
+ sal_Int32 _nHandle, const css::uno::Any& _rValue) override;
+
+ using comphelper::OPropertySetAggregationHelper::getFastPropertyValue;
+ virtual void SAL_CALL getFastPropertyValue(
+ css::uno::Any& _rValue, sal_Int32 _nHandle) const override;
+
+ // OPropertyStateHelper overridables
+ virtual css::beans::PropertyState getPropertyStateByHandle(sal_Int32 nHandle) override;
+ virtual void setPropertyToDefaultByHandle(sal_Int32 nHandle) override;
+ virtual css::uno::Any getPropertyDefaultByHandle(sal_Int32 nHandle) const override;
+
+ // XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
+
+ // OPropertySetAggregationHelper overridables
+ using OPropertySetAggregationHelper::getInfoHelper;
+
+ // XCloneable
+ virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone( ) override;
+
+ //XScriptEventsSupplier
+ virtual css::uno::Reference< css::container::XNameContainer >
+ SAL_CALL getEvents( ) override;
+
+ // XCloneable implementation - to be overwritten
+ virtual rtl::Reference<OGeometryControlModel_Base> createClone_Impl(
+ css::uno::Reference< css::util::XCloneable >& _rxAggregateInstance) = 0;
+
+ // XComponent
+ using comphelper::OPropertySetAggregationHelper::disposing;
+ virtual void SAL_CALL disposing() override;
+
+ private:
+ void registerProperties();
+ };
+
+
+ //= OTemplateInstanceDisambiguation
+
+ template <class CONTROLMODEL>
+ class OTemplateInstanceDisambiguation
+ {
+ };
+
+
+ //= OGeometryControlModel
+
+ /* example for usage:
+ Reference< XAggregation > xIFace = new ::toolkit::OGeometryControlModel< UnoControlButtonModel > ();
+ */
+ template <class CONTROLMODEL>
+ class OGeometryControlModel final
+ :public OGeometryControlModel_Base
+ ,public ::comphelper::OAggregationArrayUsageHelper< OTemplateInstanceDisambiguation< CONTROLMODEL > >
+ {
+ public:
+ OGeometryControlModel( const css::uno::Reference< css::uno::XComponentContext >& i_factory );
+
+ private:
+ OGeometryControlModel(css::uno::Reference< css::util::XCloneable >& _rxAggregateInstance);
+
+ // OAggregationArrayUsageHelper overridables
+ virtual void fillProperties(
+ css::uno::Sequence< css::beans::Property >& _rProps,
+ css::uno::Sequence< css::beans::Property >& _rAggregateProps
+ ) const override;
+
+ // OPropertySetAggregationHelper overridables
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ // OGeometryControlModel_Base
+ virtual rtl::Reference<OGeometryControlModel_Base> createClone_Impl(
+ css::uno::Reference< css::util::XCloneable >& _rxAggregateInstance) override;
+
+ // XTypeProvider
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) override;
+ };
+
+
+ //= OCommonGeometryControlModel
+
+ /** allows to extend an arbitrary com.sun.star.awt::UnoControlModel with geometry
+ information.
+ */
+ class OCommonGeometryControlModel final
+ :public OGeometryControlModel_Base
+ ,public ::comphelper::OIdPropertyArrayUsageHelper< OCommonGeometryControlModel >
+ {
+ private:
+ OUString m_sServiceSpecifier; // the service specifier of our aggregate
+ sal_Int32 m_nPropertyMapId; // our unique property info id, used to look up in s_aAggregateProperties
+
+ public:
+ /** instantiate the model
+
+ @param _rxAgg
+ the instance to aggregate. Must support the com.sun.star.awt::UnoControlModel
+ (this is not checked here)
+ */
+ OCommonGeometryControlModel(
+ css::uno::Reference< css::util::XCloneable >& _rxAgg,
+ OUString _aServiceSpecifier
+ );
+
+ // OIdPropertyArrayUsageHelper overridables
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper(sal_Int32 nId) const override;
+
+ // OPropertySetAggregationHelper overridables
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ // OGeometryControlModel_Base
+ virtual rtl::Reference<OGeometryControlModel_Base> createClone_Impl(
+ css::uno::Reference< css::util::XCloneable >& _rxAggregateInstance) override;
+
+ // XTypeProvider
+ virtual css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId( ) override;
+
+ private:
+ virtual void SAL_CALL setFastPropertyValue_NoBroadcast(
+ sal_Int32 _nHandle, const css::uno::Any& _rValue) override;
+ };
+
+#include <controls/geometrycontrolmodel_impl.hxx>
+
+
+// } // namespace toolkit
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/geometrycontrolmodel_impl.hxx b/toolkit/inc/controls/geometrycontrolmodel_impl.hxx
new file mode 100644
index 0000000000..2ec8595ddd
--- /dev/null
+++ b/toolkit/inc/controls/geometrycontrolmodel_impl.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 .
+ */
+
+// no include protection. This is included from within geometrycontrolmodel.hxx only
+
+//= OGeometryControlModel
+
+template <class CONTROLMODEL>
+OGeometryControlModel<CONTROLMODEL>::OGeometryControlModel(
+ const css::uno::Reference<css::uno::XComponentContext>& i_factory)
+ : OGeometryControlModel_Base(new CONTROLMODEL(i_factory))
+{
+}
+
+template <class CONTROLMODEL>
+OGeometryControlModel<CONTROLMODEL>::OGeometryControlModel(
+ css::uno::Reference<css::util::XCloneable>& _rxAggregateInstance)
+ : OGeometryControlModel_Base(_rxAggregateInstance)
+{
+}
+
+template <class CONTROLMODEL>
+::cppu::IPropertyArrayHelper& SAL_CALL OGeometryControlModel<CONTROLMODEL>::getInfoHelper()
+{
+ return *this->getArrayHelper();
+}
+
+template <class CONTROLMODEL>
+void OGeometryControlModel<CONTROLMODEL>::fillProperties(
+ css::uno::Sequence<css::beans::Property>& _rProps,
+ css::uno::Sequence<css::beans::Property>& _rAggregateProps) const
+{
+ // our own properties
+ OPropertyContainer::describeProperties(_rProps);
+ // the aggregate properties
+ if (m_xAggregateSet.is())
+ _rAggregateProps = m_xAggregateSet->getPropertySetInfo()->getProperties();
+}
+
+template <class CONTROLMODEL>
+css::uno::Sequence<sal_Int8> SAL_CALL OGeometryControlModel<CONTROLMODEL>::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+template <class CONTROLMODEL>
+rtl::Reference<OGeometryControlModel_Base> OGeometryControlModel<CONTROLMODEL>::createClone_Impl(
+ css::uno::Reference<css::util::XCloneable>& _rxAggregateInstance)
+{
+ return new OGeometryControlModel<CONTROLMODEL>(_rxAggregateInstance);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/roadmapcontrol.hxx b/toolkit/inc/controls/roadmapcontrol.hxx
new file mode 100644
index 0000000000..cb6e2cec45
--- /dev/null
+++ b/toolkit/inc/controls/roadmapcontrol.hxx
@@ -0,0 +1,185 @@
+/* -*- 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 <toolkit/controls/unocontrols.hxx>
+#include <toolkit/controls/unocontrolmodel.hxx>
+#include <com/sun/star/container/XContainer.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/beans/XPropertyChangeListener.hpp>
+#include <com/sun/star/container/XIndexContainer.hpp>
+#include <com/sun/star/container/XContainerListener.hpp>
+#include <com/sun/star/awt/XItemListener.hpp>
+#include <com/sun/star/awt/XItemEventBroadcaster.hpp>
+#include <cppuhelper/implbase2.hxx>
+#include <cppuhelper/implbase3.hxx>
+#include <cppuhelper/implbase4.hxx>
+
+
+#include <comphelper/uno3.hxx>
+
+
+namespace toolkit
+{
+
+
+ typedef GraphicControlModel UnoControlRoadmapModel_Base;
+
+
+ typedef ::cppu::ImplHelper3 < css::lang::XSingleServiceFactory
+ , css::container::XContainer
+ , css::container::XIndexContainer
+ > UnoControlRoadmapModel_IBase;
+
+
+ typedef UnoControlBase UnoControlRoadmap_Base;
+ typedef ::cppu::ImplHelper4 < css::awt::XItemEventBroadcaster
+ , css::container::XContainerListener
+ , css::awt::XItemListener
+ , css::beans::XPropertyChangeListener
+ > UnoControlRoadmap_IBase;
+
+
+ typedef ::cppu::ImplHelper2< css::container::XContainerListener,
+ css::awt::XItemEventBroadcaster> SVTXRoadmap_Base;
+
+
+ // = UnoControlRoadmapModel
+
+ class UnoControlRoadmapModel final : public UnoControlRoadmapModel_Base,
+ public UnoControlRoadmapModel_IBase
+
+ {
+ private:
+// PropertyChangeListenerMultiplexer maPropertyListeners;
+
+ typedef ::std::vector< css::uno::Reference< XInterface > > RoadmapItemHolderList;
+
+ ContainerListenerMultiplexer maContainerListeners;
+ RoadmapItemHolderList maRoadmapItems;
+
+ void MakeRMItemValidation( sal_Int32 Index, const css::uno::Reference< XInterface >& xRoadmapItem );
+ css::container::ContainerEvent GetContainerEvent(sal_Int32 Index, const css::uno::Reference< XInterface >& );
+ void SetRMItemDefaultProperties( const css::uno::Reference< XInterface >& );
+ static sal_Int16 GetCurrentItemID( const css::uno::Reference< css::beans::XPropertySet >& xPropertySet );
+ sal_Int32 GetUniqueID();
+
+ css::uno::Any ImplGetDefaultValue( sal_uInt16 nPropId ) const override;
+ ::cppu::IPropertyArrayHelper& getInfoHelper() override;
+
+ public:
+ UnoControlRoadmapModel( const css::uno::Reference< css::uno::XComponentContext >& i_factory );
+ UnoControlRoadmapModel( const UnoControlRoadmapModel& rModel ) :
+ UnoControlRoadmapModel_Base( rModel ),
+ UnoControlRoadmapModel_IBase( rModel ),
+ maContainerListeners( *this ) {}
+ rtl::Reference<UnoControlModel> Clone() const override { return new UnoControlRoadmapModel( *this ); }
+
+
+ // XTypeProvider
+ DECLARE_XTYPEPROVIDER( )
+
+
+ // css::io::XPersistObject
+ OUString SAL_CALL getServiceName() override;
+
+ // css::lang::XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+
+ css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+ sal_Int32 SAL_CALL getCount() override;
+ virtual css::uno::Any SAL_CALL getByIndex( sal_Int32 Index ) override;
+
+ virtual void SAL_CALL insertByIndex( sal_Int32 Index, const css::uno::Any & Element) override;
+ virtual void SAL_CALL removeByIndex( sal_Int32 Index ) override;
+ virtual void SAL_CALL replaceByIndex( sal_Int32 Index, const css::uno::Any & Element) override;
+
+ 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;
+
+ css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override { return UnoControlRoadmapModel_Base::queryInterface(rType); }
+ css::uno::Any SAL_CALL queryAggregation( const css::uno::Type & rType ) override;
+ void SAL_CALL acquire() noexcept override { UnoControlRoadmapModel_Base::acquire(); }
+ void SAL_CALL release() noexcept override { UnoControlRoadmapModel_Base::release(); }
+
+
+ // css::beans::XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+
+
+ virtual css::uno::Reference< XInterface > SAL_CALL createInstance( ) override;
+ virtual css::uno::Reference< XInterface > SAL_CALL createInstanceWithArguments( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
+
+ virtual css::uno::Type SAL_CALL getElementType() override;
+
+ virtual sal_Bool SAL_CALL hasElements() override;
+
+ };
+
+
+ // = UnoRoadmapControl
+
+ class UnoRoadmapControl final : public UnoControlRoadmap_Base,
+ public UnoControlRoadmap_IBase
+ {
+ private:
+ ItemListenerMultiplexer maItemListeners;
+ public:
+ UnoRoadmapControl();
+ OUString GetComponentServiceName() const override;
+
+ void SAL_CALL disposing( const css::lang::EventObject& Source ) override { UnoControlBase::disposing( Source ); }
+
+ void SAL_CALL dispose( ) override;
+
+
+ sal_Bool SAL_CALL setModel(const css::uno::Reference< css::awt::XControlModel >& Model) override;
+
+ 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;
+
+ 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;
+
+
+ virtual void SAL_CALL itemStateChanged( const css::awt::ItemEvent& rEvent ) override;
+
+ virtual void SAL_CALL propertyChange( const css::beans::PropertyChangeEvent& evt ) override;
+
+ // XTypeProvider
+ DECLARE_XTYPEPROVIDER( )
+ DECLARE_UNO3_AGG_DEFAULTS(UnoRoadmapControl, UnoControlRoadmap_Base)
+
+ css::uno::Any SAL_CALL queryAggregation(css::uno::Type const & aType) override;
+
+ // css::lang::XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+
+ css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+ };
+
+
+} // toolkit
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/roadmapentry.hxx b/toolkit/inc/controls/roadmapentry.hxx
new file mode 100644
index 0000000000..b8490439c9
--- /dev/null
+++ b/toolkit/inc/controls/roadmapentry.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 .
+ */
+#pragma once
+
+#include <comphelper/uno3.hxx>
+#include <comphelper/broadcasthelper.hxx>
+#include <comphelper/propertycontainer.hxx>
+#include <comphelper/proparrhlp.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <cppuhelper/implbase.hxx>
+
+
+#define RM_PROPERTY_ID_LABEL 1
+#define RM_PROPERTY_ID_ID 2
+#define RM_PROPERTY_ID_ENABLED 4
+#define RM_PROPERTY_ID_INTERACTIVE 5
+
+typedef cppu::WeakImplHelper< css::lang::XServiceInfo > ORoadmapEntry_Base;
+
+class ORoadmapEntry final : public ORoadmapEntry_Base
+ ,public ::comphelper::OMutexAndBroadcastHelper
+ ,public ::comphelper::OPropertyContainer
+ ,public ::comphelper::OPropertyArrayUsageHelper< ORoadmapEntry >
+{
+
+public:
+ ORoadmapEntry();
+
+ DECLARE_XINTERFACE() // merge XInterface implementations
+ DECLARE_XTYPEPROVIDER() // merge XTypeProvider implementations
+
+private:
+ /// @see css::beans::XPropertySet
+ virtual css::uno::Reference< css::beans::XPropertySetInfo >
+ SAL_CALL getPropertySetInfo() override;
+
+ // OPropertySetHelper
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+
+ // OPropertyArrayUsageHelper
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper() const override;
+
+ 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;
+
+ OUString m_sLabel;
+ sal_Int32 m_nID;
+ bool m_bEnabled;
+ bool m_bInteractive;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/stdtabcontroller.hxx b/toolkit/inc/controls/stdtabcontroller.hxx
new file mode 100644
index 0000000000..37de42d7da
--- /dev/null
+++ b/toolkit/inc/controls/stdtabcontroller.hxx
@@ -0,0 +1,86 @@
+/* -*- 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/lang/XServiceInfo.hpp>
+#include <com/sun/star/awt/XTabController.hpp>
+#include <com/sun/star/lang/XTypeProvider.hpp>
+#include <cppuhelper/weakagg.hxx>
+#include <osl/mutex.hxx>
+
+
+namespace com::sun::star::awt { class XWindow; }
+namespace com::sun::star::awt { class XControl; }
+namespace com::sun::star::awt { class XControlContainer; }
+
+class StdTabController final : public css::awt::XTabController,
+ public css::lang::XServiceInfo,
+ public css::lang::XTypeProvider,
+ public ::cppu::OWeakAggObject
+{
+private:
+ ::osl::Mutex maMutex;
+ css::uno::Reference< css::awt::XTabControllerModel > mxModel;
+ css::uno::Reference< css::awt::XControlContainer > mxControlContainer;
+
+ ::osl::Mutex& GetMutex() { return maMutex; }
+ static bool ImplCreateComponentSequence( css::uno::Sequence< css::uno::Reference< css::awt::XControl > >& rControls, const css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > >& rModels, css::uno::Sequence< css::uno::Reference< css::awt::XWindow > >& rComponents, css::uno::Sequence< css::uno::Any>* pTabStops, bool bPeerComponent );
+ // if sequence length of rModels is less than rControls, return only the matching elements in rModels sequence and remove corresponding elements from rControls
+ void ImplActivateControl( bool bFirst ) const;
+
+public:
+ StdTabController();
+ virtual ~StdTabController() override;
+
+ static css::uno::Reference< css::awt::XControl > FindControl( css::uno::Sequence< css::uno::Reference< css::awt::XControl > >& rCtrls, const css::uno::Reference< css::awt::XControlModel > & rxCtrlModel );
+
+ // css::uno::XInterface
+ css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override { return OWeakAggObject::queryInterface(rType); }
+ void SAL_CALL acquire() noexcept override { OWeakAggObject::acquire(); }
+ void SAL_CALL release() noexcept override { OWeakAggObject::release(); }
+
+ css::uno::Any SAL_CALL queryAggregation( const css::uno::Type & rType ) override;
+
+ // css::lang::XTypeProvider
+ css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+
+ // XTabController
+ void SAL_CALL setModel( const css::uno::Reference< css::awt::XTabControllerModel >& Model ) override;
+ css::uno::Reference< css::awt::XTabControllerModel > SAL_CALL getModel( ) override;
+ void SAL_CALL setContainer( const css::uno::Reference< css::awt::XControlContainer >& Container ) override;
+ css::uno::Reference< css::awt::XControlContainer > SAL_CALL getContainer( ) override;
+ css::uno::Sequence< css::uno::Reference< css::awt::XControl > > SAL_CALL getControls( ) override;
+ void SAL_CALL autoTabOrder( ) override;
+ void SAL_CALL activateTabOrder( ) override;
+ void SAL_CALL activateFirst( ) override;
+ void SAL_CALL activateLast( ) override;
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+
+ sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override;
+
+ css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/stdtabcontrollermodel.hxx b/toolkit/inc/controls/stdtabcontrollermodel.hxx
new file mode 100644
index 0000000000..4fa12d252e
--- /dev/null
+++ b/toolkit/inc/controls/stdtabcontrollermodel.hxx
@@ -0,0 +1,123 @@
+/* -*- 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/lang/XServiceInfo.hpp>
+#include <com/sun/star/io/XPersistObject.hpp>
+#include <com/sun/star/awt/XTabControllerModel.hpp>
+#include <com/sun/star/lang/XTypeProvider.hpp>
+#include <cppuhelper/weakagg.hxx>
+#include <osl/mutex.hxx>
+
+#include <vector>
+
+struct UnoControlModelEntry;
+typedef ::std::vector< UnoControlModelEntry* > UnoControlModelEntryListBase;
+
+class UnoControlModelEntryList
+{
+private:
+ UnoControlModelEntryListBase maList;
+ OUString maGroupName;
+
+public:
+ UnoControlModelEntryList();
+ ~UnoControlModelEntryList();
+
+ const OUString& GetName() const { return maGroupName; }
+ void SetName( const OUString& rName ) { maGroupName = rName; }
+
+ void Reset();
+ void DestroyEntry( size_t nEntry );
+ size_t size() const;
+ UnoControlModelEntry* operator[]( size_t i ) const;
+ void push_back( UnoControlModelEntry* item );
+ void insert( size_t i, UnoControlModelEntry* item );
+};
+
+struct UnoControlModelEntry
+{
+ bool bGroup;
+ union
+ {
+ css::uno::Reference< css::awt::XControlModel >* pxControl;
+ UnoControlModelEntryList* pGroup;
+ };
+};
+
+#define CONTROLPOS_NOTFOUND 0xFFFFFFFF
+
+class StdTabControllerModel final : public css::awt::XTabControllerModel,
+ public css::lang::XServiceInfo,
+ public css::io::XPersistObject,
+ public css::lang::XTypeProvider,
+ public ::cppu::OWeakAggObject
+{
+ ::osl::Mutex maMutex;
+ UnoControlModelEntryList maControls;
+ bool mbGroupControl;
+
+ ::osl::Mutex& GetMutex() { return maMutex; }
+ sal_uInt32 ImplGetControlCount( const UnoControlModelEntryList& rList ) const;
+ void ImplGetControlModels( css::uno::Reference< css::awt::XControlModel > ** pRefs, const UnoControlModelEntryList& rList ) const;
+ static void ImplSetControlModels( UnoControlModelEntryList& rList, const css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > >& Controls );
+ static sal_uInt32 ImplGetControlPos( const css::uno::Reference< css::awt::XControlModel >& rCtrl, const UnoControlModelEntryList& rList );
+
+public:
+ StdTabControllerModel();
+ virtual ~StdTabControllerModel() override;
+
+ // css::uno::XInterface
+ css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override { return OWeakAggObject::queryInterface(rType); }
+ void SAL_CALL acquire() noexcept override { OWeakAggObject::acquire(); }
+ void SAL_CALL release() noexcept override { OWeakAggObject::release(); }
+
+ css::uno::Any SAL_CALL queryAggregation( const css::uno::Type & rType ) override;
+
+ // css::lang::XTypeProvider
+ css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+
+ // css::awt::XTabControllerModel
+ sal_Bool SAL_CALL getGroupControl( ) override;
+ void SAL_CALL setGroupControl( sal_Bool GroupControl ) override;
+ void SAL_CALL setControlModels( const css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > >& Controls ) override;
+ css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > > SAL_CALL getControlModels( ) override;
+ void SAL_CALL setGroup( const css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > >& Group, const OUString& GroupName ) override;
+ sal_Int32 SAL_CALL getGroupCount( ) override;
+ void SAL_CALL getGroup( sal_Int32 nGroup, css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > >& Group, OUString& Name ) override;
+ void SAL_CALL getGroupByName( const OUString& Name, css::uno::Sequence< css::uno::Reference< css::awt::XControlModel > >& Group ) override;
+
+ // css::io::XPersistObject
+ OUString SAL_CALL getServiceName( ) override;
+ void SAL_CALL write( const css::uno::Reference< css::io::XObjectOutputStream >& OutStream ) override;
+ void SAL_CALL read( const css::uno::Reference< css::io::XObjectInputStream >& InStream ) override;
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+
+ sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override;
+
+ css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/svmedit.hxx b/toolkit/inc/controls/svmedit.hxx
new file mode 100644
index 0000000000..61befc9815
--- /dev/null
+++ b/toolkit/inc/controls/svmedit.hxx
@@ -0,0 +1,32 @@
+/* -*- 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/toolkit/vclmedit.hxx>
+
+class MultiLineEdit final : public VclMultiLineEdit
+{
+public:
+ MultiLineEdit( vcl::Window* pParent, WinBits nWinStyle );
+
+ virtual css::uno::Reference< css::awt::XVclWindowPeer > GetComponentInterface(bool bCreate = true) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/table/defaultinputhandler.hxx b/toolkit/inc/controls/table/defaultinputhandler.hxx
new file mode 100644
index 0000000000..3f3d425a69
--- /dev/null
+++ b/toolkit/inc/controls/table/defaultinputhandler.hxx
@@ -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 .
+ */
+
+#pragma once
+
+#include <controls/table/mousefunction.hxx>
+#include <controls/table/tableinputhandler.hxx>
+#include <rtl/ref.hxx>
+
+#include <vector>
+
+namespace svt::table
+{
+
+ class DefaultInputHandler final : public ITableInputHandler
+ {
+ public:
+ DefaultInputHandler();
+ virtual ~DefaultInputHandler() override;
+
+ virtual bool MouseMove ( ITableControl& _rControl, const MouseEvent& rMEvt ) override;
+ virtual bool MouseButtonDown ( ITableControl& _rControl, const MouseEvent& rMEvt ) override;
+ virtual bool MouseButtonUp ( ITableControl& _rControl, const MouseEvent& rMEvt ) override;
+ virtual bool KeyInput ( ITableControl& _rControl, const KeyEvent& rKEvt ) override;
+ virtual bool GetFocus ( ITableControl& _rControl ) override;
+ virtual bool LoseFocus ( ITableControl& _rControl ) override;
+
+ private:
+ bool delegateMouseEvent( ITableControl& i_control, const MouseEvent& i_event,
+ FunctionResult ( MouseFunction::*i_handlerMethod )( ITableControl&, const MouseEvent& ) );
+
+ rtl::Reference< MouseFunction > pActiveFunction;
+ std::vector< rtl::Reference< MouseFunction > > aMouseFunctions;
+ };
+
+
+} // namespace svt::table
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/table/gridtablerenderer.hxx b/toolkit/inc/controls/table/gridtablerenderer.hxx
new file mode 100644
index 0000000000..e2634b2d26
--- /dev/null
+++ b/toolkit/inc/controls/table/gridtablerenderer.hxx
@@ -0,0 +1,116 @@
+/* -*- 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 <vcl/image.hxx>
+
+#include <memory>
+
+
+namespace svt::table
+{
+
+
+ struct GridTableRenderer_Impl;
+
+
+ //= GridTableRenderer
+
+ /** a default implementation for the ->ITableRenderer interface
+
+ This class is able to paint a table grid, table headers, and cell
+ backgrounds according to the selected/active state of cells.
+ */
+ class GridTableRenderer final : public ITableRenderer
+ {
+ private:
+ ::std::unique_ptr< GridTableRenderer_Impl > m_pImpl;
+
+ public:
+ /** creates a table renderer associated with the given model
+
+ @param _rModel
+ the model which should be rendered. The caller is responsible
+ for lifetime control, that is, the model instance must live
+ at least as long as the renderer instance lives
+ */
+ GridTableRenderer( ITableModel& _rModel );
+ virtual ~GridTableRenderer() override;
+
+ /** determines whether or not to paint grid lines
+ */
+ bool useGridLines() const;
+
+ /** controls whether or not to paint grid lines
+ */
+ void useGridLines( bool const i_use );
+
+ public:
+ // ITableRenderer overridables
+ virtual void PaintHeaderArea(
+ vcl::RenderContext& _rDevice, const tools::Rectangle& _rArea,
+ bool _bIsColHeaderArea, bool _bIsRowHeaderArea,
+ const StyleSettings& _rStyle ) override;
+ virtual void PaintColumnHeader( ColPos _nCol,
+ vcl::RenderContext& _rDevice, const tools::Rectangle& _rArea,
+ const StyleSettings& _rStyle ) override;
+ virtual void PrepareRow( RowPos _nRow, bool i_hasControlFocus, bool _bSelected,
+ vcl::RenderContext& _rDevice, const tools::Rectangle& _rRowArea,
+ const StyleSettings& _rStyle ) override;
+ virtual void PaintRowHeader(
+ vcl::RenderContext& _rDevice, const tools::Rectangle& _rArea,
+ const StyleSettings& _rStyle ) override;
+ virtual void PaintCell( ColPos const i_col,
+ bool i_hasControlFocus, bool _bSelected,
+ vcl::RenderContext& _rDevice, const tools::Rectangle& _rArea,
+ const StyleSettings& _rStyle ) override;
+ virtual void ShowCellCursor( vcl::Window& _rView, const tools::Rectangle& _rCursorRect) override;
+ virtual void HideCellCursor( vcl::Window& _rView ) override;
+ virtual bool FitsIntoCell(
+ css::uno::Any const & i_cellContent,
+ OutputDevice& i_targetDevice, tools::Rectangle const & i_targetArea
+ ) const override;
+ virtual bool GetFormattedCellString(
+ css::uno::Any const & i_cellValue,
+ OUString & o_cellString
+ ) const override;
+
+ private:
+ struct CellRenderContext;
+
+ void impl_paintCellContent(
+ CellRenderContext const & i_context
+ );
+ void impl_paintCellImage(
+ CellRenderContext const & i_context,
+ Image const & i_image
+ );
+ void impl_paintCellText(
+ CellRenderContext const & i_context,
+ OUString const & i_text
+ );
+ };
+
+} // namespace svt::table
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/table/mousefunction.hxx b/toolkit/inc/controls/table/mousefunction.hxx
new file mode 100644
index 0000000000..ef68dc89ce
--- /dev/null
+++ b/toolkit/inc/controls/table/mousefunction.hxx
@@ -0,0 +1,133 @@
+/* -*- 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 "tabletypes.hxx"
+
+#include <salhelper/simplereferenceobject.hxx>
+
+class MouseEvent;
+
+namespace svt::table
+{
+class ITableControl;
+
+//= FunctionResult
+
+enum FunctionResult
+{
+ ActivateFunction,
+ ContinueFunction,
+ DeactivateFunction,
+
+ SkipFunction
+};
+
+//= MouseFunction
+
+class MouseFunction : public ::salhelper::SimpleReferenceObject
+{
+public:
+ MouseFunction() {}
+ MouseFunction(const MouseFunction&) = delete;
+ MouseFunction& operator=(const MouseFunction&) = delete;
+ virtual FunctionResult handleMouseMove(ITableControl& i_tableControl, MouseEvent const& i_event)
+ = 0;
+ virtual FunctionResult handleMouseDown(ITableControl& i_tableControl, MouseEvent const& i_event)
+ = 0;
+ virtual FunctionResult handleMouseUp(ITableControl& i_tableControl, MouseEvent const& i_event)
+ = 0;
+
+protected:
+ virtual ~MouseFunction() override {}
+};
+
+//= ColumnResize
+
+class ColumnResize final : public MouseFunction
+{
+public:
+ ColumnResize()
+ : m_nResizingColumn(COL_INVALID)
+ {
+ }
+
+public:
+ // MouseFunction
+ virtual FunctionResult handleMouseMove(ITableControl& i_tableControl,
+ MouseEvent const& i_event) override;
+ virtual FunctionResult handleMouseDown(ITableControl& i_tableControl,
+ MouseEvent const& i_event) override;
+ virtual FunctionResult handleMouseUp(ITableControl& i_tableControl,
+ MouseEvent const& i_event) override;
+
+private:
+ ColPos m_nResizingColumn;
+};
+
+//= RowSelection
+
+class RowSelection final : public MouseFunction
+{
+public:
+ RowSelection()
+ : m_bActive(false)
+ {
+ }
+
+public:
+ // MouseFunction
+ virtual FunctionResult handleMouseMove(ITableControl& i_tableControl,
+ MouseEvent const& i_event) override;
+ virtual FunctionResult handleMouseDown(ITableControl& i_tableControl,
+ MouseEvent const& i_event) override;
+ virtual FunctionResult handleMouseUp(ITableControl& i_tableControl,
+ MouseEvent const& i_event) override;
+
+private:
+ bool m_bActive;
+};
+
+//= ColumnSortHandler
+
+class ColumnSortHandler final : public MouseFunction
+{
+public:
+ ColumnSortHandler()
+ : m_nActiveColumn(COL_INVALID)
+ {
+ }
+
+public:
+ // MouseFunction
+ virtual FunctionResult handleMouseMove(ITableControl& i_tableControl,
+ MouseEvent const& i_event) override;
+ virtual FunctionResult handleMouseDown(ITableControl& i_tableControl,
+ MouseEvent const& i_event) override;
+ virtual FunctionResult handleMouseUp(ITableControl& i_tableControl,
+ MouseEvent const& i_event) override;
+
+private:
+ ColPos m_nActiveColumn;
+};
+
+} // namespace svt::table
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/table/tablecontrol.hxx b/toolkit/inc/controls/table/tablecontrol.hxx
new file mode 100644
index 0000000000..9d9f98ff11
--- /dev/null
+++ b/toolkit/inc/controls/table/tablecontrol.hxx
@@ -0,0 +1,174 @@
+/* -*- 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 <vcl/accessibletable.hxx>
+
+#include <vcl/ctrl.hxx>
+#include <vcl/seleng.hxx>
+
+#include <memory>
+
+namespace svt::table
+{
+ class TableControl_Impl;
+
+
+ //= TableControl
+
+ /** a basic control which manages table-like data, i.e. a number of cells
+ organized in <code>m</code> rows and <code>n</code> columns.
+
+ The control itself does not do any assumptions about the concrete data
+ it displays, this is encapsulated in an instance supporting the
+ ->ITableModel interface.
+
+ Also, the control does not do any assumptions about how the model's
+ content is rendered. This is the responsibility of a component
+ supporting the ->ITableRenderer interface (the renderer is obtained from
+ the model).
+
+ The control supports the concept of a <em>current</em> (or <em>active</em>
+ cell).
+ The control supports accessibility, this is encapsulated in IAccessibleTable
+ */
+ class TableControl final : public Control, public vcl::table::IAccessibleTable
+ {
+ private:
+ std::shared_ptr<TableControl_Impl> m_pImpl;
+
+
+ public:
+ TableControl( vcl::Window* _pParent, WinBits _nStyle );
+ virtual ~TableControl() override;
+ virtual void dispose() override;
+
+ /// sets a new table model
+ void SetModel( const PTableModel& _pModel );
+ /// retrieves the current table model
+ PTableModel GetModel() const;
+
+ /** retrieves the current row
+
+ The current row is the one which contains the active cell.
+
+ @return
+ the row index of the active cell, or ->ROW_INVALID
+ if there is no active cell, e.g. because the table does
+ not contain any rows or columns.
+ */
+ sal_Int32 GetCurrentRow() const override;
+
+ ITableControl&
+ getTableControlInterface();
+
+ /** retrieves the current column
+
+ The current col is the one which contains the active cell.
+
+ @return
+ the column index of the active cell, or ->COL_INVALID
+ if there is no active cell, e.g. because the table does
+ not contain any rows or columns.
+ */
+ sal_Int32 GetCurrentColumn() const override;
+
+ /** activates the cell at the given position
+ */
+ void GoTo( ColPos _nColumnPos, RowPos _nRow);
+
+ virtual void Resize() override;
+ void Select();
+
+ /**after removing a row, updates the vector which contains the selected rows
+ if the row, which should be removed, is selected, it will be erased from the vector
+ */
+ SelectionEngine* getSelEngine();
+ vcl::Window& getDataWindow();
+
+ // Window overridables
+ virtual void GetFocus() override;
+ virtual void LoseFocus() override;
+ virtual void KeyInput( const KeyEvent& rKEvt ) override;
+ virtual void StateChanged( StateChangedType i_nStateChange ) override;
+
+ /** Creates and returns the accessible object of the whole GridControl. */
+ virtual css::uno::Reference< css::accessibility::XAccessible > CreateAccessible() override;
+ virtual css::uno::Reference< css::accessibility::XAccessible > CreateAccessibleControl( sal_Int32 _nIndex ) override;
+ virtual OUString GetAccessibleObjectName(vcl::table::AccessibleTableControlObjType eObjType, sal_Int32 _nRow, sal_Int32 _nCol) const override;
+ virtual void GoToCell( sal_Int32 _nColumnPos, sal_Int32 _nRow ) override;
+ virtual OUString GetAccessibleObjectDescription(vcl::table::AccessibleTableControlObjType eObjType) const override;
+ virtual void FillAccessibleStateSet( sal_Int64& rStateSet, vcl::table::AccessibleTableControlObjType eObjType ) const override;
+
+ // temporary methods
+ // Those do not really belong into the public API - they're intended for firing A11Y-related events. However,
+ // firing those events should be an implementation internal to the TableControl resp. TableControl_Impl,
+ // instead of something triggered externally.
+ void commitCellEventIfAccessibleAlive( sal_Int16 const i_eventID, const css::uno::Any& i_newValue, const css::uno::Any& i_oldValue );
+ void commitTableEventIfAccessibleAlive( sal_Int16 const i_eventID, const css::uno::Any& i_newValue, const css::uno::Any& i_oldValue );
+
+
+ // IAccessibleTable
+ virtual AbsoluteScreenPixelRectangle GetWindowExtentsAbsolute() const override;
+ virtual tools::Rectangle GetWindowExtentsRelative(const vcl::Window& rRelativeWindow) const override;
+ virtual void GrabFocus() override;
+ virtual css::uno::Reference< css::accessibility::XAccessible > GetAccessible() override;
+ virtual vcl::Window* GetAccessibleParentWindow() const override;
+ virtual vcl::Window* GetWindowInstance() override;
+ virtual sal_Int32 GetAccessibleControlCount() const override;
+ virtual bool ConvertPointToControlIndex( sal_Int32& _rnIndex, const Point& _rPoint ) override;
+ virtual sal_Int32 GetRowCount() const override;
+ virtual sal_Int32 GetColumnCount() const override;
+ virtual bool ConvertPointToCellAddress( sal_Int32& _rnRow, sal_Int32& _rnColPos, const Point& _rPoint ) override;
+ virtual tools::Rectangle calcHeaderRect( bool _bIsColumnBar ) override;
+ virtual tools::Rectangle calcHeaderCellRect( bool _bIsColumnBar, sal_Int32 nPos) override;
+ virtual tools::Rectangle calcTableRect() override;
+ virtual tools::Rectangle calcCellRect( sal_Int32 _nRowPos, sal_Int32 _nColPos ) override;
+ virtual tools::Rectangle GetFieldCharacterBounds(sal_Int32 _nRow,sal_Int32 _nColumnPos,sal_Int32 nIndex) override;
+ virtual sal_Int32 GetFieldIndexAtPoint(sal_Int32 _nRow,sal_Int32 _nColumnPos,const Point& _rPoint) override;
+ virtual void FillAccessibleStateSetForCell( sal_Int64& _rStateSet, sal_Int32 _nRow, sal_uInt16 _nColumnPos ) const override;
+ virtual OUString GetRowName(sal_Int32 _nIndex) const override;
+ virtual OUString GetColumnName( sal_Int32 _nIndex ) const override;
+ virtual bool HasRowHeader() override;
+ virtual bool HasColHeader() override;
+ virtual OUString GetAccessibleCellText(sal_Int32 _nRowPos, sal_Int32 _nColPos) const override;
+
+ virtual sal_Int32 GetSelectedRowCount() const override;
+ virtual sal_Int32 GetSelectedRowIndex( sal_Int32 const i_selectionIndex ) const override;
+ virtual bool IsRowSelected( sal_Int32 const i_rowIndex ) const override;
+ virtual void SelectRow( sal_Int32 const i_rowIndex, bool const i_select ) override;
+ virtual void SelectAllRows( bool const i_select ) override;
+
+
+ private:
+ DECL_LINK( ImplSelectHdl, LinkParamNone*, void );
+
+ private:
+ TableControl( const TableControl& ) = delete;
+ TableControl& operator=( const TableControl& ) = delete;
+ };
+
+
+} // namespace svt::table
+
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/table/tablecontrolinterface.hxx b/toolkit/inc/controls/table/tablecontrolinterface.hxx
new file mode 100644
index 0000000000..8f5dca6763
--- /dev/null
+++ b/toolkit/inc/controls/table/tablecontrolinterface.hxx
@@ -0,0 +1,234 @@
+/* -*- 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 <sal/types.h>
+#include <vcl/seleng.hxx>
+#include <vcl/window.hxx>
+
+#include <controls/table/tabletypes.hxx>
+#include <controls/table/tablemodel.hxx>
+
+namespace svt::table
+{
+ //= TableControlAction
+ enum TableControlAction
+ {
+ /// moves the cursor in the table control one row up, if possible, by keeping the current column
+ cursorUp,
+ /// moves the cursor in the table control one row down, if possible, by keeping the current column
+ cursorDown,
+ /// moves the cursor in the table control one column to the left, if possible, by keeping the current row
+ cursorLeft,
+ /// moves the cursor in the table control one column to the right, if possible, by keeping the current row
+ cursorRight,
+ /// moves the cursor to the beginning of the current line
+ cursorToLineStart,
+ /// moves the cursor to the end of the current line
+ cursorToLineEnd,
+ /// moves the cursor to the first row, keeping the current column
+ cursorToFirstLine,
+ /// moves the cursor to the last row, keeping the current column
+ cursorToLastLine,
+ /// moves the cursor one page up, keeping the current column
+ cursorPageUp,
+ /// moves the cursor one page down, keeping the current column
+ cursorPageDown,
+ /// moves the cursor to the top-most, left-most cell
+ cursorTopLeft,
+ /// moves the cursor to the bottom-most, right-most cell
+ cursorBottomRight,
+ /// selects the row, where the actual cursor is
+ cursorSelectRow,
+ /// selects the rows, above the actual cursor is
+ cursorSelectRowUp,
+ /// selects the row, beneath the actual cursor is
+ cursorSelectRowDown,
+ /// selects the row, from the actual cursor till top
+ cursorSelectRowAreaTop,
+ /// selects the row, from the actual cursor till bottom
+ cursorSelectRowAreaBottom
+ };
+
+
+ //= TableCellArea
+
+ enum TableCellArea
+ {
+ CellContent,
+ ColumnDivider
+ };
+
+
+ //= TableCell
+
+ struct TableCell
+ {
+ ColPos nColumn;
+ RowPos nRow;
+ TableCellArea eArea;
+
+ TableCell( ColPos const i_column, RowPos const i_row )
+ :nColumn( i_column )
+ ,nRow( i_row )
+ ,eArea( CellContent )
+ {
+ }
+ };
+
+
+ //= ColumnMetrics
+
+ struct ColumnMetrics
+ {
+ /** the start of the column, in pixels. Might be negative, in case the column is scrolled out of the visible
+ area. Note: see below.
+ */
+ tools::Long nStartPixel;
+
+ /** the end of the column, in pixels, plus 1. Effectively, this is the accumulated width of all columns
+ up to the current one.
+
+ Huh? Earlier you said that the nStartPixel of columns
+ scrolled out (to the left) of the visible area is
+ negative. Also, where is the promise that there is no gap
+ between columns? The above claim would be true only if the
+ first column always started at zero, and there is never a
+ gap. So these doc comments are inconsistent. How
+ surprising.
+ */
+ tools::Long nEndPixel;
+
+ ColumnMetrics()
+ :nStartPixel(0)
+ ,nEndPixel(0)
+ {
+ }
+
+ ColumnMetrics( tools::Long const i_start, tools::Long const i_end )
+ :nStartPixel( i_start )
+ ,nEndPixel( i_end )
+ {
+ }
+ };
+
+
+ //= TableArea
+
+ enum class TableArea
+ {
+ ColumnHeaders,
+ RowHeaders,
+ All
+ };
+
+
+ //= ITableControl
+
+ /** defines a callback interface to be implemented by a concrete table control
+ */
+ class SAL_NO_VTABLE ITableControl
+ {
+ public:
+ /** hides the cell cursor
+
+ The method cares for successive calls, that is, for every call to
+ ->hideCursor(), you need one call to ->showCursor. Only if the number
+ of both calls matches, the cursor is really shown.
+
+ @see showCursor
+ */
+ virtual void hideCursor() = 0;
+
+ /** shows the cell cursor
+
+ @see hideCursor
+ */
+ virtual void showCursor() = 0;
+
+ /** dispatches an action to the table control
+
+ @return
+ <TRUE/> if the action could be dispatched successfully, <FALSE/> otherwise. Usual
+ failure conditions include some other instance vetoing the action, or impossibility
+ to execute the action at all (for instance moving up one row when already positioned
+ on the very first row).
+
+ @see TableControlAction
+ */
+ virtual bool dispatchAction( TableControlAction _eAction ) = 0;
+
+ /** returns selection engine*/
+ virtual SelectionEngine* getSelEngine() = 0;
+
+ /** returns the table model
+
+ The returned model is guaranteed to not be <NULL/>.
+ */
+ virtual PTableModel getModel() const = 0;
+
+ /// returns the index of the currently active column
+ virtual ColPos getCurrentColumn() const = 0;
+
+ /// returns the index of the currently active row
+ virtual RowPos getCurrentRow() const = 0;
+
+ /// activates the given cell
+ virtual void activateCell( ColPos const i_col, RowPos const i_row ) = 0;
+
+ /// retrieves the size of the table window, in pixels
+ virtual ::Size getTableSizePixel() const = 0;
+
+ /// sets a new mouse pointer for the table window
+ virtual void setPointer( PointerStyle i_pointer ) = 0;
+
+ /// captures the mouse to the table window
+ virtual void captureMouse() = 0;
+
+ /// releases the mouse, after it had previously been captured
+ virtual void releaseMouse() = 0;
+
+ /// invalidates the table window
+ virtual void invalidate( TableArea const i_what ) = 0;
+
+ /// calculates a width, given in pixels, into an AppFont-based width
+ virtual tools::Long pixelWidthToAppFont( tools::Long const i_pixels ) const = 0;
+
+ /// shows a tracking rectangle
+ virtual void showTracking( tools::Rectangle const & i_location, ShowTrackFlags const i_flags ) = 0;
+
+ /// hides a previously shown tracking rectangle
+ virtual void hideTracking() = 0;
+
+ /// does a hit test for the given pixel coordinates
+ virtual TableCell hitTest( const Point& rPoint ) const = 0;
+
+ /// retrieves the metrics for a given column
+ virtual ColumnMetrics getColumnMetrics( ColPos const i_column ) const = 0;
+
+ /// determines whether a given row is selected
+ virtual bool isRowSelected( RowPos _nRow ) const = 0;
+
+ virtual ~ITableControl() {};
+ };
+
+} // namespace svt::table
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/table/tableinputhandler.hxx b/toolkit/inc/controls/table/tableinputhandler.hxx
new file mode 100644
index 0000000000..9d11df38db
--- /dev/null
+++ b/toolkit/inc/controls/table/tableinputhandler.hxx
@@ -0,0 +1,63 @@
+/* -*- 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 <memory>
+
+class MouseEvent;
+class KeyEvent;
+
+
+namespace svt::table
+{
+
+
+ class ITableControl;
+
+
+ //= ITableInputHandler
+
+ /** interface for components handling input in a ->TableControl
+ */
+ class ITableInputHandler
+ {
+ public:
+ // all those methods have the same semantics as the equal-named methods of ->Window,
+ // with the additional option to return a boolean value indicating whether
+ // the event should be further processed by the ->Window implementations (<FALSE/>),
+ // or whether it has been sufficiently handled by the ->ITableInputHandler instance
+ // (<FALSE/>).
+
+ virtual bool MouseMove ( ITableControl& _rControl, const MouseEvent& rMEvt ) = 0;
+ virtual bool MouseButtonDown ( ITableControl& _rControl, const MouseEvent& rMEvt ) = 0;
+ virtual bool MouseButtonUp ( ITableControl& _rControl, const MouseEvent& rMEvt ) = 0;
+ virtual bool KeyInput ( ITableControl& _rControl, const KeyEvent& rKEvt ) = 0;
+ virtual bool GetFocus ( ITableControl& _rControl ) = 0;
+ virtual bool LoseFocus ( ITableControl& _rControl ) = 0;
+
+ virtual ~ITableInputHandler() { }
+ };
+ typedef std::shared_ptr< ITableInputHandler > PTableInputHandler;
+
+
+} // namespace svt::table
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/table/tablemodel.hxx b/toolkit/inc/controls/table/tablemodel.hxx
new file mode 100644
index 0000000000..7add49629a
--- /dev/null
+++ b/toolkit/inc/controls/table/tablemodel.hxx
@@ -0,0 +1,454 @@
+/* -*- 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 <toolkit/dllapi.h>
+#include <controls/table/tabletypes.hxx>
+#include <controls/table/tablerenderer.hxx>
+#include <controls/table/tableinputhandler.hxx>
+
+#include <com/sun/star/style/VerticalAlignment.hpp>
+#include <com/sun/star/style/HorizontalAlignment.hpp>
+
+#include <sal/types.h>
+
+#include <optional>
+#include <memory>
+#include <vector>
+#include <o3tl/typed_flags_set.hxx>
+
+namespace svt::table { class ITableDataSort; }
+
+class Color;
+
+enum class ColumnAttributeGroup
+{
+ NONE = 0x00,
+ /// denotes column attributes related to the width of the column
+ WIDTH = 0x01,
+ /// denotes column attributes related to the appearance of the column, i.e. those relevant for rendering
+ APPEARANCE = 0x02,
+ /// denotes the entirety of column attributes
+ ALL = 0x03,
+};
+namespace o3tl
+{
+ template<> struct typed_flags<ColumnAttributeGroup> : is_typed_flags<ColumnAttributeGroup, 0x03> {};
+}
+
+
+namespace svt::table
+{
+ //= ScrollbarVisibility
+ enum ScrollbarVisibility
+ {
+ /** enumeration value denoting that a scrollbar should never be visible, even
+ if needed normally
+ */
+ ScrollbarShowNever,
+ /** enumeration value denoting that a scrollbar should be visible when needed only
+ */
+ ScrollbarShowSmart,
+ /** enumeration value denoting that a scrollbar should always be visible, even
+ if not needed normally
+ */
+ ScrollbarShowAlways
+ };
+
+
+ //= ITableModelListener
+
+ /** declares an interface to be implemented by components interested in
+ changes in an ->ITableModel
+ */
+ class SAL_NO_VTABLE ITableModelListener : public std::enable_shared_from_this< ITableModelListener >
+ {
+ public:
+ /** notifies the listener that one or more rows have been inserted into
+ the table
+
+ @param first
+ the index of the first newly inserted row
+ @param last
+ the index of the last newly inserted row. Must not be smaller
+ than ->first
+ */
+ virtual void rowsInserted( RowPos first, RowPos last ) = 0;
+
+ /** notifies the listener that one or more rows have been removed from
+ the table
+
+ @param first
+ the old index of the first removed row. If this is <code>-1</code>, then all
+ rows have been removed from the model.
+ @param last
+ the old index of the last removed row. Must not be smaller
+ than ->first
+ */
+ virtual void rowsRemoved( RowPos first, RowPos last ) = 0;
+
+ /** notifies the listener that one or more columns have been inserted into
+ the table
+ */
+ virtual void columnInserted() = 0;
+
+ /** notifies the listener that one or more columns have been removed from
+ the table
+ */
+ virtual void columnRemoved() = 0;
+
+ /** notifies the listener that all columns have been removed from the model
+ */
+ virtual void allColumnsRemoved() = 0;
+
+ /** notifies the listener that a rectangular cell range in the table
+ has been updated
+
+ Listeners are required to discard any possibly cached information
+ they have about the cells in question, in particular any possibly
+ cached cell values.
+ */
+ virtual void cellsUpdated( RowPos const i_firstRow, RowPos const i_lastRow ) = 0;
+
+ /** notifies the listener that attributes of a given column changed
+
+ @param i_column
+ the position of the column whose attributes changed
+ @param i_attributeGroup
+ a combination of one or more <code>COL_ATTRS_*</code> flags, denoting the attribute group(s)
+ in which changes occurred.
+ */
+ virtual void columnChanged( ColPos const i_column, ColumnAttributeGroup const i_attributeGroup ) = 0;
+
+ /** notifies the listener that the metrics of the table changed.
+
+ Metrics here include the column header height, the row header width, the row height, and the presence
+ of both the row and column header.
+ */
+ virtual void tableMetricsChanged() = 0;
+
+ /// deletes the listener instance
+ virtual ~ITableModelListener(){};
+ };
+ typedef std::shared_ptr< ITableModelListener > PTableModelListener;
+
+
+ //= IColumnModel
+
+ /** interface to be implemented by table column models
+ */
+ class SAL_NO_VTABLE IColumnModel
+ {
+ public:
+ /** returns the name of the column
+
+ Column names should be human-readable, but not necessarily unique
+ within a given table.
+
+ @see setName
+ */
+ virtual OUString getName() const = 0;
+
+ /** retrieves the help text to be displayed for the column.
+ */
+ virtual OUString getHelpText() const = 0;
+
+ /** determines whether the column can be interactively resized
+
+ @see getMinWidth
+ @see getMaxWidth
+ @see getWidth
+ */
+ virtual bool isResizable() const = 0;
+
+ /** denotes the relative flexibility of the column
+
+ This flexibility is taken into account when a table control auto-resizes its columns, because the available
+ space changed. In this case, the columns grow or shrink according to their flexibility.
+
+ A value of 0 means the column is not auto-resized at all.
+ */
+ virtual sal_Int32 getFlexibility() const = 0;
+
+ /** returns the width of the column, in app-font units
+
+ The returned value must be a positive ->TableMetrics value.
+
+ @see setWidth
+ @see getMinWidth
+ @see getMaxWidth
+ */
+ virtual TableMetrics getWidth() const = 0;
+
+ /** sets a new width for the column
+
+ @param _nWidth
+ the new width, app-font units
+
+ @see getWidth
+ */
+ virtual void setWidth( TableMetrics _nWidth ) = 0;
+
+ /** returns the minimum width of the column, in app-font units, or 0 if the column
+ does not have a minimal width
+
+ @see setMinWidth
+ @see getMaxWidth
+ @see getWidth
+ */
+ virtual TableMetrics getMinWidth() const = 0;
+
+ /** returns the maximum width of the column, in app-font units, or 0 if the column
+ does not have a minimal width
+
+ @see setMaxWidth
+ @see getMinWidth
+ @see getWidth
+ */
+ virtual TableMetrics getMaxWidth() const = 0;
+
+ /** retrieves the horizontal alignment to be used for content in this cell
+ */
+ virtual css::style::HorizontalAlignment getHorizontalAlign() = 0;
+
+ /// deletes the column model instance
+ virtual ~IColumnModel() { }
+ };
+ typedef std::shared_ptr< IColumnModel > PColumnModel;
+
+
+ //= ITableModel
+
+ /** declares the interface to implement by an abstract table model
+ */
+ class SAL_NO_VTABLE TOOLKIT_DLLPUBLIC ITableModel
+ {
+ public:
+ /** returns the number of columns in the table
+ */
+ virtual TableSize getColumnCount() const = 0;
+
+ /** returns the number of rows in the table
+ */
+ virtual TableSize getRowCount() const = 0;
+
+ /** determines whether the table has column headers
+
+ If this method returns <TRUE/>, the renderer returned by
+ ->getRenderer must be able to render column headers.
+
+ @see IColumnRenderer
+ */
+ virtual bool hasColumnHeaders() const = 0;
+
+ /** determines whether the table has row headers
+
+ If this method returns <TRUE/>, the renderer returned by
+ ->getRenderer must be able to render row headers.
+
+ @see IColumnRenderer
+ */
+ virtual bool hasRowHeaders() const = 0;
+
+ /** returns a model for a certain column
+
+ @param column
+ the index of the column in question. Must be greater than or
+ equal 0, and smaller than the return value of ->getColumnCount()
+
+ @return
+ the model of the column in question. Must not be <NULL/>
+ */
+ virtual PColumnModel getColumnModel( ColPos column ) = 0;
+
+ /** returns a renderer which is able to paint the table represented
+ by this table model
+
+ @return the renderer to use. Must not be <NULL/>
+ */
+ virtual PTableRenderer getRenderer() const = 0;
+
+ /** returns the component handling input in a view associated with the model
+ */
+ virtual PTableInputHandler getInputHandler() const = 0;
+
+ /** determines the height of rows in the table.
+
+ @return
+ the logical height of rows in the table, in app-font units. The height must be
+ greater 0.
+ */
+ virtual TableMetrics getRowHeight() const = 0;
+
+ /** determines the height of the column header row
+
+ This method is not to be called if ->hasColumnHeaders()
+ returned <FALSE/>.
+
+ @return
+ the logical height of the column header row, in app-font units.
+ Must be greater than 0.
+ */
+ virtual TableMetrics getColumnHeaderHeight() const = 0;
+
+ /** determines the width of the row header column
+
+ This method is not to be called if ->hasRowHeaders()
+ returned <FALSE/>.
+
+ @return
+ the logical width of the row header column, in app-font units.
+ Must be greater than 0.
+ */
+ virtual TableMetrics getRowHeaderWidth() const = 0;
+
+ /** returns the visibility mode of the vertical scrollbar
+ */
+ virtual ScrollbarVisibility getVerticalScrollbarVisibility() const = 0;
+
+ /** returns the visibility mode of the horizontal scrollbar
+ */
+ virtual ScrollbarVisibility getHorizontalScrollbarVisibility() const = 0;
+
+ /** adds a listener to be notified of changes in the table model
+ */
+ virtual void addTableModelListener( const PTableModelListener& i_listener ) = 0;
+
+ /** remove a listener to be notified of changes in the table model
+ */
+ virtual void removeTableModelListener( const PTableModelListener& i_listener ) = 0;
+
+ /** retrieves the content of the given cell
+ */
+ virtual void getCellContent( ColPos const i_col, RowPos const i_row, css::uno::Any& o_cellContent ) = 0;
+
+ /** returns an object which should be displayed as tooltip for the given cell
+
+ At the moment, only string-convertible values are supported here. In the future, one might imagine displaying
+ scaled-down versions of a graphic in a cell, and a larger version of that very graphic as tooltip.
+
+ If no tooltip object is provided, then the cell content is used, and displayed as tooltip for the cell
+ if and only if it doesn't fit into the cell's space itself.
+
+ @param i_col
+ The column index of the cell in question. COL_ROW_HEADERS is a valid argument here.
+ @param i_row
+ The row index of the cell in question.
+ @param o_cellToolTip
+ takes the tooltip object upon return.
+ */
+ virtual void getCellToolTip( ColPos const i_col, RowPos const i_row, css::uno::Any & o_cellToolTip ) = 0;
+
+ /** retrieves title of a given row
+ */
+ virtual css::uno::Any getRowHeading( RowPos const i_rowPos ) const = 0;
+
+ /** returns the color to be used for rendering the grid lines.
+
+ If this value is not set, a default color from the style settings will be used.
+ */
+ virtual ::std::optional< ::Color > getLineColor() const = 0;
+
+ /** returns the color to be used for rendering the header background.
+
+ If this value is not set, a default color from the style settings will be used.
+ */
+ virtual ::std::optional< ::Color > getHeaderBackgroundColor() const = 0;
+
+ /** returns the color to be used for rendering the header text.
+
+ If this value is not set, a default color from the style settings will be used.
+ */
+ virtual ::std::optional< ::Color > getHeaderTextColor() const = 0;
+
+ /** returns the color to be used for the background of selected cells, when the control has the focus
+
+ If this value is not set, a default color from the style settings will be used.
+ */
+ virtual ::std::optional< ::Color > getActiveSelectionBackColor() const = 0;
+
+ /** returns the color to be used for the background of selected cells, when the control does not have the focus
+
+ If this value is not set, a default color from the style settings will be used.
+ */
+ virtual ::std::optional< ::Color > getInactiveSelectionBackColor() const = 0;
+
+ /** returns the color to be used for the text of selected cells, when the control has the focus
+
+ If this value is not set, a default color from the style settings will be used.
+ */
+ virtual ::std::optional< ::Color > getActiveSelectionTextColor() const = 0;
+
+ /** returns the color to be used for the text of selected cells, when the control does not have the focus
+
+ If this value is not set, a default color from the style settings will be used.
+ */
+ virtual ::std::optional< ::Color > getInactiveSelectionTextColor() const = 0;
+
+ /** returns the color to be used for rendering cell texts.
+
+ If this value is not set, a default color from the style settings will be used.
+ */
+ virtual ::std::optional< ::Color > getTextColor() const = 0;
+
+ /** returns the color to be used for text lines (underline, strikethrough) when rendering cell text.
+
+ If this value is not set, a default color from the style settings will be used.
+ */
+ virtual ::std::optional< ::Color > getTextLineColor() const = 0;
+
+ /** returns the colors to be used for the row backgrounds.
+
+ If this value is not set, every second row will have a background color derived from the style settings's
+ selection color, the other rows will not have a special background at all.
+
+ If this value is an empty sequence, the rows will not have a special background at all, instead the
+ normal background of the complete control will be used.
+
+ If value is a non-empty sequence, then rows will have the background colors as specified in the sequence,
+ in alternating order.
+ */
+ virtual ::std::optional< ::std::vector< ::Color > >
+ getRowBackgroundColors() const = 0;
+
+ /** determines the vertical alignment of content within a cell
+ */
+ virtual css::style::VerticalAlignment getVerticalAlign() const = 0;
+
+ /** returns an adapter to the sorting functionality of the model
+
+ It is legitimate to return <NULL/> here, in this case, the table model does not support sorting.
+ */
+ virtual ITableDataSort* getSortAdapter() = 0;
+
+ /** returns enabled state.
+ */
+ virtual bool isEnabled() const = 0;
+
+ /// destroys the table model instance
+ virtual ~ITableModel() { }
+ };
+ typedef std::shared_ptr< ITableModel > PTableModel;
+
+
+} // namespace svt::table
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/table/tablerenderer.hxx b/toolkit/inc/controls/table/tablerenderer.hxx
new file mode 100644
index 0000000000..a4d7a48a62
--- /dev/null
+++ b/toolkit/inc/controls/table/tablerenderer.hxx
@@ -0,0 +1,249 @@
+/* -*- 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 <rtl/ustring.hxx>
+
+#include <memory>
+
+namespace com :: sun :: star :: uno { class Any; }
+namespace tools { class Rectangle; }
+namespace vcl { class Window; }
+
+class OutputDevice;
+class StyleSettings;
+namespace vcl {
+ typedef OutputDevice RenderContext;
+};
+
+
+namespace svt::table
+{
+
+
+ //= ITableRenderer
+
+ /** interface to implement by components rendering a ->TableControl
+ */
+ class SAL_NO_VTABLE ITableRenderer
+ {
+ public:
+
+ /** paints a (part of) header area
+
+ There are two header areas in a table control:
+ <ul><li>The row containing all column headers, i.e. <em>above</em> all rows containing the data</li>
+ <li>The column containing all row headers. i.e. <em>left of</em> all columns containing the data</li>
+ </ul>
+
+ A header area is more than the union of the single column/row headers.
+
+ First, there might be less columns than fit into the view - in this case, right
+ beside the right-most column, there's still room which belongs to the column header
+ area, but is not occupied by any particular column header.<br/>
+ An equivalent statement holds for the row header area, if there are fewer rows than
+ fit into the view.
+
+ Second, if the table control has both a row header and a column header,
+ the intersection between those both belongs to both the column header area and the
+ row header area, but not to any particular column or row header.
+
+ There are two flags specifying whether the to-be-painted area is part of the column
+ and/or row header area.
+ <ul><li>If both are <TRUE/>, the intersection of both areas is to be painted.</li>
+ <li>If ->_bIsColHeaderArea is <TRUE/> and ->_bIsRowHeaderArea is <FALSE/>,
+ then ->_rArea denotes the column header area <em>excluding</em> the
+ intersection between row and column header area.</li>
+ <li>Equivalently for ->_bIsColHeaderArea being <FALSE/> and ->_bIsRowHeaderArea
+ being <TRUE/></li>
+ </ul>
+ Note that it's not possible for both ->_bIsColHeaderArea and ->_bIsRowHeaderArea
+ to be <FALSE/> at the same time.
+
+ @param _rDevice
+ the device to paint onto
+ @param _rArea
+ the area to paint into
+ @param _bIsColHeaderArea
+ <TRUE/> if and only if ->_rArea is part of the column header area.
+ @param _bIsRowHeaderArea
+ <TRUE/> if and only if ->_rArea is part of the row header area.
+ @param _rStyle
+ the style to be used for drawing
+ */
+ virtual void PaintHeaderArea(
+ vcl::RenderContext& _rDevice, const tools::Rectangle& _rArea,
+ bool _bIsColHeaderArea, bool _bIsRowHeaderArea,
+ const StyleSettings& _rStyle ) = 0;
+
+ /** paints the header for a given column
+
+ @param _nCol
+ the index of the column to paint
+ @param _rDevice
+ denotes the device to paint onto
+ @param _rArea
+ the are into which the column header should be painted
+ @param _rStyle
+ the style to be used for drawing
+ */
+ virtual void PaintColumnHeader( ColPos _nCol,
+ vcl::RenderContext& _rDevice, const tools::Rectangle& _rArea,
+ const StyleSettings& _rStyle ) = 0;
+
+ /** prepares a row for painting
+
+ Painting a table means painting rows as necessary, in an increasing
+ order. The assumption is that retrieving data for two different rows
+ is (potentially) more expensive than retrieving data for two different
+ columns. Thus, the renderer will get the chance to "seek" to a certain
+ row, and then has to render all cells in this row, before another
+ row is going to be painted.
+
+ @param _nRow
+ the row which is going to be painted. The renderer should
+ at least remember this row, since subsequent calls to
+ ->PaintRowHeader(), ->PaintCell(), and ->FinishRow() will
+ not pass this parameter again.
+
+ However, the renderer is also allowed to render any
+ cell-independent content of this row.
+
+ @param i_hasControlFocus
+ <TRUE/> if and only if the table control currently has the focus
+ @param _bSelected
+ <TRUE/> if and only if the row to be prepared is
+ selected currently.
+ @param _rDevice
+ denotes the device to paint onto
+ @param _rRowArea
+ the are into which the row should be painted. This excludes
+ the row header area, if applicable.
+ @param _rStyle
+ the style to be used for drawing
+ */
+ virtual void PrepareRow( RowPos _nRow, bool i_hasControlFocus, bool _bSelected,
+ vcl::RenderContext& _rDevice, const tools::Rectangle& _rRowArea,
+ const StyleSettings& _rStyle ) = 0;
+
+ /** paints the header of a row
+
+ The row to be painted is denoted by the most recent call to
+ ->PrepareRow.
+
+ @param _rDevice
+ denotes the device to paint onto
+ @param _rArea
+ the are into which the row header should be painted
+ @param _rStyle
+ the style to be used for drawing
+ */
+ virtual void PaintRowHeader(
+ vcl::RenderContext& _rDevice, tools::Rectangle const & _rArea,
+ StyleSettings const & _rStyle ) = 0;
+
+ /** paints a certain cell
+
+ The row to be painted is denoted by the most recent call to
+ ->PrepareRow.
+
+ @param _bSelected
+ <TRUE/> if and only if the cell to be painted is
+ selected currently. This is the case if either
+ the row or the column of the cell is currently selected.
+ <br/>
+ Note that this flag is equal to the respective flag in the
+ previous ->PrepareRow call, it's passed here for convenience
+ only.
+ @param i_hasControlFocus
+ <TRUE/> if and only if the table control currently has the focus
+ <br/>
+ Note that this flag is equal to the respective flag in the
+ previous ->PrepareRow call, it's passed here for convenience
+ only.
+ @param _rDevice
+ denotes the device to paint onto
+ @param _rArea
+ the are into which the cell should be painted
+ @param _rStyle
+ the style to be used for drawing
+ */
+ virtual void PaintCell( ColPos const i_col,
+ bool i_hasControlFocus, bool _bSelected,
+ vcl::RenderContext& _rDevice, const tools::Rectangle& _rArea,
+ const StyleSettings& _rStyle ) = 0;
+
+ /** draws a cell cursor in the given rectangle
+
+ The cell cursor is used to indicate the active/current cell
+ of a table control.
+ */
+ virtual void ShowCellCursor( vcl::Window& _rView, const tools::Rectangle& _rCursorRect) = 0;
+
+ /** hides the cell cursor previously drawn into the given rectangle
+
+ The cell cursor is used to indicate the active/current cell
+ of a table control.
+ */
+ virtual void HideCellCursor( vcl::Window& _rView ) = 0;
+
+ /** checks whether a given cell content fits into a given target area on a given device.
+
+ @param i_targetDevice
+ denotes the target device for the assumed rendering operation
+
+ @param i_targetArea
+ denotes the area within the target device for the assumed rendering operation.
+
+ @return
+ <TRUE/> if and only if the given cell content could be rendered into the given device and the
+ given area.
+ */
+ virtual bool FitsIntoCell(
+ css::uno::Any const & i_cellContent,
+ OutputDevice& i_targetDevice, tools::Rectangle const & i_targetArea
+ ) const = 0;
+
+ /** attempts to format the content of the given cell as string
+
+ @param i_cellValue
+ the value for which an attempt for a string conversion should be made
+ @param o_cellString
+ the cell content, formatted as string
+ @return
+ <TRUE/> if and only if the content could be formatted as string
+ */
+ virtual bool GetFormattedCellString(
+ css::uno::Any const & i_cellValue,
+ OUString & o_cellString
+ ) const = 0;
+
+ /// deletes the renderer instance
+ virtual ~ITableRenderer() { }
+ };
+ typedef std::shared_ptr< ITableRenderer > PTableRenderer;
+
+
+} // namespace svt::table
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/table/tablesort.hxx b/toolkit/inc/controls/table/tablesort.hxx
new file mode 100644
index 0000000000..691beea4ed
--- /dev/null
+++ b/toolkit/inc/controls/table/tablesort.hxx
@@ -0,0 +1,79 @@
+/* -*- 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>
+
+namespace svt::table
+{
+
+
+ //= ColumnSortDirection
+
+ enum ColumnSortDirection
+ {
+ ColumnSortAscending,
+ ColumnSortDescending
+ };
+
+
+ //= ColumnSort
+
+ struct ColumnSort
+ {
+ ColPos nColumnPos;
+ ColumnSortDirection eSortDirection;
+
+ ColumnSort()
+ :nColumnPos( COL_INVALID )
+ ,eSortDirection( ColumnSortAscending )
+ {
+ }
+
+ };
+
+
+ //= ITableDataSort
+
+ /** provides sorting functionality for the data underlying an ITableModel
+ */
+ class SAL_NO_VTABLE ITableDataSort
+ {
+ public:
+ /** sorts the rows in the model by the given column's data, in the given direction.
+ */
+ virtual void sortByColumn( ColPos const i_column, ColumnSortDirection const i_sortDirection ) = 0;
+
+ /** retrieves the current sort order of the data
+
+ If the <code>nColumnIndex</code> member of the returned structure is <code>COL_INVALID</code>, then
+ the data is currently not sorted.
+ */
+ virtual ColumnSort getCurrentSortOrder() const = 0;
+
+ protected:
+ ~ITableDataSort() {}
+ };
+
+
+} // namespace svt::table
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/table/tabletypes.hxx b/toolkit/inc/controls/table/tabletypes.hxx
new file mode 100644
index 0000000000..8fdb18a830
--- /dev/null
+++ b/toolkit/inc/controls/table/tabletypes.hxx
@@ -0,0 +1,52 @@
+/* -*- 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 <sal/types.h>
+
+
+namespace svt::table
+{
+
+ /// a value denoting the size of a table
+ typedef sal_Int32 TableSize;
+
+ /// a value denoting a column position within a table
+ typedef sal_Int32 ColPos;
+ /// a value denoting a row position within a table
+ typedef sal_Int32 RowPos;
+
+ typedef sal_Int32 TableMetrics;
+
+/// denotes the column containing the row headers
+#define COL_ROW_HEADERS (::svt::table::ColPos(-1))
+/// denotes the row containing the column headers
+#define ROW_COL_HEADERS (::svt::table::RowPos(-1))
+
+/// denotes an invalid column index
+#define COL_INVALID (::svt::table::ColPos(-2))
+/// denotes an invalid row index
+#define ROW_INVALID (::svt::table::RowPos(-2))
+
+
+} // namespace svt::table
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/tabpagecontainer.hxx b/toolkit/inc/controls/tabpagecontainer.hxx
new file mode 100644
index 0000000000..f9fe2df02d
--- /dev/null
+++ b/toolkit/inc/controls/tabpagecontainer.hxx
@@ -0,0 +1,127 @@
+/* -*- 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/awt/tab/XTabPageContainer.hpp>
+#include <com/sun/star/awt/tab/XTabPageContainerModel.hpp>
+#include <toolkit/controls/unocontrolbase.hxx>
+#include <toolkit/controls/unocontrolmodel.hxx>
+#include <cppuhelper/implbase1.hxx>
+#include <controls/controlmodelcontainerbase.hxx>
+#include <toolkit/helper/listenermultiplexer.hxx>
+
+
+namespace com::sun::star::awt::tab { class XTabPage; }
+namespace com::sun::star::awt::tab { class XTabPageContainerListener; }
+namespace com::sun::star::awt::tab { class XTabPageModel; }
+
+
+typedef ::cppu::AggImplInheritanceHelper1 < UnoControlModel
+ , css::awt::tab::XTabPageContainerModel
+ > UnoControlTabPageContainerModel_Base;
+class UnoControlTabPageContainerModel final : public UnoControlTabPageContainerModel_Base
+{
+private:
+ std::vector< css::uno::Reference< css::awt::tab::XTabPageModel > > m_aTabPageVector;
+ ContainerListenerMultiplexer maContainerListeners;
+
+ css::uno::Any ImplGetDefaultValue( sal_uInt16 nPropId ) const override;
+ ::cppu::IPropertyArrayHelper& getInfoHelper() override;
+ // css::beans::XMultiPropertySet
+ css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+
+public:
+ UnoControlTabPageContainerModel( const css::uno::Reference< css::uno::XComponentContext >& i_factory );
+ UnoControlTabPageContainerModel( const UnoControlTabPageContainerModel& rModel ) : UnoControlTabPageContainerModel_Base( rModel ),maContainerListeners( *this ) {}
+
+ rtl::Reference<UnoControlModel> Clone() const override { return new UnoControlTabPageContainerModel( *this ); }
+
+ // css::io::XPersistObject
+ OUString SAL_CALL getServiceName() override;
+
+ // css::lang::XServiceInfo
+ DECLIMPL_SERVICEINFO_DERIVED( UnoControlTabPageContainerModel, UnoControlModel, "com.sun.star.awt.tab.UnoControlTabPageContainerModel" )
+
+ // XTabPageContainerModel
+ virtual css::uno::Reference< css::awt::tab::XTabPageModel > SAL_CALL createTabPage( ::sal_Int16 TabPageID ) override;
+ virtual css::uno::Reference< css::awt::tab::XTabPageModel > SAL_CALL loadTabPage( ::sal_Int16 TabPageID, const OUString& ResourceURL ) override;
+
+ // XIndexContainer
+ virtual void SAL_CALL insertByIndex( sal_Int32 Index, const css::uno::Any& Element ) override;
+ virtual void SAL_CALL removeByIndex( sal_Int32 Index ) override;
+
+ // XIndexReplace
+ virtual void SAL_CALL replaceByIndex( sal_Int32 Index, const css::uno::Any& Element ) override;
+
+ // XIndexAccess
+ virtual sal_Int32 SAL_CALL getCount() override;
+
+ virtual css::uno::Any SAL_CALL getByIndex( sal_Int32 Index ) override;
+
+ // XElementAccess
+ virtual css::uno::Type SAL_CALL getElementType() override;
+ virtual sal_Bool SAL_CALL hasElements() override;
+
+ // css::container::XContainer
+ void SAL_CALL addContainerListener( const css::uno::Reference< css::container::XContainerListener >& xListener ) override;
+ void SAL_CALL removeContainerListener( const css::uno::Reference< css::container::XContainerListener >& xListener ) override;
+};
+
+// = UnoControlTabPageContainer
+
+typedef ::cppu::AggImplInheritanceHelper1 < ControlContainerBase
+ , css::awt::tab::XTabPageContainer
+ > UnoControlTabPageContainer_Base;
+class UnoControlTabPageContainer final : public UnoControlTabPageContainer_Base
+{
+public:
+ UnoControlTabPageContainer( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
+ 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::awt::tab::XTabPageContainer
+ virtual ::sal_Int16 SAL_CALL getActiveTabPageID() override;
+ virtual void SAL_CALL setActiveTabPageID( ::sal_Int16 _activetabpageid ) override;
+ virtual ::sal_Int16 SAL_CALL getTabPageCount( ) override;
+ virtual sal_Bool SAL_CALL isTabPageActive( ::sal_Int16 tabPageIndex ) override;
+ virtual css::uno::Reference< css::awt::tab::XTabPage > SAL_CALL getTabPage( ::sal_Int16 tabPageIndex ) override;
+ virtual css::uno::Reference< css::awt::tab::XTabPage > SAL_CALL getTabPageByID( ::sal_Int16 tabPageID ) override;
+ virtual void SAL_CALL addTabPageContainerListener( const css::uno::Reference< css::awt::tab::XTabPageContainerListener >& listener ) override;
+ virtual void SAL_CALL removeTabPageContainerListener( const css::uno::Reference< css::awt::tab::XTabPageContainerListener >& listener ) override;
+
+ // css::beans::XPropertiesChangeListener
+ virtual void SAL_CALL propertiesChange( const ::css::uno::Sequence< ::css::beans::PropertyChangeEvent >& aEvent ) override;
+
+ virtual void SAL_CALL addControl( const OUString& Name, const css::uno::Reference< css::awt::XControl >& Control ) override;
+ // css::lang::XServiceInfo
+ DECLIMPL_SERVICEINFO_DERIVED( UnoControlTabPageContainer, UnoControlBase, "com.sun.star.awt.tab.UnoControlTabPageContainer" )
+
+// using UnoControl::getPeer;
+private:
+ virtual void updateFromModel() override;
+ TabPageListenerMultiplexer m_aTabPageListeners;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/tabpagemodel.hxx b/toolkit/inc/controls/tabpagemodel.hxx
new file mode 100644
index 0000000000..a1668e2d5d
--- /dev/null
+++ b/toolkit/inc/controls/tabpagemodel.hxx
@@ -0,0 +1,79 @@
+/* -*- 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/controlmodelcontainerbase.hxx>
+#include <com/sun/star/awt/tab/XTabPage.hpp>
+#include <cppuhelper/implbase2.hxx>
+
+class UnoControlTabPageModel final : public ControlModelContainerBase
+{
+ css::uno::Any ImplGetDefaultValue( sal_uInt16 nPropId ) const override;
+ ::cppu::IPropertyArrayHelper& getInfoHelper() override;
+public:
+ UnoControlTabPageModel( css::uno::Reference< css::uno::XComponentContext > const & i_factory);
+
+ // css::io::XPersistObject
+ OUString SAL_CALL getServiceName() override;
+
+ // css::beans::XMultiPropertySet
+ css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+ // XInitialization
+ virtual void SAL_CALL initialize (const css::uno::Sequence<css::uno::Any>& rArguments) override;
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+
+ css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+};
+
+
+
+typedef ::cppu::AggImplInheritanceHelper2 < ControlContainerBase
+ , css::awt::tab::XTabPage
+ , css::awt::XWindowListener
+ > UnoControlTabPage_Base;
+class UnoControlTabPage final : public UnoControlTabPage_Base
+{
+private:
+ bool m_bWindowListener;
+public:
+
+ UnoControlTabPage( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
+ virtual ~UnoControlTabPage() override;
+ OUString GetComponentServiceName() const 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;
+
+ // css::awt::XWindowListener
+ virtual void SAL_CALL windowResized( const css::awt::WindowEvent& e ) override;
+ virtual void SAL_CALL windowMoved( const css::awt::WindowEvent& e ) override;
+ virtual void SAL_CALL windowShown( const css::lang::EventObject& e ) override;
+ virtual void SAL_CALL windowHidden( const css::lang::EventObject& e ) override;
+ // css::lang::XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+
+ virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override;
+
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/tkscrollbar.hxx b/toolkit/inc/controls/tkscrollbar.hxx
new file mode 100644
index 0000000000..c7948de072
--- /dev/null
+++ b/toolkit/inc/controls/tkscrollbar.hxx
@@ -0,0 +1,112 @@
+/* -*- 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 <toolkit/controls/unocontrolmodel.hxx>
+#include <toolkit/controls/unocontrolbase.hxx>
+#include <com/sun/star/awt/XScrollBar.hpp>
+#include <com/sun/star/awt/XAdjustmentListener.hpp>
+
+
+namespace toolkit
+{
+
+
+ //= UnoControlScrollBarModel
+
+ class UnoControlScrollBarModel final : public UnoControlModel
+ {
+ css::uno::Any ImplGetDefaultValue( sal_uInt16 nPropId ) const override;
+ ::cppu::IPropertyArrayHelper& getInfoHelper() override;
+
+ public:
+ UnoControlScrollBarModel( const css::uno::Reference< css::uno::XComponentContext >& i_factory );
+ UnoControlScrollBarModel( const UnoControlScrollBarModel& rModel ) : UnoControlModel( rModel ) {}
+
+ rtl::Reference<UnoControlModel> Clone() const override { return new UnoControlScrollBarModel( *this ); }
+
+ // 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;
+
+ css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+ };
+
+
+ //= UnoControlScrollBarModel
+
+ class UnoScrollBarControl final : public UnoControlBase,
+ public css::awt::XAdjustmentListener,
+ public css::awt::XScrollBar
+ {
+ private:
+ AdjustmentListenerMultiplexer maAdjustmentListeners;
+
+ public:
+ UnoScrollBarControl();
+ OUString GetComponentServiceName() const override;
+
+ css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override { return UnoControlBase::queryInterface(rType); }
+ css::uno::Any SAL_CALL queryAggregation( const css::uno::Type & rType ) override;
+ void SAL_CALL acquire() noexcept override { OWeakAggObject::acquire(); }
+ void SAL_CALL release() noexcept override { OWeakAggObject::release(); }
+ 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;
+
+ // css::lang::XTypeProvider
+ css::uno::Sequence< css::uno::Type > SAL_CALL getTypes() override;
+ css::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+
+ // css::awt::XAdjustmentListener
+ void SAL_CALL adjustmentValueChanged( const css::awt::AdjustmentEvent& rEvent ) override;
+
+ // css::awt::XScrollBar
+ void SAL_CALL addAdjustmentListener( const css::uno::Reference< css::awt::XAdjustmentListener >& l ) override;
+ void SAL_CALL removeAdjustmentListener( const css::uno::Reference< css::awt::XAdjustmentListener >& l ) override;
+ void SAL_CALL setValue( sal_Int32 n ) override;
+ void SAL_CALL setValues( sal_Int32 nValue, sal_Int32 nVisible, sal_Int32 nMax ) override;
+ sal_Int32 SAL_CALL getValue( ) override;
+ void SAL_CALL setMaximum( sal_Int32 n ) override;
+ sal_Int32 SAL_CALL getMaximum( ) override;
+ void SAL_CALL setLineIncrement( sal_Int32 n ) override;
+ sal_Int32 SAL_CALL getLineIncrement( ) override;
+ void SAL_CALL setBlockIncrement( sal_Int32 n ) override;
+ sal_Int32 SAL_CALL getBlockIncrement( ) override;
+ void SAL_CALL setVisibleSize( sal_Int32 n ) override;
+ sal_Int32 SAL_CALL getVisibleSize( ) override;
+ void SAL_CALL setOrientation( sal_Int32 n ) override;
+ sal_Int32 SAL_CALL getOrientation( ) override;
+
+ // css::lang::XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+
+ css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+ };
+
+
+} // namespacetoolkit
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/treecontrolpeer.hxx b/toolkit/inc/controls/treecontrolpeer.hxx
new file mode 100644
index 0000000000..d584516ae3
--- /dev/null
+++ b/toolkit/inc/controls/treecontrolpeer.hxx
@@ -0,0 +1,166 @@
+/* -*- 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/awt/tree/XTreeControl.hpp>
+#include <com/sun/star/awt/tree/XTreeDataModel.hpp>
+#include <com/sun/star/graphic/XGraphicProvider.hpp>
+
+#include <toolkit/awt/vclxwindow.hxx>
+#include <toolkit/helper/listenermultiplexer.hxx>
+
+#include <vcl/image.hxx>
+
+#include <cppuhelper/implbase.hxx>
+
+#include <map>
+
+namespace com::sun::star::awt::tree { class XTreeNode; }
+
+class UnoTreeListEntry;
+class TreeControlPeer;
+class UnoTreeListBoxImpl;
+
+class TreeControlPeer final : public ::cppu::ImplInheritanceHelper< VCLXWindow, css::awt::tree::XTreeControl, css::awt::tree::XTreeDataModelListener >
+{
+ typedef std::map<css::uno::Reference<css::awt::tree::XTreeNode>, UnoTreeListEntry*> TreeNodeMap;
+
+ friend class UnoTreeListBoxImpl;
+ friend class UnoTreeListEntry;
+public:
+ TreeControlPeer();
+ virtual ~TreeControlPeer() override;
+
+ vcl::Window* createVclControl( vcl::Window* pParent, sal_Int64 nWinStyle );
+
+ // 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::awt::tree::TreeDataModelListener
+ virtual void SAL_CALL treeNodesChanged( const css::awt::tree::TreeDataModelEvent& aEvent ) override;
+ virtual void SAL_CALL treeNodesInserted( const css::awt::tree::TreeDataModelEvent& aEvent ) override;
+ virtual void SAL_CALL treeNodesRemoved( const css::awt::tree::TreeDataModelEvent& aEvent ) override;
+ virtual void SAL_CALL treeStructureChanged( const css::awt::tree::TreeDataModelEvent& aEvent ) override;
+
+ // XEventListener
+ void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ // css::awt::XLayoutConstrains
+ css::awt::Size SAL_CALL getMinimumSize() override;
+ css::awt::Size SAL_CALL getPreferredSize() override;
+ css::awt::Size SAL_CALL calcAdjustedSize( const css::awt::Size& aNewSize ) override;
+
+ // 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;
+
+private:
+ /// @throws css::lang::IllegalArgumentException
+ UnoTreeListEntry* getEntry( const css::uno::Reference< css::awt::tree::XTreeNode >& xNode, bool bThrow = true );
+
+ void disposeControl();
+
+ bool onEditingEntry( UnoTreeListEntry const * pEntry );
+ bool onEditedEntry( UnoTreeListEntry const * pEntry, const OUString& rNewText );
+
+ void fillTree( UnoTreeListBoxImpl& rTree, const css::uno::Reference< css::awt::tree::XTreeDataModel >& xDataModel );
+ void addNode( UnoTreeListBoxImpl& rTree, const css::uno::Reference< css::awt::tree::XTreeNode >& xNode, UnoTreeListEntry* pParentEntry );
+
+ UnoTreeListEntry* createEntry( const css::uno::Reference< css::awt::tree::XTreeNode >& xNode, UnoTreeListEntry* pParent, sal_uLong nPos );
+ void updateEntry( UnoTreeListEntry* pEntry );
+
+ void updateTree( const css::awt::tree::TreeDataModelEvent& rEvent );
+ void updateNode( UnoTreeListBoxImpl const & rTree, const css::uno::Reference< css::awt::tree::XTreeNode >& xNode );
+ void updateChildNodes( UnoTreeListBoxImpl const & rTree, const css::uno::Reference< css::awt::tree::XTreeNode >& xParentNode, UnoTreeListEntry* pParentEntry );
+
+ static OUString getEntryString( const css::uno::Any& rValue );
+
+ /// @throws css::uno::RuntimeException
+ UnoTreeListBoxImpl& getTreeListBoxOrThrow() const;
+ /// @throws css::uno::RuntimeException
+ /// @throws css::lang::IllegalArgumentException
+ void ChangeNodesSelection( const css::uno::Any& rSelection, bool bSelect, bool bSetSelection );
+
+ void onChangeDataModel( UnoTreeListBoxImpl& rTree, const css::uno::Reference< css::awt::tree::XTreeDataModel >& xDataModel );
+
+ void onSelectionChanged();
+ void onRequestChildNodes( const css::uno::Reference< css::awt::tree::XTreeNode >& xNode );
+ bool onExpanding( const css::uno::Reference< css::awt::tree::XTreeNode >& xNode, bool bExpanding );
+ void onExpanded( const css::uno::Reference< css::awt::tree::XTreeNode >& xNode, bool bExpanding );
+
+ void onChangeRootDisplayed( bool bIsRootDisplayed );
+
+ void addEntry( UnoTreeListEntry* pEntry );
+ void removeEntry( UnoTreeListEntry const * pEntry );
+
+ bool loadImage( const OUString& rURL, Image& rImage );
+
+private:
+ css::uno::Reference< css::awt::tree::XTreeDataModel >mxDataModel;
+ TreeSelectionListenerMultiplexer maSelectionListeners;
+ TreeExpansionListenerMultiplexer maTreeExpansionListeners;
+ TreeEditListenerMultiplexer maTreeEditListeners;
+ bool mbIsRootDisplayed;
+ VclPtr<UnoTreeListBoxImpl> mpTreeImpl;
+ sal_Int32 mnEditLock;
+ OUString msDefaultCollapsedGraphicURL;
+ OUString msDefaultExpandedGraphicURL;
+ Image maDefaultExpandedImage;
+ Image maDefaultCollapsedImage;
+ std::unique_ptr<TreeNodeMap> mpTreeNodeMap;
+ css::uno::Reference< css::graphic::XGraphicProvider > mxGraphicProvider;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/unocontrolcontainer.hxx b/toolkit/inc/controls/unocontrolcontainer.hxx
new file mode 100644
index 0000000000..ac4e018160
--- /dev/null
+++ b/toolkit/inc/controls/unocontrolcontainer.hxx
@@ -0,0 +1,151 @@
+/* -*- 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/awt/XControlContainer.hpp>
+#include <com/sun/star/awt/XUnoControlContainer.hpp>
+#include <com/sun/star/container/XContainer.hpp>
+#include <com/sun/star/container/XIdentifierContainer.hpp>
+
+#include <toolkit/controls/unocontrolbase.hxx>
+
+#include <cppuhelper/implbase4.hxx>
+#include <memory>
+
+class UnoControlHolderList;
+
+
+
+typedef ::cppu::AggImplInheritanceHelper4 < UnoControlBase
+ , css::awt::XUnoControlContainer
+ , css::awt::XControlContainer
+ , css::container::XContainer
+ , css::container::XIdentifierContainer
+ > UnoControlContainer_Base;
+
+class UnoControlContainer : public UnoControlContainer_Base
+{
+private:
+ std::unique_ptr<UnoControlHolderList> mpControls;
+ css::uno::Sequence< css::uno::Reference< css::awt::XTabController > > maTabControllers;
+ ContainerListenerMultiplexer maCListeners;
+
+protected:
+ void ImplActivateTabControllers();
+
+public:
+ UnoControlContainer();
+ UnoControlContainer( const css::uno::Reference< css::awt::XVclWindowPeer >& xPeer );
+ virtual ~UnoControlContainer() override;
+
+
+ // css::lang::XComponent
+ void SAL_CALL dispose() override;
+
+ // css::lang::XEventListener
+ void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+
+ // css::container::XContainer
+ void SAL_CALL addContainerListener( const css::uno::Reference< css::container::XContainerListener >& xListener ) override;
+ void SAL_CALL removeContainerListener( const css::uno::Reference< css::container::XContainerListener >& xListener ) override;
+
+ // css::container::XIdentifierContainer
+ virtual ::sal_Int32 SAL_CALL insert( const css::uno::Any& aElement ) override;
+
+ // css::container::XIdentifierReplace
+ virtual void SAL_CALL removeByIdentifier( ::sal_Int32 Identifier ) override;
+ virtual void SAL_CALL replaceByIdentifer( ::sal_Int32 Identifier, const css::uno::Any& aElement ) override;
+
+ // css::container::XIdentifierAccess
+ virtual css::uno::Any SAL_CALL getByIdentifier( ::sal_Int32 Identifierr ) override;
+ virtual css::uno::Sequence< ::sal_Int32 > SAL_CALL getIdentifiers( ) override;
+
+ // css::container::XElementAccess
+ virtual css::uno::Type SAL_CALL getElementType( ) override;
+ virtual sal_Bool SAL_CALL hasElements( ) override;
+
+ // css::awt::XControlContainer
+ void SAL_CALL setStatusText( const OUString& StatusText ) override;
+ css::uno::Sequence< css::uno::Reference< css::awt::XControl > > SAL_CALL getControls( ) override;
+ css::uno::Reference< css::awt::XControl > SAL_CALL getControl( const OUString& aName ) override;
+ void SAL_CALL addControl( const OUString& Name, const css::uno::Reference< css::awt::XControl >& Control ) override;
+ void SAL_CALL removeControl( const css::uno::Reference< css::awt::XControl >& Control ) override;
+
+ // css::awt::XUnoControlContainer
+ void SAL_CALL setTabControllers( const css::uno::Sequence< css::uno::Reference< css::awt::XTabController > >& TabControllers ) override;
+ css::uno::Sequence< css::uno::Reference< css::awt::XTabController > > SAL_CALL getTabControllers( ) override;
+ void SAL_CALL addTabController( const css::uno::Reference< css::awt::XTabController >& TabController ) override;
+ void SAL_CALL removeTabController( const css::uno::Reference< css::awt::XTabController >& TabController ) 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::awt::XWindow
+ void SAL_CALL setVisible( sal_Bool Visible ) override;
+
+ OUString SAL_CALL getImplementationName() override;
+
+ css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+protected:
+ virtual void PrepareWindowDescriptor( css::awt::WindowDescriptor& rDesc ) override;
+ virtual void removingControl( const css::uno::Reference< css::awt::XControl >& _rxControl );
+ virtual void addingControl( const css::uno::Reference< css::awt::XControl >& _rxControl );
+
+ /** ensures that the given control has a peer, if necessary and possible
+ @param _rxControl
+ an ->XControl which has just been inserted into the container. Must not be <NULL/>.
+ @precond
+ our mutex is locked
+ */
+ virtual void impl_createControlPeerIfNecessary(
+ const css::uno::Reference< css::awt::XControl >& _rxControl
+ );
+private:
+ /** adds the control to the container, does necessary notifications, and the like
+ @param _rxControl
+ the control to add. Must not be <NULL/>
+ @param _pName
+ Pointer to a name for the control. Might be <NULL/>, in this case an automatic name is generated
+ @return
+ the ID of the newly added control
+ */
+ sal_Int32 impl_addControl(
+ const css::uno::Reference< css::awt::XControl >& _rxControl,
+ const OUString* _pName = nullptr
+ );
+
+ /** removes the given control from the container, including necessary notifications and the like
+ @param _nId
+ the ID of the control to remove
+ @param _rxControl
+ the control itself. Must be the one which is stored under the given ID. This parameter could also be
+ obtained inside the method, but callers usually have obtained it, anyway.
+ */
+ void impl_removeControl(
+ sal_Int32 _nId,
+ const css::uno::Reference< css::awt::XControl >& _rxControl
+ );
+
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/controls/unocontrolcontainermodel.hxx b/toolkit/inc/controls/unocontrolcontainermodel.hxx
new file mode 100644
index 0000000000..83db8af31b
--- /dev/null
+++ b/toolkit/inc/controls/unocontrolcontainermodel.hxx
@@ -0,0 +1,51 @@
+/* -*- 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 <toolkit/controls/unocontrolmodel.hxx>
+
+
+
+class UnoControlContainerModel final : public UnoControlModel
+{
+ css::uno::Any ImplGetDefaultValue( sal_uInt16 nPropId ) const override;
+ ::cppu::IPropertyArrayHelper& getInfoHelper() override;
+
+public:
+ UnoControlContainerModel( const css::uno::Reference< css::uno::XComponentContext >& i_factory );
+ UnoControlContainerModel( const UnoControlContainerModel& rModel ) : UnoControlModel( rModel ) {}
+
+ rtl::Reference<UnoControlModel> Clone() const override { return new UnoControlContainerModel( *this ); }
+
+ // css::beans::XMultiPropertySet
+ css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) override;
+
+ // css::io::XPersistObject
+ OUString SAL_CALL getServiceName() override;
+
+ // css::lang::XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+
+ css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/helper/accessibilityclient.hxx b/toolkit/inc/helper/accessibilityclient.hxx
new file mode 100644
index 0000000000..f90414671d
--- /dev/null
+++ b/toolkit/inc/helper/accessibilityclient.hxx
@@ -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 .
+ */
+
+#ifndef INCLUDED_TOOLKIT_INC_HELPER_ACCESSIBILITYCLIENT_HXX
+#define INCLUDED_TOOLKIT_INC_HELPER_ACCESSIBILITYCLIENT_HXX
+
+#include <toolkit/helper/accessiblefactory.hxx>
+
+namespace toolkit
+{
+ /** a client for the accessibility implementations which have been
+ outsourced from the main toolkit library
+
+ All instances of this class share a reference to a common IAccessibleFactory
+ instance, which is used for creating all kind of Accessibility related
+ components.
+
+ When the AccessibilityClient goes away, also this factory goes away, and the respective
+ library is unloaded.
+
+ This class is not thread-safe.
+ */
+ class AccessibilityClient
+ {
+ private:
+ bool m_bInitialized;
+
+ public:
+ AccessibilityClient();
+
+ IAccessibleFactory& getFactory();
+
+ private:
+ void ensureInitialized();
+ };
+
+} // namespace toolkit
+
+#endif // INCLUDED_TOOLKIT_INC_HELPER_ACCESSIBILITYCLIENT_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/helper/btndlg.hxx b/toolkit/inc/helper/btndlg.hxx
new file mode 100644
index 0000000000..8894b8dec6
--- /dev/null
+++ b/toolkit/inc/helper/btndlg.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 .
+ */
+
+#ifndef INCLUDED_VCL_BTNDLG_HXX
+#define INCLUDED_VCL_BTNDLG_HXX
+
+#include <vcl/toolkit/dialog.hxx>
+#include <o3tl/typed_flags_set.hxx>
+
+#include <vector>
+#include <memory>
+
+struct ImplBtnDlgItem;
+class PushButton;
+class Button;
+
+#define BUTTONDIALOG_BUTTON_NOTFOUND (sal_uInt16(0xFFFF))
+
+enum class ButtonDialogFlags
+{
+ NONE = 0x0000,
+ Default = 0x0001,
+ OK = 0x0002,
+ Cancel = 0x0004,
+ Help = 0x0008,
+ Focus = 0x0010,
+};
+namespace o3tl
+{
+ template<> struct typed_flags<ButtonDialogFlags> : is_typed_flags<ButtonDialogFlags, 0x001f> {};
+}
+
+class ButtonDialog : public Dialog
+{
+public:
+ virtual ~ButtonDialog() override;
+ virtual void dispose() override;
+
+ virtual void Resize() override;
+ virtual void StateChanged( StateChangedType nStateChange ) override;
+
+ void SetPageSizePixel( const Size& rSize ) { maPageSize = rSize; }
+
+ void AddButton( StandardButtonType eType, sal_uInt16 nId, ButtonDialogFlags nBtnFlags, tools::Long nSepPixel = 0 );
+ void RemoveButton( sal_uInt16 nId );
+
+protected:
+ ButtonDialog( WindowType nType );
+ tools::Long ImplGetButtonSize();
+
+private:
+ ButtonDialog( const ButtonDialog & ) = delete;
+ ButtonDialog& operator=( const ButtonDialog& ) = delete;
+
+private:
+ std::vector<std::unique_ptr<ImplBtnDlgItem>> m_ItemList;
+ Size maPageSize;
+ Size maCtrlSize;
+ tools::Long mnButtonSize;
+ sal_uInt16 mnCurButtonId;
+ sal_uInt16 mnFocusButtonId;
+ bool mbFormat;
+
+ void ImplInitButtonDialogData();
+ VclPtr<PushButton> ImplCreatePushButton( ButtonDialogFlags nBtnFlags );
+ DECL_LINK( ImplClickHdl, Button* pBtn, void );
+ void ImplPosControls();
+
+};
+
+#endif // INCLUDED_VCL_BTNDLG_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/helper/imagealign.hxx b/toolkit/inc/helper/imagealign.hxx
new file mode 100644
index 0000000000..b3c68cd210
--- /dev/null
+++ b/toolkit/inc/helper/imagealign.hxx
@@ -0,0 +1,52 @@
+/* -*- 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_INC_HELPER_IMAGEALIGN_HXX
+#define INCLUDED_TOOLKIT_INC_HELPER_IMAGEALIGN_HXX
+
+#include <sal/types.h>
+#include <vcl/wintypes.hxx>
+
+namespace toolkit
+{
+
+
+ /** translates a VCL ImageAlign value into a css.awt.ImagePosition value
+ */
+ sal_Int16 translateImagePosition( ImageAlign _eVCLAlign );
+
+ /** translates a css.awt.ImagePosition value into a VCL ImageAlign
+ */
+ ImageAlign translateImagePosition( sal_Int16 _nImagePosition );
+
+ /** translates a VCL ImageAlign value into a compatible css.awt.ImageAlign value
+ */
+ sal_Int16 getCompatibleImageAlign( ImageAlign _eAlign );
+
+ /** translates a css.awt.ImageAlign value into a css.awt.ImagePosition value
+ */
+ sal_Int16 getExtendedImagePosition( sal_Int16 _nImageAlign );
+
+
+} // namespace toolkit
+
+
+#endif // INCLUDED_TOOLKIT_INC_HELPER_IMAGEALIGN_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/helper/msgbox.hxx b/toolkit/inc/helper/msgbox.hxx
new file mode 100644
index 0000000000..7c2b26ee1e
--- /dev/null
+++ b/toolkit/inc/helper/msgbox.hxx
@@ -0,0 +1,78 @@
+/* -*- 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 <o3tl/typed_flags_set.hxx>
+#include <helper/btndlg.hxx>
+#include <vcl/toolkit/fixed.hxx>
+#include <vcl/toolkit/vclmedit.hxx>
+
+// Window-Bits for MessageBoxen
+enum class MessBoxStyle
+{
+ NONE = 0x0000,
+ Ok = 0x0001,
+ OkCancel = 0x0002,
+ YesNo = 0x0004,
+ YesNoCancel = 0x0008,
+ RetryCancel = 0x0010,
+ DefaultOk = 0x0020,
+ DefaultCancel = 0x0040,
+ DefaultRetry = 0x0080,
+ DefaultYes = 0x0100,
+ DefaultNo = 0x0200,
+ AbortRetryIgnore = 0x1000,
+ DefaultIgnore = 0x2000,
+};
+namespace o3tl
+{
+template <> struct typed_flags<MessBoxStyle> : is_typed_flags<MessBoxStyle, 0x33ff>
+{
+};
+}
+
+class MessBox : public ButtonDialog
+{
+ VclPtr<VclMultiLineEdit> mpVCLMultiLineEdit;
+ VclPtr<FixedImage> mpFixedImage;
+ Image maImage;
+ bool mbHelpBtn;
+ MessBoxStyle mnMessBoxStyle;
+ OUString maMessText;
+
+protected:
+ void ImplInitButtons();
+ void ImplPosControls();
+
+public:
+ MessBox(vcl::Window* pParent, MessBoxStyle nMessBoxStyle, WinBits n, const OUString& rTitle,
+ OUString rMessage);
+ virtual ~MessBox() override;
+ virtual void dispose() override;
+
+ virtual void StateChanged(StateChangedType nStateChange) override;
+
+ void SetMessText(const OUString& rText) { maMessText = rText; }
+ const OUString& GetMessText() const { return maMessText; }
+
+ void SetImage(const Image& rImage) { maImage = rImage; }
+
+ virtual Size GetOptimalSize() const override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/helper/property.hxx b/toolkit/inc/helper/property.hxx
new file mode 100644
index 0000000000..013f734964
--- /dev/null
+++ b/toolkit/inc/helper/property.hxx
@@ -0,0 +1,246 @@
+/* -*- 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_HELPER_PROPERTY_HXX
+#define INCLUDED_TOOLKIT_HELPER_PROPERTY_HXX
+
+#include <sal/types.h>
+#include <rtl/ustring.hxx>
+
+namespace com::sun::star::uno {
+ class Type;
+ class Any;
+}
+
+
+#define BASEPROPERTY_NOTFOUND 0
+
+#define BASEPROPERTY_TEXT 1 // OUString
+#define BASEPROPERTY_BACKGROUNDCOLOR 2 // sal_Int32
+#define BASEPROPERTY_FILLCOLOR 3 // sal_Int32
+#define BASEPROPERTY_TEXTCOLOR 4 // sal_Int32
+#define BASEPROPERTY_LINECOLOR 5 // sal_Int32
+#define BASEPROPERTY_BORDER 6 // sal_Int16
+#define BASEPROPERTY_ALIGN 7 // sal_Int16
+#define BASEPROPERTY_FONTDESCRIPTOR 8 // css::awt::FontDescriptor
+#define BASEPROPERTY_DROPDOWN 9 // sal_Bool
+#define BASEPROPERTY_MULTILINE 10 // sal_Bool
+#define BASEPROPERTY_STRINGITEMLIST 11 // UStringSequence
+#define BASEPROPERTY_HSCROLL 12 // sal_Bool
+#define BASEPROPERTY_VSCROLL 13 // sal_Bool
+#define BASEPROPERTY_TABSTOP 14 // sal_Bool
+#define BASEPROPERTY_STATE 15 // sal_Int16
+#define BASEPROPERTY_FONT_TYPE 16 // OLD: Font_Type
+#define BASEPROPERTY_FONT_SIZE 17 // OLD: Font_Size
+#define BASEPROPERTY_FONT_ATTRIBS 18 // OLD: Font_Attribs
+#define BASEPROPERTY_DEFAULTCONTROL 19 // OUString (ServiceName)
+#define BASEPROPERTY_LABEL 20 // OUString
+#define BASEPROPERTY_LINECOUNT 21 // sal_Int16
+#define BASEPROPERTY_EXTDATEFORMAT 22 // sal_Int16
+#define BASEPROPERTY_DATESHOWCENTURY 23 // sal_Bool
+#define BASEPROPERTY_EXTTIMEFORMAT 24 // sal_Int16
+#define BASEPROPERTY_NUMSHOWTHOUSANDSEP 25 // sal_Bool
+#define BASEPROPERTY_CURRENCYSYMBOL 26 // OUString
+#define BASEPROPERTY_SPIN 27 // sal_Bool
+#define BASEPROPERTY_STRICTFORMAT 28 // sal_Bool
+#define BASEPROPERTY_DECIMALACCURACY 29 // sal_Int16
+#define BASEPROPERTY_DATE 30 // css::util::Date
+#define BASEPROPERTY_DATEMIN 31 // css::util::Date
+#define BASEPROPERTY_DATEMAX 32 // css::util::Date
+#define BASEPROPERTY_TIME 33 // css::util::Time
+#define BASEPROPERTY_TIMEMIN 34 // css::util::Time
+#define BASEPROPERTY_TIMEMAX 35 // css::util::Time
+#define BASEPROPERTY_VALUE_INT32 36 // sal_Int32
+#define BASEPROPERTY_VALUEMIN_INT32 37 // sal_Int32
+#define BASEPROPERTY_VALUEMAX_INT32 38 // sal_Int32
+#define BASEPROPERTY_VALUESTEP_INT32 39 // sal_Int32
+#define BASEPROPERTY_EDITMASK 40 // OUString
+#define BASEPROPERTY_LITERALMASK 41 // OUString
+#define BASEPROPERTY_IMAGEURL 42 // OUString
+#define BASEPROPERTY_READONLY 43 // sal_Bool
+#define BASEPROPERTY_ENABLED 44 // sal_Bool
+#define BASEPROPERTY_PRINTABLE 45 // sal_Bool
+#define BASEPROPERTY_ECHOCHAR 46 // sal_Int16
+#define BASEPROPERTY_MAXTEXTLEN 47 // sal_Int16
+#define BASEPROPERTY_HARDLINEBREAKS 48 // sal_Int16
+#define BASEPROPERTY_AUTOCOMPLETE 49 // sal_Bool
+#define BASEPROPERTY_MULTISELECTION 50 // sal_Bool
+#define BASEPROPERTY_SELECTEDITEMS 51 // INT16Sequence
+#define BASEPROPERTY_VALUE_DOUBLE 52 // DOUBLE
+#define BASEPROPERTY_VALUEMIN_DOUBLE 53 // DOUBLE
+#define BASEPROPERTY_VALUEMAX_DOUBLE 54 // DOUBLE
+#define BASEPROPERTY_VALUESTEP_DOUBLE 55 // DOUBLE
+#define BASEPROPERTY_TRISTATE 56 // sal_Bool
+#define BASEPROPERTY_DEFAULTBUTTON 57 // sal_Bool
+#define BASEPROPERTY_HELPURL 58 // OUString
+#define BASEPROPERTY_AUTOTOGGLE 59 // sal_Bool
+//#define BASEPROPERTY_FOCUSSELECTIONHIDE 60 // sal_Bool
+#define BASEPROPERTY_FORMATKEY 61 // sal_Bool
+#define BASEPROPERTY_FORMATSSUPPLIER 62 // css::util::XNumberFormatsSupplier
+#define BASEPROPERTY_EFFECTIVE_VALUE 63 // Any (double or string)
+#define BASEPROPERTY_TREATASNUMBER 64 // sal_Bool
+#define BASEPROPERTY_EFFECTIVE_DEFAULT 65 // Any (double or string)
+#define BASEPROPERTY_EFFECTIVE_MIN 66 // Double
+#define BASEPROPERTY_EFFECTIVE_MAX 67 // Double
+#define BASEPROPERTY_CURSYM_POSITION 68 // sal_Bool
+#define BASEPROPERTY_TITLE 69 // OUString
+#define BASEPROPERTY_MOVEABLE 70 // sal_Bool
+#define BASEPROPERTY_CLOSEABLE 71 // sal_Bool
+#define BASEPROPERTY_SIZEABLE 72 // sal_Bool
+#define BASEPROPERTY_HELPTEXT 73 // OUString
+#define BASEPROPERTY_PROGRESSVALUE 74 // sal_Int32
+#define BASEPROPERTY_PROGRESSVALUE_MIN 75 // sal_Int32
+#define BASEPROPERTY_PROGRESSVALUE_MAX 76 // sal_Int32
+#define BASEPROPERTY_SCROLLVALUE 77 // sal_Int32
+#define BASEPROPERTY_SCROLLVALUE_MAX 78 // sal_Int32
+#define BASEPROPERTY_LINEINCREMENT 79 // sal_Int32
+#define BASEPROPERTY_BLOCKINCREMENT 80 // sal_Int32
+#define BASEPROPERTY_VISIBLESIZE 81 // sal_Int32
+#define BASEPROPERTY_ORIENTATION 82 // sal_Int32
+#define BASEPROPERTY_FONTRELIEF 83 // sal_Int16
+#define BASEPROPERTY_FONTEMPHASISMARK 84 // sal_Int16
+#define BASEPROPERTY_TEXTLINECOLOR 85 // sal_Int32
+#define BASEPROPERTY_IMAGEALIGN 86 // sal_Int16
+#define BASEPROPERTY_SCALEIMAGE 87 // sal_Bool
+#define BASEPROPERTY_PUSHBUTTONTYPE 88 // sal_Int16
+#define BASEPROPERTY_DISPLAYBACKGROUNDCOLOR 89 // sal_Int32
+#define BASEPROPERTY_AUTOMNEMONICS 90 // sal_Bool
+#define BASEPROPERTY_MOUSETRANSPARENT 91 // sal_Bool
+#define BASEPROPERTY_ACCESSIBLENAME 92 // OUString
+#define BASEPROPERTY_PLUGINPARENT 93 // sal_Int64
+#define BASEPROPERTY_SCROLLVALUE_MIN 94 // sal_Int32
+#define BASEPROPERTY_REPEAT_DELAY 95 // sal_Int32
+#define BASEPROPERTY_SYMBOL_COLOR 96 // sal_Int32
+#define BASEPROPERTY_SPINVALUE 97 // sal_Int32
+#define BASEPROPERTY_SPINVALUE_MIN 98 // sal_Int32
+#define BASEPROPERTY_SPINVALUE_MAX 99 // sal_Int32
+#define BASEPROPERTY_SPININCREMENT 100 // sal_Int32
+#define BASEPROPERTY_REPEAT 101 // sal_Bool
+#define BASEPROPERTY_ENFORCE_FORMAT 102 // sal_Bool
+#define BASEPROPERTY_LIVE_SCROLL 103 // sal_Bool
+#define BASEPROPERTY_LINE_END_FORMAT 104 // sal_Int16
+#define BASEPROPERTY_ACTIVATED 105 // sal Bool
+#define BASEPROPERTY_COMPLETE 106 // sal_Bool
+#define BASEPROPERTY_CURRENTITEMID 107 // sal_Int16
+#define BASEPROPERTY_TOGGLE 108 // sal_Bool
+#define BASEPROPERTY_FOCUSONCLICK 109 // sal_Bool
+#define BASEPROPERTY_HIDEINACTIVESELECTION 110 // sal_Bool
+#define BASEPROPERTY_VISUALEFFECT 111 // sal_Int16
+#define BASEPROPERTY_BORDERCOLOR 112 // sal_Int32
+#define BASEPROPERTY_IMAGEPOSITION 113 // sal_Int16
+#define BASEPROPERTY_NATIVE_WIDGET_LOOK 114 // sal_Bool
+#define BASEPROPERTY_VERTICALALIGN 115 // VerticalAlignment
+#define BASEPROPERTY_MOUSE_WHEEL_BEHAVIOUR 116 // sal_Int16
+#define BASEPROPERTY_GRAPHIC 117 // css.graphic.XGraphic
+#define BASEPROPERTY_STEP_TIME 118 // sal_Int32
+#define BASEPROPERTY_DECORATION 119 // sal_Bool
+#define BASEPROPERTY_PAINTTRANSPARENT 120 // sal_Bool
+#define BASEPROPERTY_AUTOHSCROLL 121 // sal_Bool
+#define BASEPROPERTY_AUTOVSCROLL 122 // sal_Bool
+#define BASEPROPERTY_DESKTOP_AS_PARENT 123 // sal_Bool
+#define BASEPROPERTY_TREE_START 124
+#define BASEPROPERTY_TREE_SELECTIONTYPE 124
+#define BASEPROPERTY_TREE_EDITABLE 125
+#define BASEPROPERTY_TREE_DATAMODEL 126
+#define BASEPROPERTY_TREE_ROOTDISPLAYED 127
+#define BASEPROPERTY_TREE_SHOWSHANDLES 128
+#define BASEPROPERTY_TREE_SHOWSROOTHANDLES 129
+#define BASEPROPERTY_ROW_HEIGHT 130
+#define BASEPROPERTY_TREE_INVOKESSTOPNODEEDITING 131
+#define BASEPROPERTY_TREE_END 131
+#define BASEPROPERTY_DIALOGSOURCEURL 132
+#define BASEPROPERTY_NOLABEL 133 // OUString added for issue79712
+#define BASEPROPERTY_URL 134 // OUString
+#define BASEPROPERTY_UNIT 135 // ::awt::FieldUnit
+#define BASEPROPERTY_CUSTOMUNITTEXT 136 // OUString
+#define BASEPROPERTY_IMAGE_SCALE_MODE 137
+#define BASEPROPERTY_WRITING_MODE 138
+#define BASEPROPERTY_CONTEXT_WRITING_MODE 139
+#define BASEPROPERTY_GRID_SHOWROWHEADER 140
+#define BASEPROPERTY_GRID_SHOWCOLUMNHEADER 141
+#define BASEPROPERTY_GRID_DATAMODEL 142
+#define BASEPROPERTY_GRID_COLUMNMODEL 143
+#define BASEPROPERTY_GRID_SELECTIONMODE 144
+#define BASEPROPERTY_ENABLEVISIBLE 145 // sal_Bool
+#define BASEPROPERTY_REFERENCE_DEVICE 146
+
+#define BASEPROPERTY_HIGHCONTRASTMODE 147
+#define BASEPROPERTY_GRID_HEADER_BACKGROUND 148
+#define BASEPROPERTY_GRID_HEADER_TEXT_COLOR 149
+#define BASEPROPERTY_GRID_ROW_BACKGROUND_COLORS 150
+#define BASEPROPERTY_GRID_LINE_COLOR 151
+#define BASEPROPERTY_MULTISELECTION_SIMPLEMODE 152
+#define BASEPROPERTY_ITEM_SEPARATOR_POS 153
+#define BASEPROPERTY_GROUPNAME 154 // OUString
+#define BASEPROPERTY_MULTIPAGEVALUE 155 // sal_Int32
+#define BASEPROPERTY_USERFORMCONTAINEES 156 // css::container::XNameContainer
+#define BASEPROPERTY_AUTO_REPEAT 157
+#define BASEPROPERTY_ROW_HEADER_WIDTH 158
+#define BASEPROPERTY_COLUMN_HEADER_HEIGHT 159
+#define BASEPROPERTY_USE_GRID_LINES 160
+#define BASEPROPERTY_SCROLLWIDTH 161
+#define BASEPROPERTY_SCROLLHEIGHT 162
+#define BASEPROPERTY_SCROLLTOP 163
+#define BASEPROPERTY_SCROLLLEFT 164
+#define BASEPROPERTY_ACTIVE_SEL_BACKGROUND_COLOR 165
+#define BASEPROPERTY_INACTIVE_SEL_BACKGROUND_COLOR 166
+#define BASEPROPERTY_ACTIVE_SEL_TEXT_COLOR 167
+#define BASEPROPERTY_INACTIVE_SEL_TEXT_COLOR 168
+#define BASEPROPERTY_HIGHLIGHT_COLOR 169
+#define BASEPROPERTY_HIGHLIGHT_TEXT_COLOR 170
+#define BASEPROPERTY_TYPEDITEMLIST 171 // AnySequence
+
+
+// These properties are not bound, they are always extracted from the BASEPROPERTY_FONTDESCRIPTOR property
+#define BASEPROPERTY_FONTDESCRIPTORPART_START 1000
+#define BASEPROPERTY_FONTDESCRIPTORPART_NAME 1000 // OUString, not bound
+#define BASEPROPERTY_FONTDESCRIPTORPART_STYLENAME 1001 // OUString, not bound
+#define BASEPROPERTY_FONTDESCRIPTORPART_FAMILY 1002 // sal_Int16, not bound
+#define BASEPROPERTY_FONTDESCRIPTORPART_CHARSET 1003 // sal_Int16, not bound
+#define BASEPROPERTY_FONTDESCRIPTORPART_HEIGHT 1004 // sal_Int16, not bound
+#define BASEPROPERTY_FONTDESCRIPTORPART_WEIGHT 1005 // Float, not bound
+#define BASEPROPERTY_FONTDESCRIPTORPART_SLANT 1006 // sal_Int16, not bound
+#define BASEPROPERTY_FONTDESCRIPTORPART_UNDERLINE 1007 // sal_Int16, not bound
+#define BASEPROPERTY_FONTDESCRIPTORPART_STRIKEOUT 1008 // sal_Int16, not bound
+#define BASEPROPERTY_FONTDESCRIPTORPART_WIDTH 1009 // sal_Int16, not bound
+#define BASEPROPERTY_FONTDESCRIPTORPART_PITCH 1010 // sal_Int16, not bound
+#define BASEPROPERTY_FONTDESCRIPTORPART_CHARWIDTH 1011 // Float, not bound
+#define BASEPROPERTY_FONTDESCRIPTORPART_ORIENTATION 1012 // Float, not bound
+#define BASEPROPERTY_FONTDESCRIPTORPART_KERNING 1013 // sal_Bool, not bound
+#define BASEPROPERTY_FONTDESCRIPTORPART_WORDLINEMODE 1014 // sal_Bool, not bound
+#define BASEPROPERTY_FONTDESCRIPTORPART_TYPE 1015 // sal_Int16, not bound
+#define BASEPROPERTY_FONTDESCRIPTORPART_END 1015
+
+#define PROPERTY_ALIGN_LEFT 0
+#define PROPERTY_ALIGN_CENTER 1
+#define PROPERTY_ALIGN_RIGHT 2
+
+
+sal_uInt16 GetPropertyId( const OUString& rPropertyName );
+const css::uno::Type* GetPropertyType( sal_uInt16 nPropertyId );
+const OUString& GetPropertyName( sal_uInt16 nPropertyId );
+sal_Int16 GetPropertyAttribs( sal_uInt16 nPropertyId );
+bool DoesDependOnOthers( sal_uInt16 nPropertyId );
+bool CompareProperties( const css::uno::Any& r1, const css::uno::Any& r2 );
+
+
+#endif // INCLUDED_TOOLKIT_HELPER_PROPERTY_HXX
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/helper/scrollabledialog.hxx b/toolkit/inc/helper/scrollabledialog.hxx
new file mode 100644
index 0000000000..b93751c680
--- /dev/null
+++ b/toolkit/inc/helper/scrollabledialog.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 .
+ */
+
+#ifndef INCLUDED_TOOLKIT_AWT_SCROLLABLEDIALOG_HXX
+#define INCLUDED_TOOLKIT_AWT_SCROLLABLEDIALOG_HXX
+
+#include <vcl/toolkit/dialog.hxx>
+#include <vcl/toolkit/scrbar.hxx>
+
+namespace toolkit
+{
+ class ScrollableDialog final : public Dialog
+ {
+ public:
+ enum ScrollBarVisibility { None, Vert, Hori, Both };
+
+ private:
+ VclPtr<ScrollBar> maHScrollBar;
+ VclPtr<ScrollBar> maVScrollBar;
+ Size maScrollArea;
+ bool mbHasHoriBar;
+ bool mbHasVertBar;
+ Point mnScrollPos;
+ tools::Long mnScrWidth;
+ ScrollBarVisibility maScrollVis;
+
+ void lcl_Scroll( tools::Long nX, tools::Long nY );
+ DECL_LINK( ScrollBarHdl, ScrollBar*, void );
+
+ public:
+ ScrollableDialog( vcl::Window* pParent, WinBits nStyle, Dialog::InitFlag eFlag = Dialog::InitFlag::Default );
+ virtual ~ScrollableDialog() override;
+ virtual void dispose() override;
+ // Window
+ virtual void Resize() override;
+
+ void SetScrollWidth( tools::Long nWidth );
+ void SetScrollHeight( tools::Long nHeight );
+ void SetScrollLeft( tools::Long nLeft );
+ void SetScrollTop( tools::Long Top );
+ void setScrollVisibility( ScrollBarVisibility rState );
+ void ResetScrollBars();
+ };
+
+} // namespacetoolkit
+
+
+#endif // INCLUDED_TOOLKIT_AWT_SCROLLABLEDIALOG_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/helper/servicenames.hxx b/toolkit/inc/helper/servicenames.hxx
new file mode 100644
index 0000000000..7fb7ab2a57
--- /dev/null
+++ b/toolkit/inc/helper/servicenames.hxx
@@ -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 .
+ */
+
+#pragma once
+
+extern const char szServiceName_UnoControlDialog[];
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/helper/tkresmgr.hxx b/toolkit/inc/helper/tkresmgr.hxx
new file mode 100644
index 0000000000..70cc4118c7
--- /dev/null
+++ b/toolkit/inc/helper/tkresmgr.hxx
@@ -0,0 +1,34 @@
+/* -*- 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_INC_HELPER_TKRESMGR_HXX
+#define INCLUDED_TOOLKIT_INC_HELPER_TKRESMGR_HXX
+
+#include <rtl/ustring.hxx>
+
+class Image;
+
+namespace TkResMgr
+{
+Image getImageFromURL(const OUString& i_rImageURL);
+};
+
+#endif // INCLUDED_TOOLKIT_INC_HELPER_TKRESMGR_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/helper/unopropertyarrayhelper.hxx b/toolkit/inc/helper/unopropertyarrayhelper.hxx
new file mode 100644
index 0000000000..31940ec4c4
--- /dev/null
+++ b/toolkit/inc/helper/unopropertyarrayhelper.hxx
@@ -0,0 +1,52 @@
+/* -*- 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_INC_HELPER_UNOPROPERTYARRAYHELPER_HXX
+#define INCLUDED_TOOLKIT_INC_HELPER_UNOPROPERTYARRAYHELPER_HXX
+
+#include <cppuhelper/propshlp.hxx>
+
+#include <vector>
+#include <o3tl/sorted_vector.hxx>
+
+
+
+class UnoPropertyArrayHelper final : public ::cppu::IPropertyArrayHelper
+{
+ o3tl::sorted_vector<sal_Int32> maIDs;
+
+ bool ImplHasProperty( sal_uInt16 nPropId ) const;
+
+public:
+ UnoPropertyArrayHelper( const css::uno::Sequence<sal_Int32>& rIDs );
+ UnoPropertyArrayHelper( const std::vector< sal_uInt16 > &rIDs );
+
+ // ::cppu::IPropertyArrayHelper
+ sal_Bool SAL_CALL fillPropertyMembersByHandle( OUString * pPropName, sal_Int16 * pAttributes, sal_Int32 nHandle ) override;
+ css::uno::Sequence< css::beans::Property > SAL_CALL getProperties() override;
+ css::beans::Property SAL_CALL getPropertyByName(const OUString& rPropertyName) override;
+ sal_Bool SAL_CALL hasPropertyByName(const OUString& rPropertyName) override;
+ sal_Int32 SAL_CALL getHandleByName( const OUString & rPropertyName ) override;
+ sal_Int32 SAL_CALL fillHandles( sal_Int32* pHandles, const css::uno::Sequence< OUString > & rPropNames ) override;
+};
+
+
+#endif // INCLUDED_TOOLKIT_INC_HELPER_UNOPROPERTYARRAYHELPER_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/inc/helper/unowrapper.hxx b/toolkit/inc/helper/unowrapper.hxx
new file mode 100644
index 0000000000..dfed1b1215
--- /dev/null
+++ b/toolkit/inc/helper/unowrapper.hxx
@@ -0,0 +1,73 @@
+/* -*- 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_INC_HELPER_UNOWRAPPER_HXX
+#define INCLUDED_TOOLKIT_INC_HELPER_UNOWRAPPER_HXX
+
+#include <com/sun/star/awt/XToolkit.hpp>
+#include <com/sun/star/awt/XGraphics.hpp>
+#include <com/sun/star/awt/XVclWindowPeer.hpp>
+#include <com/sun/star/accessibility/XAccessible.hpp>
+
+#include <vcl/toolkit/unowrap.hxx>
+#include <vcl/window.hxx>
+
+#include <helper/accessibilityclient.hxx>
+
+
+
+class UnoWrapper final : public UnoWrapperBase
+{
+private:
+ css::uno::Reference< css::awt::XToolkit> mxToolkit;
+ ::toolkit::AccessibilityClient maAccessibleFactoryAccess;
+
+public:
+ UnoWrapper( const css::uno::Reference< css::awt::XToolkit>& rxToolkit );
+
+ virtual void Destroy() override;
+
+ // Toolkit
+ virtual css::uno::Reference< css::awt::XToolkit> GetVCLToolkit() override;
+
+ // Graphics
+ virtual css::uno::Reference< css::awt::XGraphics> CreateGraphics( OutputDevice* pOutDev ) override;
+ virtual void ReleaseAllGraphics( OutputDevice* pOutDev ) override;
+
+ // Window
+ virtual css::uno::Reference< css::awt::XVclWindowPeer> GetWindowInterface( vcl::Window* pWindow ) override;
+ virtual void SetWindowInterface( vcl::Window* pWindow, const css::uno::Reference< css::awt::XVclWindowPeer> & xIFace ) override;
+ virtual VclPtr<vcl::Window> GetWindow(const css::uno::Reference<css::awt::XWindow>& rxWindow) override;
+
+ // Menu
+ virtual css::uno::Reference<css::awt::XPopupMenu> CreateMenuInterface( PopupMenu* pPopupMenu ) override;
+
+ void WindowDestroyed( vcl::Window* pWindow ) override;
+
+ // Accessibility
+ virtual css::uno::Reference< css::accessibility::XAccessible >
+ CreateAccessible( Menu* pMenu, bool bIsMenuBar ) override;
+
+private:
+ virtual ~UnoWrapper();
+};
+
+#endif // INCLUDED_TOOLKIT_INC_HELPER_UNOWRAPPER_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/qa/complex/toolkit/AccessibleStatusBarItem.java b/toolkit/qa/complex/toolkit/AccessibleStatusBarItem.java
new file mode 100644
index 0000000000..d2c9b0f68a
--- /dev/null
+++ b/toolkit/qa/complex/toolkit/AccessibleStatusBarItem.java
@@ -0,0 +1,359 @@
+/*
+ * 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 .
+ */
+
+package complex.toolkit;
+
+import java.util.logging.Logger;
+import java.util.logging.Level;
+import complex.toolkit.accessibility._XAccessibleEventBroadcaster;
+import complex.toolkit.accessibility._XAccessibleExtendedComponent;
+import complex.toolkit.accessibility._XAccessibleText;
+import complex.toolkit.accessibility._XAccessibleComponent;
+import complex.toolkit.accessibility._XAccessibleContext;
+import util.SOfficeFactory;
+import util.AccessibilityTools;
+import com.sun.star.awt.XWindow;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.lang.XComponent;
+import com.sun.star.lang.XServiceInfo;
+import com.sun.star.sheet.XSpreadsheetDocument;
+import com.sun.star.text.XTextDocument;
+import com.sun.star.uno.XInterface;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.util.XCloseable;
+import com.sun.star.accessibility.AccessibleRole;
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.awt.XExtendedToolkit;
+
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openoffice.test.OfficeConnection;
+import static org.junit.Assert.*;
+
+/**
+ *
+ */
+public class AccessibleStatusBarItem {
+
+ XMultiServiceFactory xMSF = null;
+ XAccessibleContext testObject = null;
+ XWindow xWindow = null;
+
+ /**
+ * Check document types
+ */
+ @Test
+ public void checkDocs()
+ {
+ checkWriterDoc();
+ checkMathDoc();
+ checkDrawDoc();
+ checkImpressDoc();
+ checkCalcDoc();
+ }
+
+ private XMultiServiceFactory getMSF()
+ {
+ return UnoRuntime.queryInterface(XMultiServiceFactory.class, connection.getComponentContext().getServiceManager());
+ }
+
+ /**
+ * Test the interfaces on a writer document
+ */
+ private void checkWriterDoc() {
+ xMSF = getMSF();
+ SOfficeFactory xSOF = SOfficeFactory.getFactory(xMSF);
+ XTextDocument xTextDoc = null;
+ try {
+ System.out.println("****** Open a new writer document");
+ xTextDoc = xSOF.createTextDoc("_blank");
+ getTestObject();
+ }
+ catch(com.sun.star.uno.Exception e) {
+ Logger.getLogger( this.getClass().getName() ).log( Level.SEVERE, "caught an exception", e );
+ }
+ runAllInterfaceTests();
+
+ if (xTextDoc != null) {
+ XCloseable xClose = UnoRuntime.queryInterface(XCloseable.class, xTextDoc);
+ try {
+ xClose.close(false);
+ }
+ catch(com.sun.star.util.CloseVetoException e) {
+ Logger.getLogger( this.getClass().getName() ).log( Level.SEVERE, "caught an exception", e );
+ }
+ }
+ }
+
+ /**
+ * Test the interfaces on a math document
+ */
+ public void checkMathDoc() {
+ xMSF = getMSF();
+ SOfficeFactory xSOF = SOfficeFactory.getFactory(xMSF);
+ XComponent xMathDoc = null;
+ try {
+ System.out.println("****** Open a new math document");
+ xMathDoc = xSOF.createMathDoc("_blank");
+ getTestObject();
+ }
+ catch(com.sun.star.uno.Exception e) {
+ Logger.getLogger( this.getClass().getName() ).log( Level.SEVERE, "caught an exception", e );
+ }
+ runAllInterfaceTests();
+
+ if (xMathDoc != null) {
+ XCloseable xClose = UnoRuntime.queryInterface(XCloseable.class, xMathDoc);
+ try {
+ xClose.close(false);
+ }
+ catch(com.sun.star.util.CloseVetoException e) {
+ Logger.getLogger( this.getClass().getName() ).log( Level.SEVERE, "caught an exception", e );
+ }
+ }
+ }
+
+ /**
+ * Test the interfaces on a draw document
+ */
+ public void checkDrawDoc() {
+ xMSF = getMSF();
+ SOfficeFactory xSOF = SOfficeFactory.getFactory(xMSF);
+ XComponent xDrawDoc = null;
+ try {
+ System.out.println("****** Open a new draw document");
+ xDrawDoc = xSOF.createDrawDoc("_blank");
+ getTestObject();
+ }
+ catch(com.sun.star.uno.Exception e) {
+ Logger.getLogger( this.getClass().getName() ).log( Level.SEVERE, "caught an exception", e );
+ }
+ runAllInterfaceTests();
+
+ if (xDrawDoc != null) {
+ XCloseable xClose = UnoRuntime.queryInterface(XCloseable.class, xDrawDoc);
+ try {
+ xClose.close(false);
+ }
+ catch(com.sun.star.util.CloseVetoException e) {
+ Logger.getLogger( this.getClass().getName() ).log( Level.SEVERE, "caught an exception", e );
+ }
+ }
+ }
+
+ /**
+ * Test the interfaces on an impress document
+ */
+ public void checkImpressDoc() {
+ xMSF = getMSF();
+ SOfficeFactory xSOF = SOfficeFactory.getFactory(xMSF);
+ XComponent xImpressDoc = null;
+ try {
+ System.out.println("****** Open a new impress document");
+ xImpressDoc = xSOF.createImpressDoc("_blank");
+ getTestObject();
+ }
+ catch(com.sun.star.uno.Exception e) {
+ Logger.getLogger( this.getClass().getName() ).log( Level.SEVERE, "caught an exception", e );
+ }
+ runAllInterfaceTests();
+
+ if (xImpressDoc != null) {
+ XCloseable xClose = UnoRuntime.queryInterface(XCloseable.class, xImpressDoc);
+ try {
+ xClose.close(false);
+ }
+ catch(com.sun.star.util.CloseVetoException e) {
+ Logger.getLogger( this.getClass().getName() ).log( Level.SEVERE, "caught an exception", e );
+ }
+ }
+ }
+ /**
+ * Test the interfaces on a calc document
+ */
+ public void checkCalcDoc() {
+ xMSF = getMSF();
+ SOfficeFactory xSOF = SOfficeFactory.getFactory(xMSF);
+ XSpreadsheetDocument xSpreadsheetDoc = null;
+ try {
+ System.out.println("****** Open a new calc document");
+ xSpreadsheetDoc = xSOF.createCalcDoc("_blank");
+ util.utils.waitForEventIdle(xMSF);
+ getTestObject();
+ }
+ catch(com.sun.star.uno.Exception e) {
+ Logger.getLogger( this.getClass().getName() ).log( Level.SEVERE, "caught an exception", e );
+ }
+ runAllInterfaceTests();
+
+ if (xSpreadsheetDoc != null) {
+ XCloseable xClose = UnoRuntime.queryInterface(XCloseable.class, xSpreadsheetDoc);
+ try {
+ xClose.close(false);
+ }
+ catch(com.sun.star.util.CloseVetoException e) {
+ Logger.getLogger( this.getClass().getName() ).log( Level.SEVERE, "caught an exception", e );
+ }
+ }
+ }
+
+ public void getTestObject() {
+ try {
+ XInterface xIfc = (XInterface) xMSF.createInstance(
+ "com.sun.star.awt.Toolkit") ;
+ XExtendedToolkit tk =
+ UnoRuntime.queryInterface(XExtendedToolkit.class,xIfc);
+
+ util.utils.waitForEventIdle(xMSF);
+ xWindow = UnoRuntime.queryInterface(
+ XWindow.class,tk.getActiveTopWindow());
+
+ util.utils.waitForEventIdle(xMSF);
+ XAccessible xRoot = AccessibilityTools.getAccessibleObject(xWindow);
+ XAccessibleContext parentContext = null;
+
+ System.out.println("Get the accessible status bar.");
+ parentContext = AccessibilityTools.getAccessibleObjectForRole(
+ xRoot, AccessibleRole.STATUS_BAR, "");
+ util.utils.waitForEventIdle(xMSF);
+ if ( parentContext == null ) {
+ fail("Could not create a test object.");
+ }
+ System.out.println("...OK.");
+
+ testObject=parentContext;
+ }
+ catch(com.sun.star.uno.Exception e) {
+ Logger.getLogger( this.getClass().getName() ).log( Level.SEVERE, "caught an exception", e );
+ }
+ catch(Throwable t) {
+ Logger.getLogger( this.getClass().getName() ).log( Level.SEVERE, "caught an exception", t );
+ }
+ }
+
+ public void runAllInterfaceTests() {
+ long count = testObject.getAccessibleChildCount();
+ System.out.println("*****");
+ System.out.println("**** Found items to test: " + count);
+ for (long i = 0; i < count; i++) {
+ System.out.println("**** Now testing StatusBarItem " + i + ".");
+ XAccessible object = null;
+ try {
+ object = testObject.getAccessibleChild(i);
+ }
+ catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("* Cannot get item Nr: " + i);
+ continue;
+ }
+ XServiceInfo xSI = UnoRuntime.queryInterface(
+ XServiceInfo.class,object);
+ String[] services = xSI.getSupportedServiceNames();
+ System.out.println("* Implementation Name: " + xSI.getImplementationName());
+ String accName = object.getAccessibleContext().getAccessibleName();
+ System.out.println("* Accessible Name: " + accName);
+ for (int j=0; j<services.length; j++)
+ {
+ System.out.println("* ServiceName "+j+": "+ services[j]);
+ }
+ System.out.println("*****");
+
+ System.out.println("*** Now testing XAccessibleComponent ***");
+ _XAccessibleComponent _xAccCompTest =
+ new _XAccessibleComponent(object);
+ assertTrue("failed: "+accName+" - XAccessibleComponent::getBounds", _xAccCompTest._getBounds());
+ assertTrue("failed: "+accName+" - XAccessibleComponent::contains", _xAccCompTest._containsPoint());
+ assertTrue("failed: "+accName+" - XAccessibleComponent::getAccessibleAt", _xAccCompTest._getAccessibleAtPoint());
+ assertTrue("failed: "+accName+" - XAccessibleComponent::getBackground", _xAccCompTest._getBackground());
+ assertTrue("failed: "+accName+" - XAccessibleComponent::getForeground", _xAccCompTest._getForeground());
+ assertTrue("failed: "+accName+" - XAccessibleComponent::getLocation", _xAccCompTest._getLocation());
+ assertTrue("failed: "+accName+" - XAccessibleComponent::getLocationOnScreen", _xAccCompTest._getLocationOnScreen());
+ assertTrue("failed: "+accName+" - XAccessibleComponent::getSize", _xAccCompTest._getSize());
+ assertTrue("failed: "+accName+" - XAccessibleComponent::grabFocus", _xAccCompTest._grabFocus());
+
+ System.out.println("*** Now testing XAccessibleContext ***");
+ _XAccessibleContext _xAccContext =
+ new _XAccessibleContext(object);
+ assertTrue("failed: "+accName+" - XAccessibleContext::getAccessibleChildCount", _xAccContext._getAccessibleChildCount());
+ assertTrue("failed: "+accName+" - XAccessibleContext::getAccessibleChild", _xAccContext._getAccessibleChild());
+ assertTrue("failed: "+accName+" - XAccessibleContext::getAccessibleDescription", _xAccContext._getAccessibleDescription());
+ assertTrue("failed: "+accName+" - XAccessibleContext::getAccessibleName", _xAccContext._getAccessibleName());
+ assertTrue("failed: "+accName+" - XAccessibleContext::getAccessibleParent", _xAccContext._getAccessibleParent());
+ assertTrue("failed: "+accName+" - XAccessibleContext::getAccessibleIndexInParent", _xAccContext._getAccessibleIndexInParent());
+ assertTrue("failed: "+accName+" - XAccessibleContext::getAccessibleRelationSet", _xAccContext._getAccessibleRelationSet());
+ assertTrue("failed: "+accName+" - XAccessibleContext::getAccessibleRole", _xAccContext._getAccessibleRole());
+ assertTrue("failed: "+accName+" - XAccessibleContext::getAccessibleStateSet", _xAccContext._getAccessibleStateSet());
+ assertTrue("failed: "+accName+" - XAccessibleContext::getLocale", _xAccContext._getLocale());
+
+ System.out.println("*** Now testing XAccessibleExtendedComponent ***");
+ _XAccessibleExtendedComponent _xAccExtComp =
+ new _XAccessibleExtendedComponent(object);
+ assertTrue("failed: "+accName+" - XAccessibleExtendedComponent::getFont", _xAccExtComp._getFont());
+ assertTrue("failed: "+accName+" - XAccessibleExtendedComponent::getTitledBorderText", _xAccExtComp._getTitledBorderText());
+ assertTrue("failed: "+accName+" - XAccessibleExtendedComponent::getToolTipText", _xAccExtComp._getToolTipText());
+
+ System.out.println("*** Now testing XAccessibleEventBroadcaster ***");
+ _XAccessibleEventBroadcaster _xAccEvBcast =
+ new _XAccessibleEventBroadcaster(object, xWindow);
+ assertTrue("failed: "+accName+" - XAccessibleEventBroadcaster::addEventListener", _xAccEvBcast._addEventListener(xMSF));
+ assertTrue("failed: "+accName+" - XAccessibleEventBroadcaster::removeEventListener", _xAccEvBcast._removeEventListener(xMSF));
+
+ System.out.println("*** Now testing XAccessibleText ***");
+ _XAccessibleText _xAccText =
+ new _XAccessibleText(object, xMSF, "true");
+ assertTrue("failed: "+accName+" - XAccessibleText::getText", _xAccText._getText());
+ assertTrue("failed: "+accName+" - XAccessibleText::getCharacterCount", _xAccText._getCharacterCount());
+ assertTrue("failed: "+accName+" - XAccessibleText::getCharacterBounds", _xAccText._getCharacterBounds());
+ assertTrue("failed: "+accName+" - XAccessibleText::setSelection", _xAccText._setSelection());
+ assertTrue("failed: "+accName+" - XAccessibleText::copyText", _xAccText._copyText());
+ assertTrue("failed: "+accName+" - XAccessibleText::getCharacter", _xAccText._getCharacter());
+ assertTrue("failed: "+accName+" - XAccessibleText::getCharacterAttributes", _xAccText._getCharacterAttributes());
+ assertTrue("failed: "+accName+" - XAccessibleText::getIndexAtPoint", _xAccText._getIndexAtPoint());
+ assertTrue("failed: "+accName+" - XAccessibleText::getSelectedText", _xAccText._getSelectedText());
+ assertTrue("failed: "+accName+" - XAccessibleText::getSelectionEnd", _xAccText._getSelectionEnd());
+ assertTrue("failed: "+accName+" - XAccessibleText::getSelectionStart", _xAccText._getSelectionStart());
+ assertTrue("failed: "+accName+" - XAccessibleText::getTextAtIndex", _xAccText._getTextAtIndex());
+ assertTrue("failed: "+accName+" - XAccessibleText::getTextBeforeIndex", _xAccText._getTextBeforeIndex());
+ assertTrue("failed: "+accName+" - XAccessibleText::getBehindIndex", _xAccText._getTextBehindIndex());
+ assertTrue("failed: "+accName+" - XAccessibleText::getTextRange", _xAccText._getTextRange());
+ assertTrue("failed: "+accName+" - XAccessibleText::setCaretPosition", _xAccText._setCaretPosition());
+ assertTrue("failed: "+accName+" - XAccessibleText::getCaretPosition", _xAccText._getCaretPosition());
+ }
+ }
+
+
+
+
+ @BeforeClass public static void setUpConnection() throws Exception {
+ System.out.println("setUpConnection()");
+ connection.setUp();
+ }
+
+ @AfterClass public static void tearDownConnection()
+ throws InterruptedException, com.sun.star.uno.Exception
+ {
+ System.out.println("tearDownConnection()");
+ connection.tearDown();
+ }
+
+ private static final OfficeConnection connection = new OfficeConnection();
+
+
+}
diff --git a/toolkit/qa/complex/toolkit/Assert.java b/toolkit/qa/complex/toolkit/Assert.java
new file mode 100644
index 0000000000..f7988270a8
--- /dev/null
+++ b/toolkit/qa/complex/toolkit/Assert.java
@@ -0,0 +1,185 @@
+/*
+ * 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 .
+ */
+
+package complex.toolkit;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import static org.junit.Assert.*;
+
+/**
+ * provides assertion capabilities not found in {@link org.junit.Assert}
+ */
+public class Assert
+{
+
+ /** invokes a given method on a given object, and assures a certain exception is caught
+ * @param i_message
+ * is the message to print when the check fails
+ * @param i_object
+ * is the object to invoke the method on
+ * @param i_methodName
+ * is the name of the method to invoke
+ * @param i_methodArgs
+ * are the arguments to pass to the method.
+ * @param i_argClasses
+ * are the classes to assume for the arguments of the methods
+ * @param i_expectedExceptionClass
+ * is the class of the exception to be caught. If this is null,
+ * it means that <em>no</em> exception must be throw by invoking the method.
+ */
+ public static void assertException( final String i_message, final Object i_object, final String i_methodName,
+ final Class<?>[] i_argClasses, final Object[] i_methodArgs, final Class<?> i_expectedExceptionClass )
+ {
+ Class<?> objectClass = i_object.getClass();
+
+ boolean noExceptionAllowed = ( i_expectedExceptionClass == null );
+
+ boolean caughtExpected = noExceptionAllowed;
+ try
+ {
+ Method method = impl_getMethod( objectClass, i_methodName, i_argClasses );
+ method.invoke(i_object, i_methodArgs );
+ }
+ catch ( NoSuchMethodException e )
+ {
+ StringBuilder message = new StringBuilder();
+ message.append( "no such method: " ).append( objectClass.getName() ).append( '.' ).append( i_methodName ).append( "( " );
+ for ( int i=0; i<i_argClasses.length; ++i )
+ {
+ message.append( i_argClasses[i].getName() );
+ if ( i<i_argClasses.length - 1 )
+ message.append( ", " );
+ }
+ message.append( " )" );
+ fail( message.toString() );
+ }
+ catch ( InvocationTargetException e )
+ {
+ caughtExpected = noExceptionAllowed
+ ? false
+ : ( e.getTargetException().getClass().equals( i_expectedExceptionClass ) );
+ }
+ catch( Exception e )
+ {
+ caughtExpected = false;
+ }
+
+ assertTrue( i_message, caughtExpected );
+ }
+
+ /**
+ * retrieves a method, given by name and parameter signature, from the given class
+ *
+ * The method does somewhat more than simply calling {@link Class#getMethod}. In particular, it recognizes
+ * primitive parameter types, and attempts to find a method taking the given primitive type, instead of the
+ * type represented by the parameter class.
+ *
+ * For instance, if you have a method <code>foo( int )</code>, {@link Class#getMethod} would not return this
+ * method when you pass <code>Integer.class</code>. <code>impl_getMethod</code> will recognize this, and
+ * properly retrieve the method.
+ *
+ * Note: <code>impl_getMethod</code> is limited in that it will not try all possible combinations of primitive
+ * and non-primitive types. That is, a method like <code>foo( int, Integer, int )</code> is likely to not be
+ * found.
+ *
+ * @param i_objectClass
+ * @param i_methodName
+ * @param i_argClasses
+ * @return
+ */
+ private static Method impl_getMethod( final Class<?> i_objectClass, final String i_methodName, final Class<?>[] i_argClasses ) throws NoSuchMethodException
+ {
+ try
+ {
+ return i_objectClass.getMethod( i_methodName, i_argClasses );
+ }
+ catch ( NoSuchMethodException ex )
+ {
+ }
+
+ int substitutedTypes = 0;
+ int substitutedTypesLastRound = 0;
+ final Class<?>[][] substitutionTable = new Class[][] {
+ new Class[] { Long.class, long.class },
+ new Class[] { Integer.class, int.class },
+ new Class[] { Short.class, short.class },
+ new Class[] { Byte.class, byte.class },
+ new Class[] { Double.class, double.class },
+ new Class[] { Float.class, float.class },
+ new Class[] { Character.class, char.class }
+ };
+ do
+ {
+ substitutedTypes = 0;
+ final Class<?>[] argClasses = new Class[ i_argClasses.length ];
+ for ( int i=0; i < argClasses.length; ++i )
+ {
+ argClasses[i] = i_argClasses[i];
+ if ( substitutedTypes > substitutedTypesLastRound )
+ continue;
+
+ for ( int c=0; c<substitutionTable.length; ++c )
+ {
+ if ( i_argClasses[i].equals( substitutionTable[c][0] ) )
+ {
+ argClasses[i] = substitutionTable[c][1];
+ ++substitutedTypes;
+ break;
+ }
+ }
+ }
+ if ( substitutedTypes == substitutedTypesLastRound )
+ throw new NoSuchMethodException();
+ substitutedTypesLastRound = substitutedTypes;
+
+ try
+ {
+ return i_objectClass.getMethod( i_methodName, argClasses );
+ }
+ catch ( NoSuchMethodException e )
+ {
+ }
+ }
+ while ( substitutedTypes > 0 );
+ throw new NoSuchMethodException();
+ }
+
+ /** invokes a given method on a given object, and assures a certain exception is caught
+ * @param i_message is the message to print when the check fails
+ * @param i_object is the object to invoke the method on
+ * @param i_methodName is the name of the method to invoke
+ * @param i_methodArgs are the arguments to pass to the method. Those implicitly define
+ * the classes of the arguments of the method which is called.
+ * @param i_expectedExceptionClass is the class of the exception to be caught. If this is null,
+ * it means that <em>no</em> exception must be throw by invoking the method.
+ */
+ public static void assertException( final String i_message, final Object i_object, final String i_methodName,
+ final Object[] i_methodArgs, final Class<?> i_expectedExceptionClass )
+ {
+ Class<?>[] argClasses = new Class[ i_methodArgs.length ];
+ for ( int i=0; i<i_methodArgs.length; ++i )
+ argClasses[i] = i_methodArgs[i].getClass();
+ assertException( i_message, i_object, i_methodName, argClasses, i_methodArgs, i_expectedExceptionClass );
+ }
+
+
+
+
+
+}
diff --git a/toolkit/qa/complex/toolkit/GridControl.java b/toolkit/qa/complex/toolkit/GridControl.java
new file mode 100644
index 0000000000..b2338ee68f
--- /dev/null
+++ b/toolkit/qa/complex/toolkit/GridControl.java
@@ -0,0 +1,746 @@
+/*
+ * 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 .
+ */
+
+package complex.toolkit;
+
+import com.sun.star.awt.XControl;
+import com.sun.star.awt.XControlContainer;
+import com.sun.star.awt.XControlModel;
+import com.sun.star.awt.XToolkit;
+import com.sun.star.awt.grid.DefaultGridDataModel;
+import com.sun.star.awt.grid.XGridColumn;
+import com.sun.star.awt.grid.XGridColumnModel;
+import com.sun.star.awt.grid.XGridControl;
+import com.sun.star.awt.grid.XGridDataModel;
+import com.sun.star.awt.grid.XMutableGridDataModel;
+import com.sun.star.awt.grid.XSortableMutableGridDataModel;
+import com.sun.star.beans.Pair;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.ContainerEvent;
+import com.sun.star.container.XContainerListener;
+import com.sun.star.container.XNameContainer;
+import com.sun.star.lang.EventObject;
+import com.sun.star.lang.IndexOutOfBoundsException;
+import com.sun.star.lang.XComponent;
+import com.sun.star.lang.XEventListener;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.uno.Exception;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XComponentContext;
+import com.sun.star.uno.XInterface;
+import com.sun.star.util.XCloneable;
+import complex.toolkit.awtgrid.DummyColumn;
+import complex.toolkit.awtgrid.TMutableGridDataModel;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+import org.openoffice.test.OfficeConnection;
+
+/** is a unit test for the grid control related implementations
+ */
+public class GridControl
+{
+
+ public GridControl()
+ {
+ m_context = m_connection.getComponentContext();
+ }
+
+
+ private static void impl_dispose( final Object... i_components )
+ {
+ for ( int i=0; i<i_components.length; ++i )
+ {
+ if ( i_components[i] != null )
+ {
+ final XComponent component = UnoRuntime.queryInterface( XComponent.class, i_components[i] );
+ component.dispose();
+ }
+ }
+ }
+
+
+ private void impl_recreateGridModel() throws Exception
+ {
+ impl_dispose( m_gridControlModel, m_columnModel, m_dataModel );
+
+ // create a grid control model, and ensure it has a proper data and column model already
+ m_gridControlModel = UnoRuntime.queryInterface( XPropertySet.class,
+ createInstance( "com.sun.star.awt.grid.UnoControlGridModel" ) );
+ assertNotNull( "grid control model does not provide XPropertySet interface", m_gridControlModel );
+
+ // ensure that the model has default column/data models
+ m_columnModel = UnoRuntime.queryInterface( XGridColumnModel.class, m_gridControlModel.getPropertyValue( "ColumnModel" ) );
+ assertNotNull( "the control model is expected to have an initial column model", m_columnModel );
+ final XGridDataModel dataModel = UnoRuntime.queryInterface( XGridDataModel.class, m_gridControlModel.getPropertyValue( "GridDataModel" ) );
+ assertNotNull( "the control model is expected to have an initial data model", dataModel );
+ m_dataModel = UnoRuntime.queryInterface( XSortableMutableGridDataModel.class,
+ dataModel );
+ assertNotNull( "the out-of-the-box data model should be mutable and sortable", m_dataModel );
+ }
+
+
+ @Test
+ public void testGridControlCloning() throws Exception
+ {
+ impl_recreateGridModel();
+
+ // give the test something to compare, actually
+ XGridColumnModel columnModel = UnoRuntime.queryInterface( XGridColumnModel.class,
+ m_gridControlModel.getPropertyValue( "ColumnModel" ) );
+ columnModel.setDefaultColumns( 10 );
+
+ // clone the grid model
+ final XCloneable cloneable = UnoRuntime.queryInterface( XCloneable.class, m_gridControlModel );
+ assertNotNull( "all UnoControlModel's are expected to be clonable", cloneable );
+
+ final XInterface clone = cloneable.createClone();
+ final XPropertySet clonedProps = UnoRuntime.queryInterface( XPropertySet.class, clone );
+
+ // TODO: check all those generic properties for equality
+
+ // the data model and the column model should have been cloned, too
+ // in particular, the clone should not share the sub models with the original
+ final XMutableGridDataModel originalDataModel = UnoRuntime.queryInterface( XMutableGridDataModel.class,
+ m_gridControlModel.getPropertyValue( "GridDataModel" ) );
+ final XMutableGridDataModel clonedDataModel = UnoRuntime.queryInterface( XMutableGridDataModel.class,
+ clonedProps.getPropertyValue( "GridDataModel" ) );
+ assertFalse( "data model should not be shared after cloning", UnoRuntime.areSame( originalDataModel, clonedDataModel ) );
+ impl_assertEquality( originalDataModel, clonedDataModel );
+
+ final XGridColumnModel originalColumnModel = columnModel;
+ final XGridColumnModel clonedColumnModel = UnoRuntime.queryInterface( XGridColumnModel.class,
+ clonedProps.getPropertyValue( "ColumnModel" ) );
+ assertFalse( "column model should not be shared after cloning", UnoRuntime.areSame( originalColumnModel, clonedColumnModel ) );
+ impl_assertEquality( originalColumnModel, clonedColumnModel );
+ }
+
+
+ @Test
+ public void testDisposal() throws Exception
+ {
+ impl_recreateGridModel();
+
+ final int columnCount = 3;
+ m_columnModel.setDefaultColumns( columnCount );
+
+ // add disposal listeners to all columns so far
+ final XGridColumn[] columns = m_columnModel.getColumns();
+ assertEquals( "creating default columns resulted in unexpected column count", columnCount, columns.length );
+ final DisposeListener[] columnListeners = new DisposeListener[columnCount];
+ for ( int i=0; i<columnCount; ++i )
+ columnListeners[i] = new DisposeListener( columns[i] );
+
+ // add another column, and check that upon removal, it is disposed
+ final int newColumnIndex = m_columnModel.addColumn( m_columnModel.createColumn() );
+ final DisposeListener columnListener = new DisposeListener( m_columnModel.getColumn( newColumnIndex ) );
+ m_columnModel.removeColumn( newColumnIndex );
+ assertTrue( "explicit column removal is expected to dispose the column", columnListener.isDisposed() );
+
+ // by definition, the grid control model is the owner of both the column and the data model. So, setting
+ // a new column/data model should implicitly dispose the old models
+ final DisposeListener oldDataModelListener = new DisposeListener( m_dataModel );
+ final DisposeListener oldColumnModelListener = new DisposeListener( m_columnModel );
+
+ final Object newDataModel = createInstance( "com.sun.star.awt.grid.DefaultGridDataModel" );
+ final Object newColumnModel = createInstance( "com.sun.star.awt.grid.DefaultGridColumnModel" );
+ final DisposeListener newDataModelListener = new DisposeListener( newDataModel );
+ final DisposeListener newColumnModelListener = new DisposeListener( newColumnModel );
+
+ m_gridControlModel.setPropertyValue( "GridDataModel", newDataModel );
+ assertTrue( "setting a new data model failed", impl_areSameInterface( newDataModel, m_gridControlModel.getPropertyValue( "GridDataModel" ) ) );
+ m_gridControlModel.setPropertyValue( "ColumnModel", newColumnModel );
+ assertTrue( "setting a new column model failed", impl_areSameInterface( newColumnModel, m_gridControlModel.getPropertyValue( "ColumnModel" ) ) );
+
+ assertTrue( "old data model has not been disposed", oldDataModelListener.isDisposed() );
+ assertTrue( "old column model has not been disposed", oldColumnModelListener.isDisposed() );
+ for ( int i=0; i<columnCount; ++i )
+ assertTrue( "column no. " + i + " has not been disposed", columnListeners[i].isDisposed() );
+
+ // the same holds if the grid control model itself is disposed - it should dispose the depending models, too
+ assertFalse( "new data model is already disposed - this is unexpected", newDataModelListener.isDisposed() );
+ assertFalse( "new column model is already disposed - this is unexpected", newColumnModelListener.isDisposed() );
+ impl_dispose( m_gridControlModel );
+ assertTrue( "new data model is not disposed after disposing the grid column model", newDataModelListener.isDisposed() );
+ assertTrue( "new column model is not disposed after disposing the grid column model", newColumnModelListener.isDisposed() );
+ }
+
+
+ /**
+ * tests various aspects of the <code>XMutableGridDataModel</code> interface
+ */
+ @Test
+ public void testMutableGridDataModel() throws Exception
+ {
+ impl_recreateGridModel();
+
+ TMutableGridDataModel test = new TMutableGridDataModel( m_dataModel );
+ test.testAddRow();
+ test.testAddRows();
+ test.testInsertRow();
+ test.testInsertRows();
+ test.testRemoveRow();
+ test.testRemoveAllRows();
+ test.testUpdateCellData();
+ test.testUpdateRowData();
+ test.testUpdateRowHeading();
+ test.cleanup();
+
+ // a somewhat less straight-forward test: the data model is expected to implicitly increase its column count
+ // when you add a row which has more columns than currently known
+ final XMutableGridDataModel dataModel = DefaultGridDataModel.create( m_context );
+ dataModel.addRow( 0, new Object[] { 1 } );
+ assertEquals( "unexpected column count after adding the most simple row", 1, dataModel.getColumnCount() );
+ dataModel.addRow( 1, new Object[] { 1, 2 } );
+ assertEquals( "implicit extension of the column count doesn't work", 2, dataModel.getColumnCount() );
+ }
+
+
+ @Test
+ public void testGridColumnModel() throws Exception
+ {
+ impl_recreateGridModel();
+
+ ColumnModelListener listener = new ColumnModelListener();
+ m_columnModel.addContainerListener( listener );
+
+ // insert default columns into the previously empty model, ensure we get the right notifications
+ final int defaultColumnsCount = 3;
+ m_columnModel.setDefaultColumns( defaultColumnsCount );
+ impl_assertColumnModelConsistency();
+ List< ContainerEvent > events = listener.assertExclusiveInsertionEvents();
+ listener.reset();
+ assertEquals( "wrong number of events fired by setDefaultColumns", defaultColumnsCount, events.size() );
+ for ( int i=0; i<defaultColumnsCount; ++i )
+ {
+ final ContainerEvent event = events.get(i);
+ final int index = impl_assertInteger( event.Accessor );
+ assertEquals( "unexpected Accessor value in insert notification", i, index );
+ assertTrue( "wrong column object notified in insert notification",
+ impl_areSameInterface( event.Element, m_columnModel.getColumn(i) ) );
+ }
+
+ // insert some more default columns, ensure that all previously existing columns are removed
+ final int moreDefaultColumnsCount = 5;
+ m_columnModel.setDefaultColumns( moreDefaultColumnsCount );
+ impl_assertColumnModelConsistency();
+ assertEquals( "setting default columns is expected to remove all previously existing columns",
+ moreDefaultColumnsCount, m_columnModel.getColumnCount() );
+
+ // in this situation, both removal and insertion events have been notified
+ final List< ContainerEvent > removalEvents = listener.getRemovalEvents();
+ final List< ContainerEvent > insertionEvents = listener.getInsertionEvents();
+ listener.reset();
+
+ // for the removal events, check the indexes
+ assertEquals( "wrong number of columns removed (or notified) upon setting default columns",
+ defaultColumnsCount, removalEvents.size() );
+ for ( int i=0; i<removalEvents.size(); ++i )
+ {
+ final ContainerEvent event = removalEvents.get(i);
+ final int removedIndex = impl_assertInteger( event.Accessor );
+
+ // The implementation is allowed to remove the columns from the beginning, in which case the
+ // index of the removed column must always be 0, since e.g. the second column has index 0
+ // after the first column (which previously had index 0) had been removed.
+ // Alternatively, the implementation is allowed to remove columns from the end, which means
+ // that the column index given in the event is steadily increasing.
+ assertTrue( "unexpected column removal event column index",
+ ( removedIndex == 0 ) || ( removedIndex == removalEvents.size() - 1 - i ) );
+ }
+
+ // for the insertion events, check the indexes as well
+ assertEquals( "wrong number of insertion events when setting default columns over existing columns",
+ moreDefaultColumnsCount, insertionEvents.size() );
+ for ( int i=0; i<insertionEvents.size(); ++i )
+ {
+ final ContainerEvent event = insertionEvents.get(i);
+ final int index = impl_assertInteger( event.Accessor );
+ assertEquals( i, index );
+ }
+
+ // okay, remove all those columns
+ while ( m_columnModel.getColumnCount() != 0 )
+ {
+ final int columnCount = m_columnModel.getColumnCount();
+ final int removeColumnIndex = m_randomGenerator.nextInt( columnCount );
+ m_columnModel.removeColumn( removeColumnIndex );
+ events = listener.assertExclusiveRemovalEvents();
+ listener.reset();
+ assertEquals( "removing a single column should notify a single event", 1, events.size() );
+ final ContainerEvent event = events.get(0);
+ final int removalIndex = impl_assertInteger( event.Accessor );
+ assertEquals( "removing an arbitrary column does not notify the proper accessor",
+ removeColumnIndex, removalIndex );
+ }
+
+ // calling addColumn with a column not created by the given model/implementation should not succeed
+ boolean caughtExpected = false;
+ try
+ {
+ m_columnModel.addColumn( new DummyColumn() );
+ }
+ catch( final com.sun.star.lang.IllegalArgumentException e )
+ {
+ assertTrue( impl_areSameInterface( e.Context, m_columnModel ) );
+ caughtExpected = true;
+ }
+ assertTrue( "adding a dummy (self-implemented) grid column to the model should not succeed", caughtExpected );
+
+ // adding a single column to the end should succeed, properly notify, and still be consistent
+ final XGridColumn newColumn = m_columnModel.createColumn();
+ m_columnModel.addColumn( newColumn );
+ impl_assertColumnModelConsistency();
+ events = listener.assertExclusiveInsertionEvents();
+ listener.reset();
+ assertEquals( "addColumn notifies the wrong number of insertion events", 1, events.size() );
+ final int insertionIndex = impl_assertInteger( events.get(0).Accessor );
+ assertEquals( insertionIndex, newColumn.getIndex() );
+ }
+
+
+ @Test
+ public void testDataModel() throws Exception
+ {
+ impl_recreateGridModel();
+
+ // ensure that getCellData and getRowData have the same opinion on the data they deliver
+ final Object[][] data = new Object[][] {
+ new Object[] { 15, 17, 0 },
+ new Object[] { 9, 8, 14 },
+ new Object[] { 17, 2, 16 },
+ new Object[] { 0, 7, 14 },
+ new Object[] { 10, 16, 16 },
+ };
+ m_dataModel.addRows( new Object[ data.length ], data );
+
+ for ( int row = 0; row < data.length; ++row )
+ {
+ assertArrayEquals( "getRowData delivers wrong data in row " + row, data[row], m_dataModel.getRowData( row ) );
+ for ( int col = 0; col < data[row].length; ++col )
+ {
+ assertEquals( "getCellData delivers wrong data at position (" + col + ", " + row + ")",
+ data[row][col], m_dataModel.getCellData( col, row ) );
+ }
+ }
+ }
+
+
+ @Test
+ public void testSortableDataModel() throws Exception
+ {
+ impl_recreateGridModel();
+
+ final int colCount = 3;
+ final int rowCount = 10;
+ // initialize with some data
+ final Object[][] data = new Object[][] {
+ new Object[] { 15, 17, 0 },
+ new Object[] { 9, 8, 14 },
+ new Object[] { 17, 2, 16 },
+ new Object[] { 0, 7, 14 },
+ new Object[] { 10, 16, 16 },
+ new Object[] { 2, 8, 10 },
+ new Object[] { 4, 8, 3 },
+ new Object[] { 7, 9, 0 },
+ new Object[] { 15, 6, 19 },
+ new Object[] { 2, 14, 19 }
+ };
+ final Object[] rowHeadings = new Object[] {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
+ };
+ // ensure consistency of the test data
+ assertEquals( rowHeadings.length, rowCount );
+ assertEquals( data.length, rowCount );
+ for ( Object[] rowData : data )
+ assertEquals( rowData.length, colCount );
+
+ // add the test data
+ m_dataModel.addRows( rowHeadings, data );
+ assertEquals( rowCount, m_dataModel.getRowCount() );
+ assertEquals( colCount, m_dataModel.getColumnCount() );
+
+ // sort by each column
+ for ( int colIndex = 0; colIndex < colCount; ++colIndex )
+ {
+ for ( boolean ascending : new boolean[] { true, false } )
+ {
+ m_dataModel.sortByColumn( colIndex, ascending );
+ Pair<Integer,Boolean> currentSortOrder = m_dataModel.getCurrentSortOrder();
+ assertEquals( "invalid current sort column (column " + colIndex + ")", currentSortOrder.First.intValue(), colIndex );
+ assertEquals( "invalid current sort direction", currentSortOrder.Second.booleanValue(), ascending );
+
+ /*for ( int i=0; i<rowCount; ++i )
+ {
+ for ( int j=0; j<colCount; ++j )
+ System.out.print( m_dataModel.getCellData( j, i ).toString() + ", " );
+ System.out.println();
+ }*/
+
+ // verify the data is actually sorted by this column
+ for ( int rowIndex = 0; rowIndex < rowCount - 1; ++rowIndex )
+ {
+ final Object currentValue = m_dataModel.getCellData( colIndex, rowIndex );
+ final int currentIntValue = impl_assertInteger( currentValue );
+ final Object nextValue = m_dataModel.getCellData( colIndex, rowIndex + 1 );
+ final int nextIntValue = impl_assertInteger( nextValue );
+ assertTrue( "data in row " + rowIndex + " is actually not sorted " + ( ascending ? "ascending" : "descending" ),
+ ascending ? currentIntValue <= nextIntValue
+ : currentIntValue >= nextIntValue );
+
+ // ensure the data in the other columns, and the row headings, are sorted as well
+ final Object rowHeading = m_dataModel.getRowHeading( rowIndex );
+ final int unsortedRowIndex = impl_assertInteger( rowHeading );
+ for ( int innerColIndex = 0; innerColIndex < colCount; ++innerColIndex )
+ {
+ assertEquals( "sorted row " + rowIndex + ", unsorted row " + unsortedRowIndex + ", col " + innerColIndex +
+ ": wrong data",
+ data[unsortedRowIndex][innerColIndex], m_dataModel.getCellData( innerColIndex, rowIndex ) );
+ }
+ }
+ }
+ }
+ }
+
+
+ @Test
+ public void testView() throws Exception
+ {
+ final XControl control = impl_createDialogWithGridControl();
+ final XPropertySet gridModelProps =
+ UnoRuntime.queryInterface( XPropertySet.class, control.getModel() );
+
+ // in the current implementation (not sure this is a good idea at all), the control (more precise: the peer)
+ // ensures that if there are no columns in the column model, but in the data model, then the column model
+ // will implicitly have the needed columns added.
+ // To ensure that clients which rely on this do not break in the future, check this here.
+ final XMutableGridDataModel dataModel = UnoRuntime.queryInterface( XMutableGridDataModel.class,
+ gridModelProps.getPropertyValue( "GridDataModel" ) );
+ assertNotNull( dataModel );
+ assertEquals( 0, dataModel.getColumnCount() );
+
+ final XGridColumnModel columnModel = UnoRuntime.queryInterface( XGridColumnModel.class,
+ gridModelProps.getPropertyValue( "ColumnModel" ) );
+ assertNotNull( columnModel );
+ assertEquals( 0, columnModel.getColumnCount() );
+
+ final int columnCount = 3;
+ final int rowCount = 2;
+ dataModel.addRow( null, new Object[] { 1, 2, 3 } );
+ dataModel.addRow( null, new Object[] { 6, 5, 4 } );
+
+ assertEquals( columnCount, dataModel.getColumnCount() );
+ assertEquals( columnCount, columnModel.getColumnCount() );
+
+ // some cursor traveling
+ final XGridControl gridControl = UnoRuntime.queryInterface( XGridControl.class, control );
+ gridControl.goToCell( 0, 0 );
+ assertEquals( "wrong 'current column' (1)", 0, gridControl.getCurrentColumn() );
+ assertEquals( "wrong 'current row' (1)", 0, gridControl.getCurrentRow() );
+ gridControl.goToCell( columnCount - 1, rowCount - 1 );
+ assertEquals( "wrong 'current column' (2)", dataModel.getColumnCount() - 1, gridControl.getCurrentColumn() );
+ assertEquals( "wrong 'current row' (2)", dataModel.getRowCount() - 1, gridControl.getCurrentRow() );
+
+ // removing the last column, while the active cell is in this very last column, is expected to adjust
+ // the active cell
+ columnModel.removeColumn( columnCount - 1 );
+ assertEquals( "removed the last and active column, active column was not adjusted!",
+ columnCount - 2, gridControl.getCurrentColumn() );
+ // same holds for rows
+ dataModel.removeRow( rowCount - 1 );
+ assertEquals( "removed the last and active row, active row was not adjusted!",
+ rowCount - 2, gridControl.getCurrentRow() );
+ }
+
+
+ private XControl impl_createDialogWithGridControl() throws Exception
+ {
+ // create a simple dialog model/control/peer trinity
+ final XControlModel dialogModel = createInstance( XControlModel.class, "com.sun.star.awt.UnoControlDialogModel" );
+ m_disposables.add( dialogModel );
+ final XPropertySet dialogProps = UnoRuntime.queryInterface( XPropertySet.class, dialogModel );
+ dialogProps.setPropertyValue( "Width", 200 );
+ dialogProps.setPropertyValue( "Height", 100 );
+ dialogProps.setPropertyValue( "Title", "Grid Control Unit Test" );
+ final XControl dialogControl = createInstance( XControl.class, "com.sun.star.awt.UnoControlDialog" );
+ m_disposables.add( dialogControl );
+ dialogControl.setModel( dialogModel );
+ dialogControl.createPeer( createInstance( XToolkit.class, "com.sun.star.awt.Toolkit" ), null );
+
+ // insert a grid control model
+ final XMultiServiceFactory controlModelFactory = UnoRuntime.queryInterface( XMultiServiceFactory.class,
+ dialogModel );
+ final XPropertySet gridModelProps = UnoRuntime.queryInterface( XPropertySet.class,
+ controlModelFactory.createInstance( "com.sun.star.awt.grid.UnoControlGridModel" ) );
+ m_disposables.add( gridModelProps );
+ gridModelProps.setPropertyValue( "PositionX", 6 );
+ gridModelProps.setPropertyValue( "PositionY", 6 );
+ gridModelProps.setPropertyValue( "Width", 188 );
+ gridModelProps.setPropertyValue( "Height", 88 );
+ final XNameContainer modelContainer = UnoRuntime.queryInterface( XNameContainer.class, dialogModel );
+ modelContainer.insertByName( "grid", gridModelProps );
+
+ // check the respective control has been created
+ final XControlContainer controlContainer = UnoRuntime.queryInterface( XControlContainer.class, dialogControl );
+ final XControl gridControl = controlContainer.getControl( "grid" );
+ assertNotNull( "no grid control created in the dialog", gridControl );
+
+ return gridControl;
+ }
+
+
+ private int impl_assertInteger( final Object i_object )
+ {
+ assertTrue( i_object instanceof Integer );
+ return ((Integer)i_object).intValue();
+ }
+
+
+ private void impl_assertColumnModelConsistency() throws IndexOutOfBoundsException
+ {
+ for ( int col = 0; col < m_columnModel.getColumnCount(); ++col )
+ {
+ final XGridColumn column = m_columnModel.getColumn( col );
+ assertNotNull( column );
+ assertEquals( "column/model inconsistency: column " + col + " has a wrong index!", col, column.getIndex() );
+ }
+
+ final XGridColumn[] allColumns = m_columnModel.getColumns();
+ assertEquals( "getColumns returns the wrong number of column objects",
+ m_columnModel.getColumnCount(), allColumns.length );
+ for ( int col = 0; col < m_columnModel.getColumnCount(); ++col )
+ {
+ assertTrue( "getColumns inconsistency", impl_areSameInterface( allColumns[col], m_columnModel.getColumn(col) ) );
+ }
+ }
+
+
+ private void impl_assertEquality( final XGridDataModel i_reference, final XGridDataModel i_compare ) throws IndexOutOfBoundsException
+ {
+ assertNotNull( i_reference );
+ assertNotNull( i_compare );
+
+ assertEquals( "data model comparison: wrong column counts", i_reference.getColumnCount(), i_compare.getColumnCount() );
+ assertEquals( "data model comparison: wrong row counts", i_reference.getRowCount(), i_compare.getRowCount() );
+
+ for ( int row = 0; row < i_reference.getRowCount(); ++row )
+ {
+ assertEquals( "data model comparison: wrong row heading content in row " + row,
+ i_reference.getRowHeading( row ) );
+ for ( int col = 0; col < i_reference.getRowCount(); ++col )
+ {
+ assertEquals( "data model comparison: wrong cell content in cell (" + col + ", " + row + ")",
+ i_reference.getCellData( col, row ) );
+ assertEquals( "data model comparison: wrong tooltip content in cell (" + col + ", " + row + ")",
+ i_reference.getCellToolTip( col, row ) );
+ }
+ }
+ }
+
+
+ private void impl_assertEquality( final XGridColumnModel i_reference, final XGridColumnModel i_compare ) throws IndexOutOfBoundsException
+ {
+ assertEquals( "column model comparison: wrong column counts", i_reference.getColumnCount(), i_compare.getColumnCount() );
+ for ( int col = 0; col < i_reference.getColumnCount(); ++col )
+ {
+ final XGridColumn referenceColumn = i_reference.getColumn( col );
+ final XGridColumn compareColumn = i_compare.getColumn( col );
+ impl_assertEquality( referenceColumn, compareColumn );
+ }
+ }
+
+
+ private void impl_assertEquality( final XGridColumn i_reference, final XGridColumn i_compare )
+ {
+ final Method[] methods = XGridColumn.class.getMethods();
+ for ( int m=0; m<methods.length; ++m )
+ {
+ if ( !methods[m].getName().startsWith( "get" ) )
+ continue;
+ try
+ {
+ final Object referenceValue = methods[m].invoke( i_reference );
+ final Object compareValue = methods[m].invoke( i_compare );
+ assertEquals( "grid column comparison: column attribute '" + methods[m].getName().substring(3) + "' does not match",
+ referenceValue, compareValue );
+ }
+ catch ( java.lang.Exception ex )
+ {
+ fail( " could not retrieve object attributes: " + ex.toString() );
+ }
+ }
+ }
+
+
+ private boolean impl_areSameInterface( final Object i_lhs, final Object i_rhs )
+ {
+ final XInterface lhs = UnoRuntime.queryInterface( XInterface.class, i_lhs );
+ final XInterface rhs = UnoRuntime.queryInterface( XInterface.class, i_rhs );
+ return UnoRuntime.areSame( lhs, rhs );
+ }
+
+
+ @Before
+ public void initTestCase()
+ {
+ m_disposables.clear();
+ }
+
+
+ @After
+ public void cleanupTestCase()
+ {
+ impl_dispose( m_disposables.toArray() );
+ }
+
+
+ @BeforeClass
+ public static void setUpConnection() throws java.lang.Exception
+ {
+ System.out.println( "--------------------------------------------------------------------------------" );
+ System.out.println( "starting class: " + GridControl.class.getName() );
+ System.out.print( "connecting ... " );
+ m_connection.setUp();
+ System.out.println( "done.");
+
+ final long seed = m_randomGenerator.nextLong();
+ m_randomGenerator.setSeed( seed );
+ System.out.println( "seeding random number generator with " + seed );
+ }
+
+
+ @AfterClass
+ public static void tearDownConnection()
+ throws InterruptedException, com.sun.star.uno.Exception
+ {
+ System.out.println();
+ System.out.println( "tearing down connection" );
+ m_connection.tearDown();
+ System.out.println( "finished class: " + GridControl.class.getName() );
+ System.out.println( "--------------------------------------------------------------------------------" );
+ }
+
+
+ public <T> T createInstance( Class<T> i_interfaceClass, final String i_serviceIndentifier ) throws Exception
+ {
+ return UnoRuntime.queryInterface( i_interfaceClass, createInstance( i_serviceIndentifier ) );
+ }
+
+
+ private Object createInstance( final String i_serviceName ) throws Exception
+ {
+ Object instance = m_context.getServiceManager().createInstanceWithContext( i_serviceName, m_context );
+ assertNotNull( "could not create an instance of '" + i_serviceName + "'", instance );
+ return instance;
+ }
+
+ private static final class DisposeListener implements XEventListener
+ {
+ DisposeListener( final Object i_component )
+ {
+ m_component = UnoRuntime.queryInterface( XComponent.class, i_component );
+ assertNotNull( m_component );
+ m_component.addEventListener( this );
+ }
+
+ public void disposing( EventObject i_event )
+ {
+ assertTrue( UnoRuntime.areSame( i_event.Source, m_component ) );
+ m_isDisposed = true;
+ }
+
+ final boolean isDisposed() { return m_isDisposed; }
+
+ private final XComponent m_component;
+ private boolean m_isDisposed;
+ }
+
+
+ private static final class ColumnModelListener implements XContainerListener
+ {
+ ColumnModelListener()
+ {
+ }
+
+ public void elementInserted( ContainerEvent i_event )
+ {
+ m_insertionEvents.add( i_event );
+ }
+
+ public void elementRemoved( ContainerEvent i_event )
+ {
+ m_removalEvents.add( i_event );
+ }
+
+ public void elementReplaced( ContainerEvent i_event )
+ {
+ m_replacementEvents.add( i_event );
+ }
+
+ public void disposing( EventObject eo )
+ {
+ }
+
+ private List< ContainerEvent > assertExclusiveInsertionEvents()
+ {
+ assertFalse( m_insertionEvents.isEmpty() );
+ assertTrue( m_removalEvents.isEmpty() );
+ assertTrue( m_replacementEvents.isEmpty() );
+ return m_insertionEvents;
+ }
+
+ private List< ContainerEvent > assertExclusiveRemovalEvents()
+ {
+ assertTrue( m_insertionEvents.isEmpty() );
+ assertFalse( m_removalEvents.isEmpty() );
+ assertTrue( m_replacementEvents.isEmpty() );
+ return m_removalEvents;
+ }
+
+ private void reset()
+ {
+ m_insertionEvents = new ArrayList< ContainerEvent >();
+ m_removalEvents = new ArrayList< ContainerEvent >();
+ m_replacementEvents = new ArrayList< ContainerEvent >();
+ }
+
+ private List< ContainerEvent > getInsertionEvents() { return m_insertionEvents; }
+ private List< ContainerEvent > getRemovalEvents() { return m_removalEvents; }
+
+ private List< ContainerEvent > m_insertionEvents = new ArrayList< ContainerEvent >();
+ private List< ContainerEvent > m_removalEvents = new ArrayList< ContainerEvent >();
+ private List< ContainerEvent > m_replacementEvents = new ArrayList< ContainerEvent >();
+ }
+
+
+ private static final OfficeConnection m_connection = new OfficeConnection();
+ private static Random m_randomGenerator = new Random();
+ private final XComponentContext m_context;
+
+ private XPropertySet m_gridControlModel;
+ private XGridColumnModel m_columnModel;
+ private XSortableMutableGridDataModel m_dataModel;
+ private final List< Object > m_disposables = new ArrayList< Object >();
+}
diff --git a/toolkit/qa/complex/toolkit/accessibility/_XAccessibleComponent.java b/toolkit/qa/complex/toolkit/accessibility/_XAccessibleComponent.java
new file mode 100644
index 0000000000..e55cb1a22a
--- /dev/null
+++ b/toolkit/qa/complex/toolkit/accessibility/_XAccessibleComponent.java
@@ -0,0 +1,463 @@
+/*
+ * 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 .
+ */
+
+package complex.toolkit.accessibility;
+
+import java.util.ArrayList;
+
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleComponent;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.awt.Point;
+import com.sun.star.awt.Rectangle;
+import com.sun.star.awt.Size;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XInterface;
+
+/**
+ * Testing <code>com.sun.star.accessibility.XAccessibleComponent</code>
+ * interface methods :
+ * <ul>
+ * <li><code> containsPoint()</code></li>
+ * <li><code> getAccessibleAtPoint()</code></li>
+ * <li><code> getBounds()</code></li>
+ * <li><code> getLocation()</code></li>
+ * <li><code> getLocationOnScreen()</code></li>
+ * <li><code> getSize()</code></li>
+ * <li><code> grabFocus()</code></li>
+ * </ul> <p>
+ *
+ * @see com.sun.star.accessibility.XAccessibleComponent
+ */
+public class _XAccessibleComponent {
+
+ private final XAccessibleComponent oObj;
+
+ private Rectangle bounds = null ;
+
+ /**
+ * Constructor
+ */
+ public _XAccessibleComponent(XInterface object/*, LogWriter log*/) {
+ oObj = UnoRuntime.queryInterface(
+ XAccessibleComponent.class, object);
+ }
+
+ /**
+ * First checks 4 inner bounds (upper, lower, left and right)
+ * of component bounding box to contain
+ * at least one point of the component. Second 4 outer bounds
+ * are checked to not contain any component points.<p>
+ *
+ * Has <b> OK </b> status if inner bounds contain component points
+ * and outer bounds don't contain any component points. <p>
+ *
+ * The following method tests are to be completed successfully before :
+ * <ul>
+ * <li> <code> getBounds() </code> : to have size of a component.</li>
+ * </ul>
+ */
+ public boolean _containsPoint() {
+
+ boolean result = true ;
+
+ int curX = 0;
+ while (!oObj.containsPoint(new Point(curX, 0)) && curX < bounds.Width) {
+ curX++;
+ }
+ if (curX < bounds.Width) {
+ System.out.println("Upper bound of box contains point ("
+ + curX + ",0) - OK");
+ } else {
+ System.out.println
+ ("Upper bound of box contains no component points - FAILED");
+ result = false;
+ }
+
+ curX = 0;
+ while (!oObj.containsPoint(new Point(curX, bounds.Height - 1))
+ && curX < bounds.Width) {
+
+ System.out.println("Contains returns false for ("+curX+","+bounds.Height+")");
+ curX++;
+ }
+ if (curX < bounds.Width) {
+ System.out.println("Lower bound of box contains point ("
+ + curX + "," + (bounds.Height - 1) + ") - OK");
+ } else {
+ System.out.println
+ ("Lower bound of box contains no component points - FAILED");
+ result = false;
+ }
+
+ int curY = 0;
+ while (!oObj.containsPoint(new Point(0, curY)) && curY < bounds.Height) {
+ curY++;
+ }
+ if (curY < bounds.Height) {
+ System.out.println("Left bound of box contains point (0,"
+ + curY + ") - OK");
+ } else {
+ System.out.println
+ ("Left bound of box contains no component points - FAILED");
+ result = false;
+ }
+
+ curY = 0;
+ while (!oObj.containsPoint(new Point(bounds.Width - 1, curY)) && curY < bounds.Height) {
+ curY++;
+ }
+ if (curY < bounds.Height) {
+ System.out.println("Right bound of box contains point ("
+ + (bounds.Width - 1) + "," + curY + ") - OK");
+ } else {
+ System.out.println
+ ("Right bound of box contains no component points - FAILED");
+ result = false;
+ }
+
+ boolean locRes = true;
+ for (int x = -1; x <= bounds.Width; x++) {
+ locRes &= !oObj.containsPoint(new Point(x, -1));
+ locRes &= !oObj.containsPoint(new Point(x, bounds.Height+bounds.Y));
+ }
+ if (locRes) {
+ System.out.println("Outer upper and lower bounds contain no component "
+ + "points - OK");
+ } else {
+ System.out.println("Outer upper and lower bounds CONTAIN some component "
+ + "points - FAILED");
+ result = false;
+ }
+
+ locRes = true;
+ for (int y = -1; y <= bounds.Height; y++) {
+ locRes &= !oObj.containsPoint(new Point(-1, y));
+ locRes &= !oObj.containsPoint(new Point(bounds.X+bounds.Width, y));
+ }
+ if (locRes) {
+ System.out.println("Outer left and right bounds contain no component "
+ + "points - OK");
+ } else {
+ System.out.println("Outer left and right bounds CONTAIN some component "
+ + "points - FAILED");
+ result = false;
+ }
+
+ return result;
+ }
+
+ /**
+ * Iterates through all children which implement
+ * <code>XAccessibleComponent</code> (if they exist) determines their
+ * boundaries and tries to get each child by <code>getAccessibleAtPoint</code>
+ * passing point which belongs to the child.
+ * Also the point is checked which doesn't belong to child boundary
+ * box. <p>
+ *
+ * Has <b> OK </b> status if in the first cases the right children
+ * are returned, and in the second <code>null</code> or
+ * another child is returned.
+ */
+ public boolean _getAccessibleAtPoint() {
+
+ boolean result = true ;
+ XAccessibleComponent[] children = getChildrenComponents();
+
+ if (children.length > 0) {
+ for (int i = 0; i < children.length; i++) {
+ Rectangle chBnd = children[i].getBounds();
+ if (chBnd.X == -1)
+ {
+ continue;
+ }
+ System.out.println("Checking child with bounds " +
+ "(" + chBnd.X + "," + chBnd.Y + "),("
+ + chBnd.Width + "," + chBnd.Height + "): "
+ + util.AccessibilityTools.accessibleToString(children[i]));
+
+ System.out.println("finding the point which lies on the component");
+ int curX = 0;
+ int curY = 0;
+ while (!children[i].containsPoint(new Point(curX, curY))
+ && curX < chBnd.Width) {
+ curX++;
+ curY++;
+ }
+
+ if (curX==chBnd.Width) {
+ System.out.println("Couldn't find a point with contains");
+ continue;
+ }
+
+ // trying the point laying on child
+ XAccessible xAcc = oObj.getAccessibleAtPoint
+ (new Point(chBnd.X , chBnd.Y));
+ if (xAcc == null) {
+ System.out.println("The child not found at point ("
+ + (chBnd.X ) + "," + chBnd.Y + ") - FAILED");
+ result = false;
+ } else {
+ XAccessible xAccCh = UnoRuntime.queryInterface
+ (XAccessible.class, children[i]);
+ System.out.println("Child found at point ("
+ + (chBnd.X ) + "," + chBnd.Y + ") - OK");
+ boolean res = util.AccessibilityTools.equals(xAccCh, xAcc);
+ if (!res) {
+ long expIndex = xAccCh.getAccessibleContext().getAccessibleIndexInParent();
+ long gotIndex = xAcc.getAccessibleContext().getAccessibleIndexInParent();
+ if (expIndex < gotIndex) {
+ System.out.println("The children found is not the same");
+ System.out.println("The expected child " +
+ xAccCh.getAccessibleContext().getAccessibleName());
+ System.out.println("is hidden behind the found Child ");
+ System.out.println(xAcc.getAccessibleContext().getAccessibleName()+" - OK");
+ } else {
+ System.out.println("The children found is not the same - FAILED");
+ System.out.println("Expected: "
+ +xAccCh.getAccessibleContext().getAccessibleName());
+ System.out.println("Found: "
+ +xAcc.getAccessibleContext().getAccessibleName());
+ result = false ;
+ }
+ }
+ }
+
+ // trying the point NOT laying on child
+ xAcc = oObj.getAccessibleAtPoint
+ (new Point(chBnd.X - 1, chBnd.Y - 1));
+ if (xAcc == null) {
+ System.out.println("No children found at point ("
+ + (chBnd.X - 1) + "," + (chBnd.Y - 1) + ") - OK");
+ result &= true;
+ } else {
+ XAccessible xAccCh = UnoRuntime.queryInterface(XAccessible.class, children[i]);
+ boolean res = util.AccessibilityTools.equals(xAccCh, xAcc);
+ if (res) {
+ System.out.println("The same child found outside "
+ + "its bounds - FAILED");
+ result = false ;
+ }
+ }
+ }
+ } else {
+ System.out.println("There are no children supporting "
+ + "XAccessibleComponent");
+ }
+
+ return result;
+ }
+
+ /**
+ * Retrieves the component bounds and stores it. <p>
+ *
+ * Has <b> OK </b> status if boundary position (x,y) is not negative
+ * and size (Width, Height) is greater than 0.
+ */
+ public boolean _getBounds() {
+ boolean result = true ;
+
+ bounds = oObj.getBounds() ;
+ result &= bounds != null
+ && bounds.X >=0 && bounds.Y >=0
+ && bounds.Width >0 && bounds.Height >0;
+
+ System.out.println("Bounds = " + (bounds != null
+ ? "(" + bounds.X + "," + bounds.Y + "),("
+ + bounds.Width + "," + bounds.Height + ")" : "null"));
+
+ return result;
+ }
+
+ /**
+ * Gets the location. <p>
+ *
+ * Has <b> OK </b> status if the location is the same as location
+ * of boundary obtained by <code>getBounds()</code> method.
+ *
+ * The following method tests are to be completed successfully before :
+ * <ul>
+ * <li> <code> getBounds() </code> : to have bounds </li>
+ * </ul>
+ */
+ public boolean _getLocation() {
+
+ boolean result = true ;
+ Point loc = oObj.getLocation() ;
+
+ result &= loc.X == bounds.X && loc.Y == bounds.Y ;
+
+ return result;
+ }
+
+ /**
+ * Get the screen location of the component and its parent
+ * (if it exists and supports <code>XAccessibleComponent</code>). <p>
+ *
+ * Has <b> OK </b> status if component screen location equals
+ * to screen location of its parent plus location of the component
+ * relative to the parent. <p>
+ *
+ * The following method tests are to be completed successfully before :
+ * <ul>
+ * <li> <code> getBounds() </code> : to have location of the component
+ * relative to its parent</li>
+ * </ul>
+ */
+ public boolean _getLocationOnScreen() {
+
+ XAccessibleComponent parent = getParentComponent();
+
+ boolean result = true ;
+ Point loc = oObj.getLocationOnScreen();
+ System.out.println("Location is (" + loc.X + "," + loc.Y + ")");
+
+ if (parent != null) {
+ Point parLoc = parent.getLocationOnScreen();
+ System.out.println("Parent location is ("
+ + parLoc.X + "," + parLoc.Y + ")");
+
+ result &= parLoc.X + bounds.X == loc.X;
+ result &= parLoc.Y + bounds.Y == loc.Y;
+ }
+
+ return result;
+ }
+
+ /**
+ * Obtains the size of the component. <p>
+ *
+ * Has <b> OK </b> status if the size is the same as in bounds. <p>
+ *
+ * The following method tests are to be completed successfully before :
+ * <ul>
+ * <li> <code> getBounds() </code> </li>
+ * </ul>
+ */
+ public boolean _getSize() {
+
+ boolean result = true ;
+ Size size = oObj.getSize() ;
+
+ result &= size.Width == bounds.Width;
+ result &= size.Height == bounds.Height;
+
+ return result;
+ }
+
+ /**
+ * Just calls the method. <p>
+ *
+ * Has <b> OK </b> status if no runtime exceptions occurred.
+ */
+ public boolean _grabFocus() {
+
+ boolean result = true ;
+ oObj.grabFocus() ;
+
+ return result ;
+ }
+
+ /**
+ * Retrieves all children (not more than 50) of the current
+ * component which support <code>XAccessibleComponent</code>.
+ *
+ * @return The array of children. Empty array returned if
+ * such children were not found or some error occurred.
+ */
+ private XAccessibleComponent[] getChildrenComponents() {
+ XAccessible xAcc = UnoRuntime.queryInterface(XAccessible.class, oObj) ;
+ if (xAcc == null) {
+ System.out.println("Component doesn't support XAccessible.");
+ return new XAccessibleComponent[0];
+ }
+ XAccessibleContext xAccCon = xAcc.getAccessibleContext();
+ long cnt = xAccCon.getAccessibleChildCount();
+
+ // for cases when too many children exist checking only first 50
+ if (cnt > 50)
+ {
+ cnt = 50;
+ }
+
+ ArrayList<XAccessibleComponent> childComp = new ArrayList<XAccessibleComponent>();
+ for (long i = 0; i < cnt; i++) {
+ try {
+ XAccessible child = xAccCon.getAccessibleChild(i);
+ XAccessibleContext xAccConCh = child.getAccessibleContext();
+ XAccessibleComponent xChAccComp = UnoRuntime.queryInterface(XAccessibleComponent.class, xAccConCh);
+ if (xChAccComp != null) {
+ childComp.add(xChAccComp) ;
+ }
+ } catch (com.sun.star.lang.IndexOutOfBoundsException e) {}
+ }
+
+ return childComp.toArray(new XAccessibleComponent[childComp.size()]);
+ }
+
+ /**
+ * Gets the parent of the current component which support
+ * <code>XAccessibleComponent</code>.
+ *
+ * @return The parent or <code>null</code> if the component
+ * has no parent or some errors occurred.
+ */
+ private XAccessibleComponent getParentComponent() {
+ XAccessible xAcc = UnoRuntime.queryInterface(XAccessible.class, oObj) ;
+ if (xAcc == null) {
+ System.out.println("Component doesn't support XAccessible.");
+ return null;
+ }
+
+ XAccessibleContext xAccCon = xAcc.getAccessibleContext();
+ XAccessible xAccPar = xAccCon.getAccessibleParent();
+
+ if (xAccPar == null) {
+ System.out.println("Component has no accessible parent.");
+ return null;
+ }
+ XAccessibleContext xAccConPar = xAccPar.getAccessibleContext();
+ XAccessibleComponent parent = UnoRuntime.queryInterface(XAccessibleComponent.class, xAccConPar);
+ if (parent == null) {
+ System.out.println
+ ("Accessible parent doesn't support XAccessibleComponent");
+ return null;
+ }
+
+ return parent;
+ }
+
+ /**
+ * Just calls the method.
+ */
+ public boolean _getForeground() {
+ int forColor = oObj.getForeground();
+ System.out.println("getForeground(): " + forColor);
+ return true;
+ }
+
+ /**
+ * Just calls the method.
+ */
+ public boolean _getBackground() {
+ int backColor = oObj.getBackground();
+ System.out.println("getBackground(): " + backColor);
+ return true;
+ }
+
+}
diff --git a/toolkit/qa/complex/toolkit/accessibility/_XAccessibleContext.java b/toolkit/qa/complex/toolkit/accessibility/_XAccessibleContext.java
new file mode 100644
index 0000000000..645b3b03b9
--- /dev/null
+++ b/toolkit/qa/complex/toolkit/accessibility/_XAccessibleContext.java
@@ -0,0 +1,244 @@
+/*
+ * 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 .
+ */
+
+package complex.toolkit.accessibility;
+
+import com.sun.star.lang.Locale;
+import com.sun.star.uno.XInterface;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.IllegalAccessibleComponentStateException;
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleRelationSet;
+import util.AccessibilityTools;
+
+/**
+ * Testing <code>com.sun.star.accessibility.XAccessibleContext</code>
+ * interface methods :
+ * <ul>
+ * <li><code> getAccessibleChildCount()</code></li>
+ * <li><code> getAccessibleChild()</code></li>
+ * <li><code> getAccessibleParent()</code></li>
+ * <li><code> getAccessibleIndexInParent()</code></li>
+ * <li><code> getAccessibleRole()</code></li>
+ * <li><code> getAccessibleDescription()</code></li>
+ * <li><code> getAccessibleName()</code></li>
+ * <li><code> getAccessibleRelationSet()</code></li>
+ * <li><code> getAccessibleStateSet()</code></li>
+ * <li><code> getLocale()</code></li>
+ * </ul> <p>
+ *
+ * @see com.sun.star.accessibility.XAccessibleContext
+ */
+public class _XAccessibleContext {
+
+ private final XAccessibleContext oObj;
+
+ private long childCount = 0;
+ private XAccessible parent = null ;
+
+ public _XAccessibleContext(XInterface object) {
+ oObj = UnoRuntime.queryInterface(XAccessibleContext.class, object);
+ }
+
+ /**
+ * Calls the method and stores the number of children. <p>
+ * Has <b> OK </b> status if non-negative number rutrned.
+ */
+ public boolean _getAccessibleChildCount() {
+ childCount = oObj.getAccessibleChildCount();
+ System.out.println(childCount + " children found.");
+ return childCount > -1;
+ }
+
+ /**
+ * Tries to get every child and checks its parent. <p>
+ *
+ * Has <b> OK </b> status if parent of every child
+ * and the tested component are the same objects.
+ *
+ * The following method tests are to be completed successfully before :
+ * <ul>
+ * <li> <code> getAccessibleChildCount() </code> : to have a number of
+ * children </li>
+ * </ul>
+ */
+ public boolean _getAccessibleChild() {
+ boolean bOK = true;
+ long counter = childCount;
+ if (childCount > 500)
+ {
+ counter = 500;
+ }
+ for (long i = 0; i < counter; i++) {
+ try {
+ XAccessible ch = oObj.getAccessibleChild(i) ;
+ XAccessibleContext chAC = ch.getAccessibleContext();
+
+ System.out.println(" Child " + i + ": " +
+ chAC.getAccessibleDescription()) ;
+
+ if (!AccessibilityTools.equals
+ (chAC.getAccessibleParent().getAccessibleContext(), oObj)){
+
+ System.out.println("Role:");
+ System.out.println("Getting: "+chAC.getAccessibleParent().getAccessibleContext().getAccessibleRole());
+ System.out.println("Expected: "+oObj.getAccessibleRole());
+
+ System.out.println("ImplementationName:");
+ System.out.println("Getting: "+util.utils.getImplName(chAC.getAccessibleParent().getAccessibleContext()));
+ System.out.println("Expected: "+util.utils.getImplName(oObj));
+
+ System.out.println("The parent of child and component "+
+ "itself differ.");
+ System.out.println("Getting(Description): "
+ +chAC.getAccessibleParent().getAccessibleContext().getAccessibleDescription());
+ System.out.println("Expected(Description): "
+ +oObj.getAccessibleDescription());
+
+ bOK = false;
+ } else {
+ System.out.println("Getting the expected Child -- OK");
+ }
+ } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
+ e.printStackTrace();
+ bOK = false;
+ }
+ }
+
+ return bOK;
+ }
+
+ /**
+ * Just gets the parent. <p>
+ *
+ * Has <b> OK </b> status if parent is not null.
+ */
+ public boolean _getAccessibleParent() {
+ // assume that the component is not ROOT
+ parent = oObj.getAccessibleParent();
+ return parent != null;
+ }
+
+ /**
+ * Retrieves the index of tested component in its parent.
+ * Then gets the parent's child by this index and compares
+ * it with tested component.<p>
+ *
+ * Has <b> OK </b> status if the parent's child and the tested
+ * component are the same objects.
+ *
+ * The following method tests are to be completed successfully before :
+ * <ul>
+ * <li> <code> getAccessibleParent() </code> : to have a parent </li>
+ * </ul>
+ */
+ public boolean _getAccessibleIndexInParent() {
+
+ boolean bOK = true;
+ long idx = oObj.getAccessibleIndexInParent();
+
+ XAccessibleContext parentAC = parent.getAccessibleContext() ;
+ try {
+ bOK &= AccessibilityTools.equals(
+ parentAC.getAccessibleChild(idx).getAccessibleContext(),oObj);
+ if (!bOK) {
+ System.out.println("Expected: "+util.utils.getImplName(oObj));
+ System.out.println("Getting: "+util.utils.getImplName(
+ parentAC.getAccessibleChild(idx).getAccessibleContext()));
+ }
+ } catch (com.sun.star.lang.IndexOutOfBoundsException e) {
+ e.printStackTrace();
+ bOK = false;
+ }
+ return bOK;
+ }
+
+ /**
+ * Get the accessible role of component. <p>
+ *
+ * Has <b> OK </b> status if non-negative number rutrned.
+ */
+ public boolean _getAccessibleRole() {
+ short role = oObj.getAccessibleRole();
+ System.out.println("The role is " + role);
+ return role > -1;
+ }
+
+ /**
+ * Get the accessible name of the component. <p>
+ *
+ * Has <b> OK </b> status if the name has non-zero length.
+ */
+ public boolean _getAccessibleName() {
+ String name = oObj.getAccessibleName();
+ System.out.println("The name is '" + name + "'");
+ return name != null;
+ }
+
+ /**
+ * Get the accessible description of the component. <p>
+ *
+ * Has <b> OK </b> status if the description has non-zero length.
+ */
+ public boolean _getAccessibleDescription() {
+ String descr = oObj.getAccessibleDescription();
+ System.out.println("The description is '" + descr + "'");
+ return descr != null;
+ }
+
+ /**
+ * Just gets the set. <p>
+ *
+ * Has <b> OK </b> status if the set is not null.
+ */
+ public boolean _getAccessibleRelationSet() {
+ XAccessibleRelationSet set = oObj.getAccessibleRelationSet();
+ return set != null;
+ }
+
+ /**
+ * Just gets the set. <p>
+ *
+ * Has <b> OK </b> status if the set is not null.
+ */
+ public boolean _getAccessibleStateSet() {
+ return true;
+ }
+
+ /**
+ * Gets the locale. <p>
+ *
+ * Has <b> OK </b> status if <code>Country</code> and
+ * <code>Language</code> fields of locale structure
+ * are not empty.
+ */
+ public boolean _getLocale() {
+ Locale loc = null ;
+ try {
+ loc = oObj.getLocale();
+ System.out.println("The locale is " + loc.Language + "," + loc.Country);
+ } catch (IllegalAccessibleComponentStateException e) {
+ e.printStackTrace();
+ }
+
+ return loc != null && loc.Language.length() > 0 &&
+ loc.Country.length() > 0;
+ }
+}
+
diff --git a/toolkit/qa/complex/toolkit/accessibility/_XAccessibleEventBroadcaster.java b/toolkit/qa/complex/toolkit/accessibility/_XAccessibleEventBroadcaster.java
new file mode 100644
index 0000000000..44b846615d
--- /dev/null
+++ b/toolkit/qa/complex/toolkit/accessibility/_XAccessibleEventBroadcaster.java
@@ -0,0 +1,178 @@
+/*
+ * 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 .
+ */
+
+package complex.toolkit.accessibility;
+
+import com.sun.star.accessibility.AccessibleEventObject;
+import com.sun.star.accessibility.AccessibleStateType;
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleEventBroadcaster;
+import com.sun.star.accessibility.XAccessibleEventListener;
+import com.sun.star.awt.PosSize;
+import com.sun.star.awt.Rectangle;
+import com.sun.star.awt.XWindow;
+import com.sun.star.lang.EventObject;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XInterface;
+
+/**
+ * Testing <code>
+ * com.sun.star.accessibility.XAccessibleEventBroadcaster</code>
+ * interface methods :
+ * <ul>
+ * <li><code> addAccessibleEventListener()</code></li>
+ * <li><code> removeAccessibleEventListener()</code></li>
+ * </ul>
+ *
+ * <p>This test needs the following object relations :</p>
+ * <ul>
+ * <li> <code>'EventProducer'</code> (of type
+ * <code>ifc.accessibility._XAccessibleEventBroadcaster.EventProducer</code>):
+ * this must be an implementation of the interface which could perform
+ * some actions for generating any kind of <code>AccessibleEvent</code></li>
+ * </ul>
+ *
+ * @see com.sun.star.accessibility.XAccessibleEventBroadcaster
+ */
+public class _XAccessibleEventBroadcaster {
+
+ private final XAccessibleEventBroadcaster oObj;
+ private final EventProducer prod;
+ private final EvListener list = new EvListener();
+
+ /**
+ * An event producer
+ */
+ private static class EventProducer {
+ private final XWindow xWindow;
+ private EventProducer(XWindow window) {
+ xWindow = window;
+ }
+
+ private void fireEvent() {
+ Rectangle newPosSize = xWindow.getPosSize();
+ newPosSize.Width = newPosSize.Width - 20;
+ newPosSize.Height = newPosSize.Height - 20;
+ newPosSize.X = newPosSize.X + 20;
+ newPosSize.Y = newPosSize.Y + 20;
+ xWindow.setPosSize(newPosSize.X, newPosSize.Y, newPosSize.Width,
+ newPosSize.Height, PosSize.POSSIZE);
+ }
+ }
+
+ /**
+ * Listener implementation which registers listener calls.
+ */
+ private class EvListener implements XAccessibleEventListener {
+ public AccessibleEventObject notifiedEvent = null ;
+ public void notifyEvent(AccessibleEventObject ev) {
+ System.out.println("Listener, Event : " + ev.EventId);
+ System.out.println("EventID: " + ev.EventId);
+ Object old=ev.OldValue;
+ if (old instanceof com.sun.star.accessibility.XAccessible) {
+ System.out.println("Old: "+((XAccessible)old).getAccessibleContext().getAccessibleName());
+ }
+
+ Object nev=ev.NewValue;
+ if (nev instanceof com.sun.star.accessibility.XAccessible) {
+ System.out.println("New: "+((XAccessible)nev).getAccessibleContext().getAccessibleName());
+ }
+ notifiedEvent = ev;
+ }
+
+ public void disposing(EventObject ev) {}
+ }
+
+ public _XAccessibleEventBroadcaster(XInterface object, XWindow window) {
+ oObj = UnoRuntime.queryInterface(XAccessibleEventBroadcaster.class, object);
+ prod = new EventProducer(window);
+ }
+
+ /**
+ * Adds two listeners and fires event by mean of object relation. <p>
+ * Has <b> OK </b> status if both listeners were called
+ */
+ public boolean _addEventListener(XMultiServiceFactory xMSF) {
+ System.out.println("adding two listeners");
+ oObj.addAccessibleEventListener(list);
+ boolean isTransient = chkTransient(oObj);
+ System.out.println("fire event");
+ prod.fireEvent() ;
+
+ util.utils.waitForEventIdle(xMSF);
+
+ boolean works = true;
+
+ if (list.notifiedEvent == null) {
+ if (!isTransient) {
+ System.out.println("listener wasn't called");
+ works = false;
+ } else {
+ System.out.println("Object is Transient, listener isn't expected to be called");
+ }
+ oObj.removeAccessibleEventListener(list);
+ }
+
+ return works;
+ }
+
+ /**
+ * Removes one of two listeners added before and fires event
+ * by mean of object relation. <p>
+ *
+ * Has <b> OK </b> status if the removed listener wasn't called. <p>
+ *
+ * The following method tests are to be completed successfully before :
+ * <ul>
+ * <li> <code>addEventListener()</code> : to have added listeners </li>
+ * </ul>
+ */
+ public boolean _removeEventListener(XMultiServiceFactory xMSF) {
+
+ list.notifiedEvent = null;
+
+ System.out.println("remove first listener");
+ oObj.removeAccessibleEventListener(list);
+
+ System.out.println("fire event");
+ prod.fireEvent() ;
+
+ util.utils.waitForEventIdle(xMSF);
+
+ if (list.notifiedEvent == null) {
+ System.out.println("listener wasn't called -- OK");
+ }
+
+ return list.notifiedEvent == null;
+
+ }
+
+ private static boolean chkTransient(Object Testcase) {
+ XAccessibleContext accCon = UnoRuntime.queryInterface(XAccessibleContext.class, Testcase);
+ long nStateSet = accCon.getAccessibleStateSet();
+ if ((nStateSet & AccessibleStateType.TRANSIENT) == 0)
+ return false;
+ long nParentStateSet = accCon.getAccessibleParent().getAccessibleContext()
+ .getAccessibleStateSet();
+ return (nParentStateSet & AccessibleStateType.MANAGES_DESCENDANTS) != 0;
+ }
+
+}
+
diff --git a/toolkit/qa/complex/toolkit/accessibility/_XAccessibleExtendedComponent.java b/toolkit/qa/complex/toolkit/accessibility/_XAccessibleExtendedComponent.java
new file mode 100644
index 0000000000..64dd66fcb7
--- /dev/null
+++ b/toolkit/qa/complex/toolkit/accessibility/_XAccessibleExtendedComponent.java
@@ -0,0 +1,75 @@
+/*
+ * 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 .
+ */
+
+package complex.toolkit.accessibility;
+
+import com.sun.star.accessibility.XAccessibleExtendedComponent;
+import com.sun.star.awt.XFont;
+import com.sun.star.uno.XInterface;
+import com.sun.star.uno.UnoRuntime;
+
+/**
+ * Testing <code>com.sun.star.accessibility.XAccessibleExtendedComponent</code>
+ * interface methods :
+ * <ul>
+ * <li><code> getForeground()</code></li>
+ * <li><code> getBackground()</code></li>
+ * <li><code> getFont()</code></li>
+ * <li><code> isEnabled()</code></li>
+ * <li><code> getTitledBorderText()</code></li>
+ * <li><code> getToolTipText()</code></li>
+ * </ul> <p>
+ * @see com.sun.star.accessibility.XAccessibleExtendedComponent
+ */
+public class _XAccessibleExtendedComponent {
+
+ private final XAccessibleExtendedComponent oObj;
+
+ public _XAccessibleExtendedComponent(XInterface object/*, LogWriter log*/) {
+ oObj = UnoRuntime.queryInterface(XAccessibleExtendedComponent.class, object);
+ }
+
+ /**
+ * Just calls the method.
+ */
+ public boolean _getFont() {
+ XFont font = oObj.getFont();
+ System.out.println("getFont(): " + font);
+ return true;
+ }
+
+ /**
+ * Calls the method and checks returned value.
+ * Has OK status if returned value isn't null.
+ */
+ public boolean _getTitledBorderText() {
+ String titleBorderText = oObj.getTitledBorderText();
+ System.out.println("getTitledBorderText(): '" + titleBorderText + "'");
+ return titleBorderText != null;
+ }
+
+ /**
+ * Calls the method and checks returned value.
+ * Has OK status if returned value isn't null.
+ */
+ public boolean _getToolTipText() {
+ String toolTipText = oObj.getToolTipText();
+ System.out.println("getToolTipText(): '" + toolTipText + "'");
+ return toolTipText != null;
+ }
+}
diff --git a/toolkit/qa/complex/toolkit/accessibility/_XAccessibleText.java b/toolkit/qa/complex/toolkit/accessibility/_XAccessibleText.java
new file mode 100644
index 0000000000..1cd97d63ab
--- /dev/null
+++ b/toolkit/qa/complex/toolkit/accessibility/_XAccessibleText.java
@@ -0,0 +1,1001 @@
+/*
+ * 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 .
+ */
+
+package complex.toolkit.accessibility;
+
+import com.sun.star.accessibility.XAccessibleText;
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.awt.Rectangle;
+import com.sun.star.awt.Point;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.accessibility.AccessibleTextType;
+import com.sun.star.accessibility.TextSegment;
+import com.sun.star.beans.UnknownPropertyException;
+import com.sun.star.uno.XInterface;
+import com.sun.star.uno.UnoRuntime;
+
+/**
+ * Testing <code>com.sun.star.accessibility.XAccessibleText</code>
+ * interface methods :
+ * <ul>
+ * <li><code> getCaretPosition()</code></li>
+ * <li><code> setCaretPosition()</code></li>
+ * <li><code> getCharacter()</code></li>
+ * <li><code> getCharacterAttributes()</code></li>
+ * <li><code> getCharacterBounds()</code></li>
+ * <li><code> getCharacterCount()</code></li>
+ * <li><code> getIndexAtPoint()</code></li>
+ * <li><code> getSelectedText()</code></li>
+ * <li><code> getSelectionStart()</code></li>
+ * <li><code> getSelectionEnd()</code></li>
+ * <li><code> setSelection()</code></li>
+ * <li><code> getText()</code></li>
+ * <li><code> getTextRange()</code></li>
+ * <li><code> getTextAtIndex()</code></li>
+ * <li><code> getTextBeforeIndex()</code></li>
+ * <li><code> getTextBehindIndex()</code></li>
+ * <li><code> copyText()</code></li>
+ * </ul>
+ * <p>This test needs the following object relations :</p>
+ * <ul>
+ * <li> <code>'XAccessibleText.Text'</code> (of type <code>String</code>)
+ * <b> optional </b> :
+ * the string presentation of component's text. If the relation
+ * is not specified, then text from method <code>getText()</code>
+ * is used.
+ * </li>
+ * </ul>
+ * @see com.sun.star.accessibility.XAccessibleText
+ */
+public class _XAccessibleText {
+
+ private final XAccessibleText oObj;
+ private final XMultiServiceFactory xMSF;
+
+ private Rectangle chBounds = null;
+ private int chCount = 0;
+
+ private String text = null;
+ private final String editOnly;
+
+
+ public _XAccessibleText(XInterface object, XMultiServiceFactory xMSF, String editOnly) {
+ this.oObj = UnoRuntime.queryInterface(XAccessibleText.class, object);
+ this.xMSF = xMSF;
+ this.editOnly = editOnly;
+ }
+
+
+ /**
+ * Calls the method and checks returned value.
+ * Has OK status if returned value is equal to <code>chCount - 1</code>.
+ * The following method tests are to be executed before:
+ * <ul>
+ * <li> <code>setCaretPosition()</code> </li>
+ * </ul>
+ */
+ public boolean _getCaretPosition() {
+
+ if (editOnly != null) {
+ System.out.println(editOnly);
+ return true;
+ }
+
+ boolean res = true;
+ if ( chCount > 0 ) {
+ try {
+ oObj.setCaretPosition(chCount - 1);
+ } catch (com.sun.star.lang.IndexOutOfBoundsException ie) {
+
+ }
+ int carPos = oObj.getCaretPosition();
+ System.out.println("getCaretPosition: " + carPos);
+ res = carPos == (chCount - 1);
+ }
+ return res;
+ }
+
+ /**
+ * Calls the method with the wrong index and with the correct index
+ * <code>chCount - 1</code>.
+ * Has OK status if exception was thrown for wrong index and
+ * if exception wasn't thrown for the correct index.
+ * The following method tests are to be executed before:
+ * <ul>
+ * <li> <code>getCharacterCount()</code> </li>
+ * </ul>
+ */
+ public boolean _setCaretPosition() {
+ boolean res = true;
+
+ try {
+ System.out.println("setCaretPosition(-1):");
+ oObj.setCaretPosition(-1);
+ res &= false;
+ System.out.println("exception was expected");
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("expected exception");
+ res &= true;
+ }
+
+ try {
+ System.out.println("setCaretPosition(chCount+1):");
+ oObj.setCaretPosition(chCount+1);
+ res &= false;
+ System.out.println("exception was expected");
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("expected exception");
+ res &= true;
+ }
+ if ( chCount > 0 ) {
+ try {
+ System.out.println("setCaretPosition(chCount - 1)");
+ oObj.setCaretPosition(chCount - 1);
+ res &= true;
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("unexpected exception");
+ e.printStackTrace();
+ res &= false;
+ }
+ }
+
+ return res;
+ }
+
+ /**
+ * Calls the method with the wrong index and with the correct indexes.
+ * Checks every character in the text.
+ * Has OK status if exception was thrown for wrong index,
+ * if exception wasn't thrown for the correct index and
+ * if every character is equal to corresponding character in the text.
+ * The following method tests are to be executed before:
+ * <ul>
+ * <li> <code>getCharacterCount()</code> </li>
+ * </ul>
+ */
+ public boolean _getCharacter() {
+ boolean res = true;
+
+ try {
+ System.out.println("getCharacter(-1)");
+ oObj.getCharacter(-1);
+ System.out.println("Exception was expected");
+ res = false;
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Expected exception");
+ res = true;
+ }
+
+ try {
+ System.out.println("getCharacter(chCount)");
+ oObj.getCharacter(chCount);
+ System.out.println("Exception was expected");
+ res &= false;
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Expected exception");
+ res &= true;
+ }
+
+ try {
+ System.out.println("Checking of every character in the text...");
+ boolean isEqCh = true;
+ for(int i = 0; i < chCount; i++) {
+ char ch = oObj.getCharacter(i);
+ isEqCh = ch == text.charAt(i);
+ res &= isEqCh;
+ if (!isEqCh) {
+ System.out.println("At the position " + i +
+ "was expected character: " + text.charAt(i));
+ System.out.println("but was returned: " + ch);
+ break;
+ }
+ }
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Unexpected exception");
+ e.printStackTrace();
+ res &= false;
+ }
+
+ return res;
+ }
+
+ /**
+ * Calls the method with the wrong indexes and with the correct index,
+ * checks a returned value.
+ * Has OK status if exception was thrown for the wrong indexes,
+ * if exception wasn't thrown for the correct index and
+ * if returned value isn't <code>null</code>.
+ * The following method tests are to be executed before:
+ * <ul>
+ * <li> <code>getCharacterCount()</code> </li>
+ * </ul>
+ */
+ public boolean _getCharacterAttributes() {
+ boolean res = true;
+
+ try {
+ System.out.println("getCharacterAttributes(-1)");
+ oObj.getCharacterAttributes(-1, new String[0]);
+ System.out.println("Exception was expected");
+ res &= false;
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Expected exception");
+ res &= true;
+ } catch(UnknownPropertyException e) {
+ System.out.println("unexpected exception => FAILED");
+ res &= false;
+ }
+
+ try {
+ System.out.println("getCharacterAttributes(chCount)");
+ oObj.getCharacterAttributes(chCount, new String[0]);
+ System.out.println("Exception was expected");
+ res &= false;
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Expected exception");
+ res &= true;
+ } catch(UnknownPropertyException e) {
+ System.out.println("unexpected exception => FAILED");
+ res &= false;
+ }
+
+ try {
+ if ( chCount > 0 ) {
+ System.out.println("getCharacterAttributes(chCount-1)");
+ PropertyValue[] props = oObj.getCharacterAttributes(chCount - 1, new String[0]);
+ res &= props != null;
+ }
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Unexpected exception");
+ e.printStackTrace();
+ res &= false;
+ } catch(UnknownPropertyException e) {
+ System.out.println("unexpected exception => FAILED");
+ res &= false;
+ }
+
+ return res;
+ }
+
+
+ /**
+ * Calls the method with the wrong indexes and with the correct index.
+ * checks and stores a returned value.
+ * Has OK status if exception was thrown for the wrong indexes,
+ * if exception wasn't thrown for the correct index and
+ * if returned value isn't <code>null</code>.
+ * The following method tests are to be executed before:
+ * <ul>
+ * <li> <code>getCharacterCount()</code> </li>
+ * </ul>
+ */
+ public boolean _getCharacterBounds() {
+ boolean res = true;
+
+ try {
+ System.out.println("getCharacterBounds(-1)");
+ oObj.getCharacterBounds(-1);
+ System.out.println("Exception was expected");
+ res &= false;
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Expected exception");
+ res &= true;
+ }
+
+ try {
+ System.out.println("getCharacterBounds(chCount)");
+ oObj.getCharacterBounds(chCount);
+ System.out.println("Exception was expected");
+ res &= false;
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Expected exception");
+ res &= true;
+ }
+
+ try {
+ if (chCount > 0) {
+ System.out.println("getCharacterBounds(chCount-1)");
+ chBounds = oObj.getCharacterBounds(chCount-1);
+ res &= chBounds != null;
+ System.out.println("rect: " + chBounds.X + ", " + chBounds.Y + ", " +
+ chBounds.Width + ", " + chBounds.Height);
+ }
+
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Unexpected exception");
+ e.printStackTrace();
+ res &= false;
+ }
+
+ return res;
+ }
+
+
+ /**
+ * Calls the method and stores a returned value to the variable
+ * <code>chCount</code>.
+ * Has OK status if a returned value is equal to the text length.
+ */
+ public boolean _getCharacterCount() {
+ chCount = oObj.getCharacterCount();
+ System.out.println("Character count:" + chCount);
+ boolean res = chCount == text.length();
+ return res;
+ }
+
+ /**
+ * Calls the method for an invalid point and for the point of rectangle
+ * returned by the method <code>getCharacterBounds()</code>.
+ * Has OK status if returned value is equal to <code>-1</code> for an
+ * invalid point and if returned value is equal to <code>chCount-1</code>
+ * for a valid point.
+ * The following method tests are to be executed before:
+ * <ul>
+ * <li> <code>getCharacterBounds()</code> </li>
+ * </ul>
+ */
+ public boolean _getIndexAtPoint() {
+
+ boolean res = true;
+ System.out.println("getIndexAtPoint(-1, -1):");
+ Point pt = new Point(-1, -1);
+ int index = oObj.getIndexAtPoint(pt);
+ System.out.println(Integer.toString(index));
+ res &= index == -1;
+
+ if (chBounds != null) {
+ pt = new Point(chBounds.X , chBounds.Y );
+ System.out.println("getIndexAtPoint(" + pt.X + ", " + pt.Y + "):");
+ index = oObj.getIndexAtPoint(pt);
+ System.out.println(Integer.toString(index));
+ res &= index == (chCount - 1);
+ }
+
+ return res;
+ }
+
+ /**
+ * Checks a returned values after different calls of the method
+ * <code>setSelection()</code>.
+ * The following method tests are to be executed before:
+ * <ul>
+ * <li> <code>setSelection()</code> </li>
+ * </ul>
+ */
+ public boolean _getSelectedText() {
+ if (editOnly != null) {
+ System.out.println(editOnly);
+ return true;
+ }
+
+ boolean res = true;
+
+ try {
+ System.out.println("setSelection(0, 0)");
+ oObj.setSelection(0, 0);
+ System.out.println("getSelectedText():");
+ String txt = oObj.getSelectedText();
+ System.out.println("'" + txt + "'");
+ res &= txt.length() == 0;
+
+ System.out.println("setSelection(0, chCount)");
+ oObj.setSelection(0, chCount);
+ System.out.println("getSelectedText():");
+ txt = oObj.getSelectedText();
+ System.out.println("'" + txt + "'");
+ res &= txt.equals(text);
+
+ if (chCount > 2) {
+ System.out.println("setSelection(1, chCount-1)");
+ oObj.setSelection(1, chCount - 1);
+ System.out.println("getSelectedText():");
+ txt = oObj.getSelectedText();
+ System.out.println("'" + txt + "'");
+ res &= txt.equals(text.substring(1, chCount - 1));
+ }
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Unexpected exception");
+ e.printStackTrace();
+ res &= false;
+ }
+
+ return res;
+ }
+
+ /**
+ * Checks a returned values after different calls of the method
+ * <code>setSelection()</code>.
+ * The following method tests are to be executed before:
+ * <ul>
+ * <li> <code>setSelection()</code> </li>
+ * </ul>
+ */
+ public boolean _getSelectionStart() {
+ if (editOnly != null) {
+ System.out.println(editOnly);
+ return true;
+ }
+
+ boolean res = true;
+
+ try {
+ System.out.println("setSelection(0, chCount)");
+ oObj.setSelection(0, chCount);
+ int start = oObj.getSelectionStart();
+ System.out.println("getSelectionStart():" + start);
+ res &= start == 0;
+
+ if (chCount > 2) {
+ System.out.println("setSelection(1, chCount-1)");
+ oObj.setSelection(1, chCount - 1);
+ start = oObj.getSelectionStart();
+ System.out.println("getSelectionStart():" + start);
+ res &= start == 1;
+ }
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Unexpected exception");
+ e.printStackTrace();
+ res &= false;
+ }
+
+ return res;
+ }
+
+ /**
+ * Checks a returned values after different calls of the method
+ * <code>setSelection()</code>.
+ * The following method tests are to be executed before:
+ * <ul>
+ * <li> <code>setSelection()</code> </li>
+ * </ul>
+ */
+ public boolean _getSelectionEnd() {
+ if (editOnly != null) {
+ System.out.println(editOnly);
+ return true;
+ }
+
+ boolean res = true;
+
+ try {
+ System.out.println("setSelection(0, chCount)");
+ oObj.setSelection(0, chCount);
+ int end = oObj.getSelectionEnd();
+ System.out.println("getSelectionEnd():" + end);
+ res &= end == chCount;
+
+ if (chCount > 2) {
+ System.out.println("setSelection(1, chCount-1)");
+ oObj.setSelection(1, chCount - 1);
+ end = oObj.getSelectionEnd();
+ System.out.println("getSelectionEnd():" + end);
+ res &= end == chCount - 1;
+ }
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Unexpected exception");
+ e.printStackTrace();
+ res &= false;
+ }
+
+ return res;
+ }
+
+ /**
+ * Calls the method with invalid parameters and with valid parameters.
+ * Has OK status if exception was thrown for invalid parameters,
+ * if exception wasn't thrown for valid parameters.
+ * The following method tests are to be executed before:
+ * <ul>
+ * <li> <code>getCharacterCount()</code> </li>
+ * </ul>
+ */
+ public boolean _setSelection() {
+ boolean res = true;
+ boolean locRes = true;
+
+ if (editOnly != null) {
+ System.out.println(editOnly);
+ return true;
+ }
+
+ try {
+ System.out.println("setSelection(-1, chCount-1):");
+ locRes = oObj.setSelection(-1, chCount - 1);
+ System.out.println(locRes + " exception was expected");
+ res &= !locRes;
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Expected exception");
+ res &= true;
+ }
+
+ try {
+ System.out.println("setSelection(0, chCount+1):");
+ locRes = oObj.setSelection(0, chCount + 1);
+ System.out.println(locRes + " exception was expected");
+ res &= !locRes;
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Expected exception");
+ res &= true;
+ }
+
+ try {
+ if (chCount > 2) {
+ System.out.println("setSelection(1, chCount-1):");
+ locRes = oObj.setSelection(1, chCount - 1);
+ System.out.println(Boolean.toString(locRes));
+ res &= locRes;
+
+ System.out.println("setSelection(chCount-1, 1):");
+ locRes = oObj.setSelection(chCount - 1, 1);
+ System.out.println(Boolean.toString(locRes));
+ res &= locRes;
+ }
+
+ if (chCount > 1) {
+ System.out.println("setSelection(0, chCount-1):");
+ locRes = oObj.setSelection(0, chCount-1);
+ System.out.println(Boolean.toString(locRes));
+ res &= locRes;
+
+ System.out.println("setSelection(chCount-1, 0):");
+ locRes = oObj.setSelection(chCount-1, 0);
+ System.out.println(Boolean.toString(locRes));
+ res &= locRes;
+ }
+
+ System.out.println("setSelection(0, 0):");
+ locRes = oObj.setSelection(0, 0);
+ System.out.println(Boolean.toString(locRes));
+ res &= locRes;
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Unexpected exception");
+ e.printStackTrace();
+ res &= false;
+ }
+
+ return res;
+ }
+
+ /**
+ * Calls the method and checks returned value.
+ * Has OK status if returned string is not null
+ * received from relation.
+ */
+ public boolean _getText() {
+ text = oObj.getText();
+ System.out.println("getText: '" + text + "'");
+ return (text != null);
+ }
+
+ /**
+ * Calls the method with invalid parameters and with valid parameters,
+ * checks returned values.
+ * Has OK status if exception was thrown for invalid parameters,
+ * if exception wasn't thrown for valid parameters and if returned values
+ * are equal to corresponding substrings of the text received by relation.
+ * The following method tests are to be executed before:
+ * <ul>
+ * <li> <code>getCharacterCount()</code> </li>
+ * </ul>
+ */
+ public boolean _getTextRange() {
+ boolean res = true;
+ boolean locRes = true;
+
+ try {
+ if (chCount > 3) {
+ System.out.println("getTextRange(1, chCount - 2): ");
+ String txtRange = oObj.getTextRange(1, chCount - 2);
+ System.out.println(txtRange);
+ locRes = txtRange.equals(text.substring(1, chCount - 2));
+ res &= locRes;
+ if (!locRes) {
+ System.out.println("Was expected: " +
+ text.substring(1, chCount - 2));
+ }
+ }
+
+ if (chCount > 0) {
+ System.out.println("getTextRange(0, chCount-1): ");
+ String txtRange = oObj.getTextRange(0, chCount-1);
+ System.out.println(txtRange);
+ locRes = txtRange.equals(text.substring(0, chCount - 1));
+ res &= locRes;
+ if (!locRes) {
+ System.out.println("Was expected: " +
+ text.substring(0, chCount - 1));
+ }
+
+ System.out.println("getTextRange(chCount, 0): ");
+ txtRange = oObj.getTextRange(chCount, 0);
+ System.out.println(txtRange);
+ res &= txtRange.equals(text);
+
+ System.out.println("getTextRange(0, 0): ");
+ txtRange = oObj.getTextRange(0, 0);
+ System.out.println(txtRange);
+ locRes = txtRange.length() == 0;
+ res &= locRes;
+ if (!locRes) {
+ System.out.println("Empty string was expected");
+ }
+ }
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Unexpected exception");
+ e.printStackTrace();
+ res &= false;
+ }
+
+ try {
+ System.out.println("getTextRange(-1, chCount - 1): ");
+ oObj.getTextRange(-1, chCount - 1);
+ System.out.println("Exception was expected");
+ res &= false;
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Expected exception");
+ res &= true;
+ }
+
+ try {
+ System.out.println("getTextRange(0, chCount + 1): ");
+ oObj.getTextRange(0, chCount + 1);
+ System.out.println("Exception was expected");
+ res &= false;
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Expected exception");
+ res &= true;
+ }
+
+ try {
+ System.out.println("getTextRange(chCount+1, -1): ");
+ oObj.getTextRange(chCount+1, -1);
+ System.out.println("Exception was expected");
+ res &= false;
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Expected exception");
+ res &= true;
+ }
+
+ return res;
+ }
+
+ /**
+ * Calls the method with invalid parameters and with valid parameters,
+ * checks returned values.
+ * Has OK status if exception was thrown for invalid parameters,
+ * if exception wasn't thrown for valid parameters and if returned values
+ * are equal to corresponding substrings of the text received by relation.
+ * The following method tests are to be executed before:
+ * <ul>
+ * <li> <code>getCharacterCount()</code> </li>
+ * </ul>
+ */
+ public boolean _getTextAtIndex() {
+ boolean res = true;
+
+ try {
+ System.out.println("getTextAtIndex(-1, AccessibleTextType.PARAGRAPH):");
+ oObj.getTextAtIndex(-1, AccessibleTextType.PARAGRAPH);
+ System.out.println("Exception was expected");
+ res &= false;
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Expected exception");
+ res &= true;
+ } catch(com.sun.star.lang.IllegalArgumentException e) {
+ System.out.println("Expected exception");
+ res &= true;
+ }
+
+ try {
+ System.out.println("getTextAtIndex(chCount+1," +
+ " AccessibleTextType.PARAGRAPH):");
+ oObj.getTextAtIndex(chCount + 1, AccessibleTextType.PARAGRAPH);
+ System.out.println("Exception was expected");
+ res &= false;
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Expected exception");
+ res &= true;
+ } catch(com.sun.star.lang.IllegalArgumentException e) {
+ System.out.println("Expected exception");
+ res &= true;
+ }
+
+
+ try {
+ if ( chCount > 0 ) {
+ System.out.println("getTextAtIndex(chCount," +
+ " AccessibleTextType.PARAGRAPH):");
+ TextSegment txt = oObj.getTextAtIndex(chCount,
+ AccessibleTextType.PARAGRAPH);
+ System.out.println("'" + txt.SegmentText + "'");
+ res &= txt.SegmentText.length() == 0;
+
+ System.out.println("getTextAtIndex(1," +
+ " AccessibleTextType.PARAGRAPH):");
+ txt = oObj.getTextAtIndex(1,
+ AccessibleTextType.PARAGRAPH);
+ System.out.println("'" + txt.SegmentText + "'");
+ res &= txt.SegmentText.equals(text);
+ }
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Unexpected exception");
+ e.printStackTrace();
+ res &= false;
+ } catch(com.sun.star.lang.IllegalArgumentException e) {
+ System.out.println("Unexpected exception");
+ res &= false;
+ }
+
+
+ return res;
+ }
+
+ /**
+ * Calls the method with invalid parameters and with valid parameters,
+ * checks returned values.
+ * Has OK status if exception was thrown for invalid parameters,
+ * if exception wasn't thrown for valid parameters and if returned values
+ * are equal to corresponding substrings of the text received by relation.
+ * The following method tests are to be executed before:
+ * <ul>
+ * <li> <code>getCharacterCount()</code> </li>
+ * </ul>
+ */
+ public boolean _getTextBeforeIndex() {
+ boolean res = true;
+
+ try {
+ System.out.println("getTextBeforeIndex(-1, AccessibleTextType.PARAGRAPH):");
+ oObj.getTextBeforeIndex(-1, AccessibleTextType.PARAGRAPH);
+ System.out.println("Exception was expected");
+ res &= false;
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Expected exception");
+ res &= true;
+ } catch(com.sun.star.lang.IllegalArgumentException e) {
+ System.out.println("Expected exception");
+ res &= true;
+ }
+
+
+ try {
+ System.out.println("getTextBeforeIndex(chCount+1, " +
+ "AccessibleTextType.PARAGRAPH):");
+ oObj.getTextBeforeIndex(chCount + 1, AccessibleTextType.PARAGRAPH);
+ System.out.println("Exception was expected");
+ res &= false;
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Expected exception");
+ res &= true;
+ } catch(com.sun.star.lang.IllegalArgumentException e) {
+ System.out.println("Expected exception");
+ res &= true;
+ }
+
+ TextSegment txt = null;
+ try {
+ if (chCount > 0) {
+ System.out.println("getTextBeforeIndex(chCount," +
+ " AccessibleTextType.PARAGRAPH):");
+ txt = oObj.getTextBeforeIndex(chCount,
+ AccessibleTextType.PARAGRAPH);
+ System.out.println("'" + txt.SegmentText + "'");
+ res &= txt.SegmentText.length() == chCount ;
+
+ System.out.println("getTextBeforeIndex(1," +
+ " AccessibleTextType.PARAGRAPH):");
+ txt = oObj.getTextBeforeIndex(1,
+ AccessibleTextType.PARAGRAPH);
+ System.out.println("'" + txt.SegmentText + "'");
+ res &= txt.SegmentText.length() == 0;
+ }
+
+ if (chCount > 2) {
+ System.out.println("getTextBeforeIndex(chCount-1," +
+ " AccessibleTextType.CHARACTER):");
+ txt = oObj.getTextBeforeIndex(chCount - 1,
+ AccessibleTextType.CHARACTER);
+ System.out.println("'" + txt.SegmentText + "'");
+ res &= txt.SegmentText.equals(text.substring(chCount - 2, chCount - 1));
+ System.out.println("getTextBeforeIndex(2," +
+ " AccessibleTextType.CHARACTER):");
+ txt = oObj.getTextBeforeIndex(2,
+ AccessibleTextType.CHARACTER);
+ System.out.println("'" + txt.SegmentText + "'");
+ res &= txt.SegmentText.equals(text.substring(1, 2));
+ }
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Unexpected exception");
+ e.printStackTrace();
+ res &= false;
+ } catch(com.sun.star.lang.IllegalArgumentException e) {
+ System.out.println("Unexpected exception");
+ res &= false;
+ }
+
+
+ return res;
+ }
+
+ /**
+ * Calls the method with invalid parameters and with valid parameters,
+ * checks returned values.
+ * Has OK status if exception was thrown for invalid parameters,
+ * if exception wasn't thrown for valid parameters and if returned values
+ * are equal to corresponding substrings of the text received by relation.
+ * The following method tests are to be executed before:
+ * <ul>
+ * <li> <code>getCharacterCount()</code> </li>
+ * </ul>
+ */
+ public boolean _getTextBehindIndex() {
+ boolean res = true;
+
+ try {
+ System.out.println("getTextBehindIndex(-1, AccessibleTextType.PARAGRAPH):");
+ oObj.getTextBehindIndex(-1, AccessibleTextType.PARAGRAPH);
+ System.out.println("Exception was expected");
+ res &= false;
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Expected exception");
+ res &= true;
+ } catch(com.sun.star.lang.IllegalArgumentException e) {
+ System.out.println("Expected exception");
+ res &= true;
+ }
+
+
+ try {
+ System.out.println("getTextBehindIndex(chCount+1, " +
+ "AccessibleTextType.PARAGRAPH):");
+ oObj.getTextBehindIndex(chCount + 1, AccessibleTextType.PARAGRAPH);
+ System.out.println("Exception was expected");
+ res &= false;
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Expected exception");
+ res &= true;
+ } catch(com.sun.star.lang.IllegalArgumentException e) {
+ System.out.println("Expected exception");
+ res &= true;
+ }
+
+
+ try {
+ if ( chCount > 0 ) {
+ System.out.println("getTextBehindIndex(chCount," +
+ " AccessibleTextType.PARAGRAPH):");
+ TextSegment txt = oObj.getTextBehindIndex(chCount,
+ AccessibleTextType.PARAGRAPH);
+ System.out.println("'" + txt.SegmentText + "'");
+ res &= txt.SegmentText.length() == 0;
+
+ System.out.println("getTextBehindIndex(chCount-1," +
+ " AccessibleTextType.PARAGRAPH):");
+ txt = oObj.getTextBehindIndex(chCount - 1,
+ AccessibleTextType.PARAGRAPH);
+ System.out.println("'" + txt.SegmentText + "'");
+ res &= txt.SegmentText.length() == 0;
+ }
+ if ( chCount > 1 ) {
+ System.out.println("getTextBehindIndex(1," +
+ " AccessibleTextType.CHARACTER):");
+ TextSegment txt = oObj.getTextBehindIndex(1,
+ AccessibleTextType.CHARACTER);
+ System.out.println("'" + txt.SegmentText + "'");
+ res &= txt.SegmentText.equals(text.substring(2, 3));
+ }
+ if (chCount > 2) {
+ System.out.println("getTextBehindIndex(chCount-2," +
+ " AccessibleTextType.CHARACTER):");
+ TextSegment txt = oObj.getTextBehindIndex(chCount - 2,
+ AccessibleTextType.CHARACTER);
+ System.out.println("'" + txt.SegmentText + "'");
+ res &= txt.SegmentText.equals(text.substring(chCount - 1, chCount));
+ }
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Unexpected exception");
+ e.printStackTrace();
+ res &= false;
+ } catch(com.sun.star.lang.IllegalArgumentException e) {
+ System.out.println("Unexpected exception");
+ res &= false;
+ }
+
+
+ return res;
+ }
+
+ /**
+ * Calls the method with invalid parameters and with valid parameter,
+ * checks returned values.
+ * Has OK status if exception was thrown for invalid parameters,
+ * if exception wasn't thrown for valid parameter and if returned value for
+ * valid parameter is equal to <code>true</code>.
+ */
+ public boolean _copyText() {
+ boolean res = true;
+ boolean locRes = true;
+
+ if (editOnly != null) {
+ System.out.println(editOnly);
+ return true;
+ }
+
+ try {
+ System.out.println("copyText(-1,chCount):");
+ oObj.copyText(-1, chCount);
+ System.out.println("Exception was expected");
+ res &= false;
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Expected exception");
+ res &= true;
+ }
+
+ try {
+ System.out.println("copyText(0,chCount+1):");
+ oObj.copyText(0, chCount + 1);
+ System.out.println("Exception was expected");
+ res &= false;
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Expected exception");
+ res &= true;
+ }
+
+ try {
+ System.out.println("copyText(0,chCount):");
+ locRes = oObj.copyText(0, chCount);
+ System.out.println(locRes);
+ res &= locRes;
+
+ String cbText = null;
+ try {
+ cbText =
+ util.SysUtils.getSysClipboardText(xMSF);
+ } catch (com.sun.star.uno.Exception e) {
+ System.out.println("Couldn't access system clipboard :");
+ e.printStackTrace();
+ }
+ System.out.println("Clipboard: '" + cbText + "'");
+ res &= text.equals(cbText);
+
+ if (chCount > 2) {
+ System.out.println("copyText(1,chCount-1):");
+ locRes = oObj.copyText(1, chCount - 1);
+ System.out.println(locRes);
+ res &= locRes;
+
+ try {
+ cbText = util.SysUtils.getSysClipboardText(xMSF);
+ } catch (com.sun.star.uno.Exception e) {
+ System.out.println("Couldn't access system clipboard :");
+ e.printStackTrace();
+ }
+
+ System.out.println("Clipboard: '" + cbText + "'");
+ res &= text.substring(1, chCount - 1).equals(cbText);
+ }
+
+ } catch(com.sun.star.lang.IndexOutOfBoundsException e) {
+ System.out.println("Unexpected exception");
+ e.printStackTrace();
+ res &= false;
+ }
+
+ return res;
+ }
+}
diff --git a/toolkit/qa/complex/toolkit/awtgrid/DummyColumn.java b/toolkit/qa/complex/toolkit/awtgrid/DummyColumn.java
new file mode 100644
index 0000000000..d86df3f1c3
--- /dev/null
+++ b/toolkit/qa/complex/toolkit/awtgrid/DummyColumn.java
@@ -0,0 +1,167 @@
+/*
+ * 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 .
+ */
+
+package complex.toolkit.awtgrid;
+
+import com.sun.star.awt.grid.XGridColumn;
+import com.sun.star.awt.grid.XGridColumnListener;
+import com.sun.star.lang.IllegalArgumentException;
+import com.sun.star.lang.XEventListener;
+import com.sun.star.style.HorizontalAlignment;
+import com.sun.star.util.XCloneable;
+
+/**
+ * a dummy implementation of css.awt.grid.XGridColumn
+ */
+public class DummyColumn implements XGridColumn
+{
+ public Object getIdentifier()
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public void setIdentifier( Object o )
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public int getColumnWidth()
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public void setColumnWidth( int i )
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public int getMinWidth()
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public void setMinWidth( int i )
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public int getMaxWidth()
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public void setMaxWidth( int i )
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public boolean getResizeable()
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public void setResizeable( boolean bln )
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public int getFlexibility()
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public void setFlexibility( int i ) throws IllegalArgumentException
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public HorizontalAlignment getHorizontalAlign()
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public void setHorizontalAlign( HorizontalAlignment ha )
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public String getTitle()
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public void setTitle( String string )
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public String getHelpText()
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public void setHelpText( String string )
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public int getIndex()
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public int getDataColumnIndex()
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public void setDataColumnIndex( int i )
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public void addGridColumnListener( XGridColumnListener xl )
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public void removeGridColumnListener( XGridColumnListener xl )
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public void dispose()
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public void addEventListener( XEventListener xl )
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public void removeEventListener( XEventListener xl )
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
+ public XCloneable createClone()
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+}
diff --git a/toolkit/qa/complex/toolkit/awtgrid/GridDataListener.java b/toolkit/qa/complex/toolkit/awtgrid/GridDataListener.java
new file mode 100644
index 0000000000..800727bb34
--- /dev/null
+++ b/toolkit/qa/complex/toolkit/awtgrid/GridDataListener.java
@@ -0,0 +1,107 @@
+/*
+ * 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 .
+ */
+
+package complex.toolkit.awtgrid;
+
+import com.sun.star.awt.grid.GridDataEvent;
+import com.sun.star.awt.grid.XGridDataListener;
+import com.sun.star.lang.EventObject;
+import static org.junit.Assert.*;
+
+final public class GridDataListener implements XGridDataListener
+{
+ public void rowsInserted( GridDataEvent i_event )
+ {
+ assertNull( m_rowInsertionEvent );
+ m_rowInsertionEvent = i_event;
+ }
+
+ public void rowsRemoved( GridDataEvent i_event )
+ {
+ assertNull( m_rowRemovalEvent );
+ m_rowRemovalEvent = i_event;
+ }
+
+ public void dataChanged( GridDataEvent i_event )
+ {
+ assertNull( m_dataChangeEvent );
+ m_dataChangeEvent = i_event;
+ }
+
+ public void rowHeadingChanged( GridDataEvent i_event )
+ {
+ assertNull( m_rowHeadingChangeEvent );
+ m_rowHeadingChangeEvent = i_event;
+ }
+
+ public void disposing( EventObject eo )
+ {
+ m_disposed = true;
+ }
+
+ public final GridDataEvent assertSingleRowInsertionEvent()
+ {
+ assertNotNull( m_rowInsertionEvent );
+ assertNull( m_rowRemovalEvent );
+ assertNull( m_dataChangeEvent );
+ assertNull( m_rowHeadingChangeEvent );
+ assertFalse( m_disposed );
+ return m_rowInsertionEvent;
+ }
+
+ public final GridDataEvent assertSingleRowRemovalEvent()
+ {
+ assertNull( m_rowInsertionEvent );
+ assertNotNull( m_rowRemovalEvent );
+ assertNull( m_dataChangeEvent );
+ assertNull( m_rowHeadingChangeEvent );
+ assertFalse( m_disposed );
+ return m_rowRemovalEvent;
+ }
+
+ public final GridDataEvent assertSingleDataChangeEvent()
+ {
+ assertNull( m_rowInsertionEvent );
+ assertNull( m_rowRemovalEvent );
+ assertNotNull( m_dataChangeEvent );
+ assertNull( m_rowHeadingChangeEvent );
+ assertFalse( m_disposed );
+ return m_dataChangeEvent;
+ }
+
+ public final GridDataEvent assertSingleRowHeadingChangeEvent()
+ {
+ assertNull( m_rowInsertionEvent );
+ assertNull( m_rowRemovalEvent );
+ assertNull( m_dataChangeEvent );
+ assertNotNull( m_rowHeadingChangeEvent );
+ assertFalse( m_disposed );
+ return m_rowHeadingChangeEvent;
+ }
+
+ public final void reset()
+ {
+ m_rowInsertionEvent = m_rowRemovalEvent = m_dataChangeEvent = m_rowHeadingChangeEvent = null;
+ // m_disposed is not reset intentionally
+ }
+ private GridDataEvent m_rowInsertionEvent = null;
+ private GridDataEvent m_rowRemovalEvent = null;
+ private GridDataEvent m_dataChangeEvent = null;
+ private GridDataEvent m_rowHeadingChangeEvent = null;
+ private boolean m_disposed = false;
+}
diff --git a/toolkit/qa/complex/toolkit/awtgrid/TMutableGridDataModel.java b/toolkit/qa/complex/toolkit/awtgrid/TMutableGridDataModel.java
new file mode 100644
index 0000000000..83878e18c7
--- /dev/null
+++ b/toolkit/qa/complex/toolkit/awtgrid/TMutableGridDataModel.java
@@ -0,0 +1,449 @@
+/*
+ * 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 .
+ */
+
+package complex.toolkit.awtgrid;
+
+import com.sun.star.awt.grid.GridDataEvent;
+import com.sun.star.awt.grid.XMutableGridDataModel;
+import com.sun.star.lang.IllegalArgumentException;
+import com.sun.star.lang.IndexOutOfBoundsException;
+import static org.junit.Assert.*;
+import static complex.toolkit.Assert.*;
+
+/** test for the <code>css.awt.grid.XMutableGridData</code> interface
+ *
+ */
+public class TMutableGridDataModel
+{
+ public TMutableGridDataModel( final XMutableGridDataModel i_dataModel )
+ {
+ m_dataModel = i_dataModel;
+
+ m_listener = new GridDataListener();
+ m_dataModel.addGridDataListener( m_listener );
+ }
+
+ /*
+ * tests the XMutableGridDataModel.addRow method
+ */
+ public void testAddRow() throws IndexOutOfBoundsException
+ {
+ m_dataModel.addRow( m_rowHeadings[0], m_rowValues[0] );
+ GridDataEvent event = m_listener.assertSingleRowInsertionEvent();
+ m_listener.reset();
+ assertEquals( "row insertion: wrong FirstRow (1)", 0, event.FirstRow );
+ assertEquals( "row insertion: wrong LastRow (1)", 0, event.LastRow );
+ impl_assertRowData( 0 );
+
+ m_dataModel.addRow( m_rowHeadings[1], m_rowValues[1] );
+ event = m_listener.assertSingleRowInsertionEvent();
+ m_listener.reset();
+ assertEquals( "row insertion: wrong FirstRow (2)", 1, event.FirstRow );
+ assertEquals( "row insertion: wrong LastRow (2)", 1, event.LastRow );
+ impl_assertRowData( 1 );
+ }
+
+ /**
+ * tests the XMutableGridDataModel.addRows method
+ */
+ public void testAddRows() throws IndexOutOfBoundsException, IllegalArgumentException
+ {
+ assertEquals( "precondition not met: call this directly after testAddRow, please!", 2, m_dataModel.getRowCount() );
+
+ m_dataModel.addRows(
+ new Object[] { m_rowHeadings[2], m_rowHeadings[3], m_rowHeadings[4] },
+ new Object[][] { m_rowValues[2], m_rowValues[3], m_rowValues[4] } );
+ GridDataEvent event = m_listener.assertSingleRowInsertionEvent();
+ assertEquals( "row insertion: wrong FirstRow (1)", 2, event.FirstRow );
+ assertEquals( "row insertion: wrong LastRow (1)", 4, event.LastRow );
+ m_listener.reset();
+
+ assertEquals( "data model's row count is not adjusted when adding rows", m_rowValues.length, m_dataModel.getRowCount() );
+ assertEquals( "data model's column count is not adjusted when adding rows", m_rowValues[0].length, m_dataModel.getColumnCount() );
+ for ( int row=0; row<m_rowValues.length; ++row )
+ {
+ for ( int col=0; col<m_rowValues[row].length; ++col )
+ {
+ assertEquals( "added row values are not preserved",
+ m_rowValues[row][col], m_dataModel.getCellData( col, row ) );
+ }
+ }
+
+ assertException( "addRows is expected to throw when invoked with different-sized arrays",
+ m_dataModel, "addRows", new Object[] { new Object[0], new Object[1][2] }, IllegalArgumentException.class );
+ }
+
+ /**
+ * tests the XMutableGridDataModel.insertRow method
+ */
+ public void testInsertRow() throws IndexOutOfBoundsException
+ {
+ int expectedRowCount = m_rowValues.length;
+ assertEquals( "precondition not met: call this directly after testAddRows, please!", expectedRowCount, m_dataModel.getRowCount() );
+
+ // inserting some row somewhere between the other rows
+ final Object heading = "inbetweenRow";
+ final Object[] inbetweenRow = new Object[] { "foo", "bar", 3, 4, 5 };
+ final int insertionPos = 2;
+ m_dataModel.insertRow( insertionPos, heading, inbetweenRow );
+ ++expectedRowCount;
+ assertEquals( "inserting a row is expected to increment the row count",
+ expectedRowCount, m_dataModel.getRowCount() );
+
+ final GridDataEvent event = m_listener.assertSingleRowInsertionEvent();
+ assertEquals( "inserting a row results in wrong FirstRow being notified", insertionPos, event.FirstRow );
+ assertEquals( "inserting a row results in wrong LastRow being notified", insertionPos, event.LastRow );
+ m_listener.reset();
+
+ for ( int row=0; row<expectedRowCount; ++row )
+ {
+ final Object[] actualRowData = m_dataModel.getRowData( row );
+ final Object[] expectedRowData =
+ ( row < insertionPos )
+ ? m_rowValues[ row ]
+ : ( row == insertionPos )
+ ? inbetweenRow
+ : m_rowValues[ row - 1 ];
+ assertArrayEquals( "row number " + row + " has wrong content after inserting a row",
+ expectedRowData, actualRowData );
+
+ final Object actualHeading = m_dataModel.getRowHeading(row);
+ final Object expectedHeading =
+ ( row < insertionPos )
+ ? m_rowHeadings[ row ]
+ : ( row == insertionPos )
+ ? heading
+ : m_rowHeadings[ row - 1 ];
+ assertEquals( "row " + row + " has a wrong heading after invoking insertRow",
+ expectedHeading, actualHeading );
+ }
+
+ // exceptions
+ assertException( "inserting a row at a position > rowCount is expected to throw",
+ m_dataModel, "insertRow",
+ new Class[] { Integer.class, Object.class, Object[].class },
+ new Object[] { expectedRowCount + 1, "", new Object[] { "1", 2, 3 } },
+ IndexOutOfBoundsException.class );
+ assertException( "inserting a row at a position < 0 is expected to throw",
+ m_dataModel, "insertRow",
+ new Class[] { Integer.class, Object.class, Object[].class },
+ new Object[] { -1, "", new Object[] { "1", 2, 3 } },
+ IndexOutOfBoundsException.class );
+
+ // remove the row, to create the situation expected by the next test
+ m_dataModel.removeRow( insertionPos );
+ m_listener.reset();
+ }
+
+ /**
+ * tests the XMutableGridDataModel.insertRows method
+ */
+ public void testInsertRows() throws IndexOutOfBoundsException, IllegalArgumentException
+ {
+ int expectedRowCount = m_rowValues.length;
+ assertEquals( "precondition not met: call this directly after testInsertRow, please!", expectedRowCount, m_dataModel.getRowCount() );
+
+ // inserting some rows somewhere between the other rows
+ final int insertionPos = 3;
+ final Object[] rowHeadings = new Object[] { "A", "B", "C" };
+ final Object[][] rowData = new Object[][] {
+ new Object[] { "A", "B", "C", "D", "E" },
+ new Object[] { "J", "I", "H", "G", "F" },
+ new Object[] { "K", "L", "M", "N", "O" }
+ };
+ final int insertedRowCount = rowData.length;
+ assertEquals( "invalid test data", rowHeadings.length, insertedRowCount );
+
+ m_dataModel.insertRows( insertionPos, rowHeadings, rowData );
+ expectedRowCount += insertedRowCount;
+
+ final GridDataEvent event = m_listener.assertSingleRowInsertionEvent();
+ assertEquals( "inserting multiple rows results in wrong FirstRow being notified",
+ insertionPos, event.FirstRow );
+ assertEquals( "inserting multiple rows results in wrong LastRow being notified",
+ insertionPos + insertedRowCount - 1, event.LastRow );
+ m_listener.reset();
+
+ for ( int row=0; row<expectedRowCount; ++row )
+ {
+ final Object[] actualRowData = m_dataModel.getRowData( row );
+ final Object[] expectedRowData =
+ ( row < insertionPos )
+ ? m_rowValues[ row ]
+ : ( row >= insertionPos ) && ( row < insertionPos + insertedRowCount )
+ ? rowData[ row - insertionPos ]
+ : m_rowValues[ row - insertedRowCount ];
+ assertArrayEquals( "row number " + row + " has wrong content after inserting multiple rows",
+ expectedRowData, actualRowData );
+
+ final Object actualHeading = m_dataModel.getRowHeading(row);
+ final Object expectedHeading =
+ ( row < insertionPos )
+ ? m_rowHeadings[ row ]
+ : ( row >= insertionPos ) && ( row < insertionPos + insertedRowCount )
+ ? rowHeadings[ row - insertionPos ]
+ : m_rowHeadings[ row - insertedRowCount ];
+ assertEquals( "row " + row + " has a wrong heading after invoking insertRows",
+ expectedHeading, actualHeading );
+ }
+
+ // exceptions
+ assertException( "inserting multiple rows at a position > rowCount is expected to throw an IndexOutOfBoundsException",
+ m_dataModel, "insertRows",
+ new Class[] { Integer.class, Object[].class, Object[][].class },
+ new Object[] { expectedRowCount + 1, new Object[0], new Object[][] { } },
+ IndexOutOfBoundsException.class );
+ assertException( "inserting multiple rows at a position < 0 is expected to throw an IndexOutOfBoundsException",
+ m_dataModel, "insertRows",
+ new Class[] { Integer.class, Object[].class, Object[][].class },
+ new Object[] { -1, new Object[0], new Object[][] { } },
+ IndexOutOfBoundsException.class );
+ assertException( "inserting multiple rows with inconsistent array lengths is expected to throw an IllegalArgumentException",
+ m_dataModel, "insertRows",
+ new Class[] { Integer.class, Object[].class, Object[][].class },
+ new Object[] { 0, new Object[0], new Object[][] { new Object[0] } },
+ IllegalArgumentException.class );
+
+ // remove the row, to create the situation expected by the next test
+ for ( int i=0; i<insertedRowCount; ++i )
+ {
+ m_dataModel.removeRow( insertionPos );
+ m_listener.reset();
+ }
+ }
+
+ /**
+ * tests the XMutableGridDataModel.removeRow method
+ */
+ public void testRemoveRow() throws IndexOutOfBoundsException
+ {
+ assertEquals( "precondition not met: call this directly after testAddRows, please!", m_rowValues.length, m_dataModel.getRowCount() );
+
+ final int rowToRemove = 2;
+ m_dataModel.removeRow( rowToRemove );
+ GridDataEvent event = m_listener.assertSingleRowRemovalEvent();
+ assertEquals( "incorrect notification of row removal (FirstRow)", rowToRemove, event.FirstRow );
+ assertEquals( "incorrect notification of row removal (LastRow)", rowToRemove, event.LastRow );
+ m_listener.reset();
+
+ assertEquals( "data model's row count does not reflect the removed row", m_rowValues.length - 1, m_dataModel.getRowCount() );
+ for ( int row = rowToRemove; row<m_rowValues.length-1; ++row )
+ {
+ for ( int col=0; col<m_rowValues[row].length; ++col )
+ {
+ assertEquals( "unexpected row values after removing a row (col: " + col + ", row: " + row + ")",
+ m_rowValues[row+1][col], m_dataModel.getCellData( col, row ) );
+ }
+ }
+
+ assertException( "removeRow silently ignores an invalid index (1)",
+ m_dataModel, "removeRow", new Object[] { -1 }, IndexOutOfBoundsException.class );
+ assertException( "removeRow silently ignores an invalid index (2)",
+ m_dataModel, "removeRow", new Object[] { m_dataModel.getRowCount() }, IndexOutOfBoundsException.class );
+ }
+
+ /**
+ * tests the XMutableGridDataModel.removeAllRows method
+ */
+ public void testRemoveAllRows()
+ {
+ assertEquals( "precondition not met: call this directly after testRemoveRow, please!", m_rowValues.length - 1, m_dataModel.getRowCount() );
+
+ m_dataModel.removeAllRows();
+ final GridDataEvent event = m_listener.assertSingleRowRemovalEvent();
+ if ( event.FirstRow != -1 )
+ { // notifying "-1" is allowed, this means "all rows affected", by definition
+ assertEquals( "removeAllRows is not notifying properly (1)", 0, event.FirstRow );
+ assertEquals( "removeAllRows is not notifying properly (2)", m_rowValues.length - 1, event.LastRow );
+ }
+ m_listener.reset();
+ }
+
+ /**
+ * tests the XMutableGridDataModel.updateCellData method
+ */
+ public void testUpdateCellData() throws IndexOutOfBoundsException, IllegalArgumentException
+ {
+ assertEquals( "precondition not met: call this directly after testRemoveAllRows, please!", 0, m_dataModel.getRowCount() );
+
+ m_dataModel.addRows( m_rowHeadings, m_rowValues );
+ m_listener.assertSingleRowInsertionEvent();
+ m_listener.reset();
+
+ final Object[][] modifyValues = new Object[][] {
+ new Object[] { 2, 1, "text" },
+ new Object[] { 3, 0, null },
+ new Object[] { 0, 4, Double.valueOf( 33.0 ) }
+ };
+ for ( int i = 0; i < modifyValues.length; ++i )
+ {
+ final int row = ((Integer)modifyValues[i][0]).intValue();
+ final int col = ((Integer)modifyValues[i][1]).intValue();
+ final Object value = modifyValues[i][2];
+ m_dataModel.updateCellData( col, row, value );
+
+ final GridDataEvent event = m_listener.assertSingleDataChangeEvent();
+ assertEquals( "data change notification: FirstRow is invalid", row, event.FirstRow );
+ assertEquals( "data change notification: LastRow is invalid", row, event.LastRow );
+ assertEquals( "data change notification: FirstColumn is invalid", col, event.FirstColumn );
+ assertEquals( "data change notification: LastColumn is invalid", col, event.LastColumn );
+ m_listener.reset();
+
+ assertEquals( "data change at (" + col + ", " + row + ") not successful", value, m_dataModel.getCellData( col, row ) );
+ }
+
+ assertException( "updateCellData silently ignores an invalid index (1)",
+ m_dataModel, "updateCellData", new Class[] { int.class, int.class, Object.class },
+ new Object[] { -1, -1, "text" }, IndexOutOfBoundsException.class );
+ assertException( "updateCellData silently ignores an invalid index (2)",
+ m_dataModel, "updateCellData", new Class[] { int.class, int.class, Object.class },
+ new Object[] { 0, m_dataModel.getRowCount(), "text" }, IndexOutOfBoundsException.class );
+ assertException( "updateCellData silently ignores an invalid index (3)",
+ m_dataModel, "updateCellData", new Class[] { int.class, int.class, Object.class },
+ new Object[] { m_dataModel.getColumnCount(), 0, "text" }, IndexOutOfBoundsException.class );
+ }
+
+ /**
+ * tests the XMutableGridDataModel.updateRowData method
+ */
+ public void testUpdateRowData() throws IndexOutOfBoundsException, IllegalArgumentException
+ {
+ assertEquals( "precondition not met: call this directly after testRemoveAllRows, please!", m_rowValues.length, m_dataModel.getRowCount() );
+
+ // get data from before the update
+ final Object[][] preUpdateValues = impl_getCurrentData();
+
+ // do the update
+ final int[] colIndexes = new int[] {
+ 0, 3, 4
+ };
+ final Object[] values = new Object[] {
+ 13, null, 42.0
+ };
+ final int rowToUpdate = 2;
+ m_dataModel.updateRowData( colIndexes, rowToUpdate, values );
+ final GridDataEvent event = m_listener.assertSingleDataChangeEvent();
+ assertEquals( "row update notification: FirstRow is invalid", rowToUpdate, event.FirstRow );
+ assertEquals( "row update notification: LastRow is invalid", rowToUpdate, event.LastRow );
+ assertEquals( "row update notification: FirstColumn is invalid", 0, event.FirstColumn );
+ assertEquals( "row update notification: LastColumn is invalid", 4, event.LastColumn );
+ m_listener.reset();
+
+ // reflect the changes made in the pre-update data
+ for ( int i=0; i<colIndexes.length; ++i )
+ {
+ preUpdateValues[rowToUpdate][colIndexes[i]] = values[i];
+ }
+
+ // get data from after the update
+ final Object[][] postUpdateValues = impl_getCurrentData();
+
+ // ensure both the manually updated pre-update data and the post-update data are identical
+ assertArrayEquals( preUpdateValues, postUpdateValues );
+
+
+ assertException( "updateRowData silently ignores an invalid index (1)",
+ m_dataModel, "updateRowData", new Class[] { int[].class, int.class, Object[].class },
+ new Object[] { new int[] { -1 }, 0, new Object[] { "text" } }, IndexOutOfBoundsException.class );
+ assertException( "updateRowData silently ignores an invalid index (2)",
+ m_dataModel, "updateRowData", new Class[] { int[].class, int.class, Object[].class },
+ new Object[] { new int[] { 0 }, -1, new Object[] { "" } }, IndexOutOfBoundsException.class );
+ assertException( "updateRowData silently ignores different-sized arrays",
+ m_dataModel, "updateRowData", new Class[] { int[].class, int.class, Object[].class },
+ new Object[] { new int[] { 0, 0 }, 0, new Object[] { "" } }, IllegalArgumentException.class );
+ }
+
+ /**
+ * tests the XMutableGridDataModel.updateRowHeading method
+ */
+ public void testUpdateRowHeading() throws IndexOutOfBoundsException
+ {
+ assertEquals( "precondition not met: call this directly after testUpdateRowData, please!", m_rowValues.length, m_dataModel.getRowCount() );
+
+ final Object[] preUpdateHeadings = impl_getCurrentRowHeadings();
+
+ final int rowToUpdate = 2;
+ final String valueToUpdate = "some text";
+ m_dataModel.updateRowHeading( rowToUpdate, valueToUpdate );
+ final GridDataEvent event = m_listener.assertSingleRowHeadingChangeEvent();
+ assertEquals( "row heading update notification: FirstRow is invalid", rowToUpdate, event.FirstRow );
+ assertEquals( "row heading update notification: FirstRow is invalid", rowToUpdate, event.LastRow );
+ m_listener.reset();
+
+ preUpdateHeadings[rowToUpdate] = valueToUpdate;
+
+ final Object[] postUpdateHeadings = impl_getCurrentRowHeadings();
+ assertArrayEquals( preUpdateHeadings, postUpdateHeadings );
+
+ assertException( "updateRowHeading silently ignores an invalid index",
+ m_dataModel, "updateRowHeading", new Class[] { int.class, Object.class },
+ new Object[] { -1, "" }, IndexOutOfBoundsException.class );
+ }
+
+ public void cleanup()
+ {
+ m_dataModel.removeGridDataListener( m_listener );
+ }
+
+ private Object[][] impl_getCurrentData() throws IndexOutOfBoundsException
+ {
+ final int rowCount = m_dataModel.getRowCount();
+ final int colCount = m_dataModel.getColumnCount();
+ final Object[][] data = new Object[rowCount][colCount];
+ for ( int row=0; row<rowCount; ++row )
+ {
+ for ( int col=0; col<colCount; ++col )
+ {
+ data[row][col] = m_dataModel.getCellData( col, row );
+ }
+ }
+ return data;
+ }
+
+ private Object[] impl_getCurrentRowHeadings() throws IndexOutOfBoundsException
+ {
+ final int rowCount = m_dataModel.getRowCount();
+ final Object[] headings = new Object[rowCount];
+ for ( int row=0; row<rowCount; ++row )
+ headings[row] = m_dataModel.getRowHeading( row );
+ return headings;
+ }
+
+ private void impl_assertRowData( final int i_rowIndex ) throws IndexOutOfBoundsException
+ {
+ for ( int i=0; i<m_rowValues[i_rowIndex].length; ++i )
+ {
+ assertEquals( m_rowValues[i_rowIndex][i], m_dataModel.getCellData( i, i_rowIndex ) );
+ }
+ }
+
+ private final XMutableGridDataModel m_dataModel;
+ private final GridDataListener m_listener;
+
+ private static final Object[][] m_rowValues = new Object[][] {
+ new Object[] { 1, 2, "3", 4, 5 },
+ new Object[] { 2, 3, 4, "5", 6 },
+ new Object[] { "3", 4, 5, 6, 7 },
+ new Object[] { 4, 5, 6, 7, "8" },
+ new Object[] { 5, "6", 7, 8, 9 },
+ };
+
+ private static final Object[] m_rowHeadings = new Object[] {
+ "1", 2, 3.0, "4", (float)5.0
+ };
+}
diff --git a/toolkit/qa/cppunit/Dialog.cxx b/toolkit/qa/cppunit/Dialog.cxx
new file mode 100644
index 0000000000..6ddf3f7258
--- /dev/null
+++ b/toolkit/qa/cppunit/Dialog.cxx
@@ -0,0 +1,73 @@
+/* -*- 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/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+#include <unotest/macros_test.hxx>
+
+#include <com/sun/star/awt/UnoControlDialog.hpp>
+#include <com/sun/star/awt/XUnoControlDialog.hpp>
+#include <com/sun/star/awt/XControlModel.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XMultiComponentFactory.hpp>
+
+#include <comphelper/processfactory.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <vcl/vclptr.hxx>
+#include <vcl/window.hxx>
+
+using namespace css;
+
+namespace
+{
+/// Test dialogs constructed via UNO
+class DialogTest : public test::BootstrapFixture, public unotest::MacrosTest
+{
+protected:
+ uno::Reference<uno::XComponentContext> mxContext;
+
+public:
+ virtual void setUp() override;
+};
+
+void DialogTest::setUp()
+{
+ test::BootstrapFixture::setUp();
+
+ mxContext.set(comphelper::getComponentContext(getMultiServiceFactory()));
+}
+
+CPPUNIT_TEST_FIXTURE(DialogTest, testDialogSizeable)
+{
+ uno::Reference<awt::XDialog> xDialog;
+ uno::Reference<lang::XMultiComponentFactory> xFactory(mxContext->getServiceManager(),
+ uno::UNO_SET_THROW);
+ uno::Reference<awt::XControlModel> xControlModel(
+ xFactory->createInstanceWithContext("com.sun.star.awt.UnoControlDialogModel", mxContext),
+ uno::UNO_QUERY_THROW);
+
+ uno::Reference<beans::XPropertySet> xPropSet(xControlModel, uno::UNO_QUERY_THROW);
+ xPropSet->setPropertyValue("Sizeable", uno::Any(true));
+
+ uno::Reference<awt::XUnoControlDialog> xControl = awt::UnoControlDialog::create(mxContext);
+ xControl->setModel(xControlModel);
+ xControl->setVisible(true);
+ xDialog.set(xControl, uno::UNO_QUERY_THROW);
+ xDialog->execute();
+
+ VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xControl->getPeer());
+ CPPUNIT_ASSERT(pWindow);
+ CPPUNIT_ASSERT(pWindow->GetStyle() & WB_SIZEABLE);
+
+ xDialog->endExecute();
+ css::uno::Reference<css::lang::XComponent>(xDialog, css::uno::UNO_QUERY_THROW)->dispose();
+ css::uno::Reference<css::lang::XComponent>(xControlModel, css::uno::UNO_QUERY_THROW)->dispose();
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/qa/cppunit/EventContainer.cxx b/toolkit/qa/cppunit/EventContainer.cxx
new file mode 100644
index 0000000000..ad62f93105
--- /dev/null
+++ b/toolkit/qa/cppunit/EventContainer.cxx
@@ -0,0 +1,84 @@
+/* -*- 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/.
+ */
+
+#include <test/bootstrapfixture.hxx>
+
+#include <com/sun/star/awt/XControlModel.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XMultiComponentFactory.hpp>
+#include <com/sun/star/script/ScriptEventDescriptor.hpp>
+#include <com/sun/star/script/XScriptEventsSupplier.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+
+#include <comphelper/processfactory.hxx>
+
+using namespace css;
+using namespace css::awt;
+using namespace css::container;
+using namespace css::lang;
+using namespace css::script;
+using namespace css::uno;
+
+namespace
+{
+/// Test EventContainer class
+class EventContainerTest : public test::BootstrapFixture
+{
+protected:
+ Reference<XComponentContext> mxContext;
+
+public:
+ virtual void setUp() override;
+};
+
+void EventContainerTest::setUp()
+{
+ test::BootstrapFixture::setUp();
+
+ mxContext.set(comphelper::getComponentContext(getMultiServiceFactory()));
+}
+
+// Make sure that EventContainer keeps insertion order, and does not reorder its elements.
+// Otherwise this would break macro signatures.
+CPPUNIT_TEST_FIXTURE(EventContainerTest, testInsertOrder)
+{
+ Reference<XMultiComponentFactory> xFactory(mxContext->getServiceManager(), UNO_SET_THROW);
+ Reference<XControlModel> xControlModel(
+ xFactory->createInstanceWithContext("com.sun.star.awt.UnoControlDialogModel", mxContext),
+ UNO_QUERY_THROW);
+
+ Reference<beans::XPropertySet> xPropSet(xControlModel, UNO_QUERY_THROW);
+
+ Reference<XScriptEventsSupplier> xEventsSupplier(xPropSet, UNO_QUERY_THROW);
+ Reference<XNameContainer> xEvents(xEventsSupplier->getEvents(), UNO_SET_THROW);
+ script::ScriptEventDescriptor descr1;
+ script::ScriptEventDescriptor descr2;
+ script::ScriptEventDescriptor descr3;
+ script::ScriptEventDescriptor descr4;
+ xEvents->insertByName("b", Any(descr1));
+ xEvents->insertByName("a", Any(descr2));
+ xEvents->insertByName("1", Any(descr3));
+ xEvents->insertByName("A", Any(descr4));
+
+ Sequence<OUString> aEventNames(xEvents->getElementNames());
+ sal_Int32 nEventCount = aEventNames.getLength();
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(4), nEventCount);
+
+ CPPUNIT_ASSERT_EQUAL(OUString("b"), aEventNames[0]);
+ CPPUNIT_ASSERT_EQUAL(OUString("a"), aEventNames[1]);
+ CPPUNIT_ASSERT_EQUAL(OUString("1"), aEventNames[2]);
+ CPPUNIT_ASSERT_EQUAL(OUString("A"), aEventNames[3]);
+
+ css::uno::Reference<css::lang::XComponent>(xControlModel, css::uno::UNO_QUERY_THROW)->dispose();
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/toolkit/qa/cppunit/UnitConversion.cxx b/toolkit/qa/cppunit/UnitConversion.cxx
new file mode 100644
index 0000000000..5e28667f5a
--- /dev/null
+++ b/toolkit/qa/cppunit/UnitConversion.cxx
@@ -0,0 +1,215 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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 <test/bootstrapfixture.hxx>
+
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/util/MeasureUnit.hpp>
+#include <com/sun/star/awt/VclWindowPeerAttribute.hpp>
+#include <com/sun/star/awt/WindowAttribute.hpp>
+#include <com/sun/star/awt/WindowDescriptor.hpp>
+#include <com/sun/star/awt/XUnitConversion.hpp>
+#include <com/sun/star/awt/XWindowPeer.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+using namespace ::com::sun::star;
+
+namespace
+{
+class ToolkitTest : public test::BootstrapFixture
+{
+public:
+ void testXUnitConversion();
+
+ CPPUNIT_TEST_SUITE(ToolkitTest);
+ CPPUNIT_TEST(testXUnitConversion);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+/**
+ * Creates a floating XWindow on the given position and size.
+ * @return a floating XWindow
+ * @param X the X-Position of the floating XWindow
+ * @param Y the Y-Position of the floating XWindow
+ * @param width the width of the floating XWindow
+ * @param height the height of the floating XWindow
+ * @param xMSF the MultiServiceFactory
+ */
+uno::Reference<awt::XWindowPeer>
+createFloatingWindow(uno::Reference<lang::XMultiServiceFactory> const& xMSF, sal_Int32 const nX,
+ sal_Int32 const nY, sal_Int32 const nWidth, sal_Int32 const nHeight)
+{
+ uno::Reference<awt::XToolkit> const xTk(xMSF->createInstance("com.sun.star.awt.Toolkit"),
+ uno::UNO_QUERY);
+
+ awt::WindowDescriptor descriptor;
+ descriptor.Type = awt::WindowClass_TOP;
+ descriptor.WindowServiceName = "modelessdialog";
+ descriptor.ParentIndex = -1;
+ descriptor.Bounds.X = nX;
+ descriptor.Bounds.Y = nY;
+ descriptor.Bounds.Width = nWidth;
+ descriptor.Bounds.Height = nHeight;
+ descriptor.WindowAttributes
+ = (awt::WindowAttribute::BORDER + awt::WindowAttribute::MOVEABLE
+ + awt::WindowAttribute::SIZEABLE + awt::WindowAttribute::CLOSEABLE
+ + awt::VclWindowPeerAttribute::CLIPCHILDREN);
+
+ return xTk->createWindow(descriptor);
+}
+
+/**
+ * Not really a check,
+ * only a simple test call to convertSizeToLogic(...) with different parameters
+ */
+void checkSize(uno::Reference<awt::XUnitConversion> const& xConv, awt::Size const& rSize,
+ sal_Int16 const nMeasureUnit, OUString const& rUnit)
+{
+ awt::Size const aSizeIn = xConv->convertSizeToLogic(rSize, nMeasureUnit);
+ std::cerr << "Window size:\n";
+ std::cerr << "Width: " << aSizeIn.Width << " " << rUnit << "\n";
+ std::cerr << "Height: " << aSizeIn.Height << " " << rUnit << "\n";
+}
+
+/**
+ * The real test function
+ * 2. try to create an empty window
+ * 3. try to convert the WindowPeer to an XWindow
+ * 4. try to resize and move the window to another position, so we get a well knowing position and size.
+ * 5. run some more tests
+ */
+void ToolkitTest::testXUnitConversion()
+{
+#ifdef _WIN32
+ HKEY hkey;
+ DWORD type;
+ DWORD data;
+ DWORD size(sizeof(data));
+ LONG ret = ::RegOpenKeyW(HKEY_CURRENT_USER, L"Control Panel\\Desktop", &hkey);
+ if (ret == ERROR_SUCCESS)
+ {
+ ret = ::RegQueryValueExW(hkey, L"LogPixels", nullptr, &type,
+ reinterpret_cast<LPBYTE>(&data), &size);
+ if (ret == ERROR_SUCCESS && type == REG_DWORD && data != 96)
+ {
+ std::cerr << "non-default resolution, skipping textXUnitConversion\n";
+ return;
+ }
+ }
+#endif
+
+ // create a window
+ sal_Int32 x = 100;
+ sal_Int32 y = 100;
+ sal_Int32 width = 640;
+ sal_Int32 height = 480;
+ uno::Reference<awt::XWindowPeer> const xWindowPeer
+ = createFloatingWindow(getMultiServiceFactory(), x, y, width, height);
+ CPPUNIT_ASSERT(xWindowPeer.is());
+
+ // resize and move the window to a well known position and size
+ uno::Reference<awt::XWindow> const xWindow(xWindowPeer, uno::UNO_QUERY);
+ CPPUNIT_ASSERT(xWindow.is());
+
+ xWindow->setVisible(true);
+
+ awt::Rectangle aRect = xWindow->getPosSize();
+ awt::Point aPoint(aRect.X, aRect.Y);
+ awt::Size aSize(aRect.Width, aRect.Height);
+
+ std::cerr << "Window position and size in pixel:\n";
+ std::cerr << "X: " << aPoint.X << "\n";
+ std::cerr << "Y: " << aPoint.Y << "\n";
+ std::cerr << "Width: " << aSize.Width << "\n";
+ std::cerr << "Height: " << aSize.Height << "\n";
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Window size wrong", width, aSize.Width);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Window size wrong", height, aSize.Height);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Window pos wrong", x, aPoint.X);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Window pos wrong", y, aPoint.Y);
+
+ uno::Reference<awt::XUnitConversion> const xConv(xWindowPeer, uno::UNO_QUERY);
+
+ // try to get the position of the window in 1/100mm with the XUnitConversion method
+ awt::Point const aPointInMM_100TH
+ = xConv->convertPointToLogic(aPoint, util::MeasureUnit::MM_100TH);
+ std::cerr << "Window position:\n";
+ std::cerr << "X: " << aPointInMM_100TH.X << " 1/100mm\n";
+ std::cerr << "Y: " << aPointInMM_100TH.Y << " 1/100mm\n";
+
+ // try to get the size of the window in 1/100mm with the XUnitConversion method
+ awt::Size const aSizeInMM_100TH = xConv->convertSizeToLogic(aSize, util::MeasureUnit::MM_100TH);
+ std::cerr << "Window size:\n";
+ std::cerr << "Width: " << aSizeInMM_100TH.Width << " 1/100mm\n";
+ std::cerr << "Height: " << aSizeInMM_100TH.Height << " 1/100mm\n";
+
+ // try to get the size of the window in 1/10mm with the XUnitConversion method
+ awt::Size const aSizeInMM_10TH = xConv->convertSizeToLogic(aSize, util::MeasureUnit::MM_10TH);
+ std::cerr << "Window size:\n";
+ std::cerr << "Width: " << aSizeInMM_10TH.Width << " 1/10mm\n";
+ std::cerr << "Height: " << aSizeInMM_10TH.Height << " 1/10mm\n";
+
+ // check the size with a delta which must be smaller a given difference
+ CPPUNIT_ASSERT_MESSAGE("Size.Width not correct",
+ std::abs(aSizeInMM_100TH.Width - aSizeInMM_10TH.Width * 10) < 10);
+ CPPUNIT_ASSERT_MESSAGE("Size.Height not correct",
+ std::abs(aSizeInMM_100TH.Height - aSizeInMM_10TH.Height * 10) < 10);
+
+ // new
+ checkSize(xConv, aSize, util::MeasureUnit::PIXEL, "pixel");
+ checkSize(xConv, aSize, util::MeasureUnit::APPFONT, "appfont");
+ checkSize(xConv, aSize, util::MeasureUnit::SYSFONT, "sysfont");
+
+ // simply check some more parameters
+ checkSize(xConv, aSize, util::MeasureUnit::MM, "mm");
+ checkSize(xConv, aSize, util::MeasureUnit::CM, "cm");
+ checkSize(xConv, aSize, util::MeasureUnit::INCH_1000TH, "1/1000inch");
+ checkSize(xConv, aSize, util::MeasureUnit::INCH_100TH, "1/100inch");
+ checkSize(xConv, aSize, util::MeasureUnit::INCH_10TH, "1/10inch");
+ checkSize(xConv, aSize, util::MeasureUnit::INCH, "inch");
+ checkSize(xConv, aSize, util::MeasureUnit::POINT, "point");
+ checkSize(xConv, aSize, util::MeasureUnit::TWIP, "twip");
+
+ // convert the 1/100mm window size back to pixel
+ awt::Size const aNewSize
+ = xConv->convertSizeToPixel(aSizeInMM_100TH, util::MeasureUnit::MM_100TH);
+ std::cerr << "Window size:\n";
+ std::cerr << "Width: " << aNewSize.Width << " pixel\n";
+ std::cerr << "Height: " << aNewSize.Height << " pixel\n";
+
+ // assure the pixels are the same as we already know
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("failed: Size from pixel to 1/100mm to pixel", aNewSize.Width,
+ aSize.Width);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("failed: Size from pixel to 1/100mm to pixel", aNewSize.Height,
+ aSize.Height);
+
+ // close the window.
+ xWindow->dispose();
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(ToolkitTest);
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/toolkit/qa/cppunit/a11y/AccessibleStatusBarTest.cxx b/toolkit/qa/cppunit/a11y/AccessibleStatusBarTest.cxx
new file mode 100644
index 0000000000..5bf522fb2e
--- /dev/null
+++ b/toolkit/qa/cppunit/a11y/AccessibleStatusBarTest.cxx
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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 <string>
+
+#include <com/sun/star/accessibility/AccessibleRole.hpp>
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/XAccessibleComponent.hpp>
+#include <com/sun/star/accessibility/XAccessibleContext.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+
+#include <rtl/ustrbuf.hxx>
+#include <test/a11y/accessibletestbase.hxx>
+#include <vcl/scheduler.hxx>
+
+#include <test/a11y/AccessibilityTools.hxx>
+#include "XAccessibleComponentTester.hxx"
+#include "XAccessibleContextTester.hxx"
+#include "XAccessibleExtendedComponentTester.hxx"
+#include "XAccessibleEventBroadcasterTester.hxx"
+
+using namespace css;
+
+namespace
+{
+class AccessibleStatusBarTest : public test::AccessibleTestBase
+{
+private:
+ uno::Reference<accessibility::XAccessibleContext>
+ getTestObject(const uno::Reference<awt::XWindow>& xWindow);
+ void runAllTests();
+ void testDocument(std::string_view sKind);
+
+ void testWriterDoc() { testDocument("swriter"); }
+ void testMathDoc() { testDocument("smath"); }
+ void testDrawDoc() { testDocument("sdraw"); }
+ void testImpressDoc() { testDocument("simpress"); }
+ void testCalcDoc() { testDocument("scalc"); }
+
+public:
+ CPPUNIT_TEST_SUITE(AccessibleStatusBarTest);
+ CPPUNIT_TEST(testWriterDoc);
+ CPPUNIT_TEST(testMathDoc);
+ CPPUNIT_TEST(testDrawDoc);
+ CPPUNIT_TEST(testImpressDoc);
+ CPPUNIT_TEST(testCalcDoc);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+uno::Reference<accessibility::XAccessibleContext>
+AccessibleStatusBarTest::getTestObject(const uno::Reference<awt::XWindow>& xWindow)
+{
+ uno::Reference<accessibility::XAccessible> xAccessible(xWindow, uno::UNO_QUERY_THROW);
+ std::cout << "got accessible: " << xAccessible << std::endl;
+ std::cout << "accessible name: " << AccessibilityTools::debugString(xAccessible) << std::endl;
+
+ auto xContext = AccessibilityTools::getAccessibleObjectForRole(
+ xAccessible, accessibility::AccessibleRole::STATUS_BAR);
+ std::cout << "got context: " << xContext << std::endl;
+ std::cout << "context name: " << AccessibilityTools::debugString(xContext) << std::endl;
+
+ Scheduler::ProcessEventsToIdle(); // not sure why?
+
+ uno::Reference<lang::XServiceInfo> xSI(xContext, uno::UNO_QUERY_THROW);
+ std::cout << "implementation name: " << xSI->getImplementationName() << std::endl;
+ auto serviceNames = xSI->getSupportedServiceNames();
+ std::cout << "has " << serviceNames.size() << " services:" << std::endl;
+ for (auto& service : serviceNames)
+ std::cout << " * service: " << service << std::endl;
+
+ return xContext;
+}
+
+void AccessibleStatusBarTest::runAllTests()
+{
+ auto xContext = getTestObject(mxWindow);
+
+ uno::Reference<accessibility::XAccessibleComponent> xAccessibleComponent(xContext,
+ uno::UNO_QUERY_THROW);
+ XAccessibleComponentTester componentTester(xAccessibleComponent);
+ componentTester.testAll();
+
+ XAccessibleContextTester contextTester(xContext);
+ contextTester.testAll();
+
+ uno::Reference<accessibility::XAccessibleExtendedComponent> xAccessibleExtendedComponent(
+ xContext, uno::UNO_QUERY_THROW);
+ XAccessibleExtendedComponentTester extendedComponentTester(xAccessibleExtendedComponent);
+ extendedComponentTester.testAll();
+
+ uno::Reference<accessibility::XAccessibleEventBroadcaster> xAccessibleEventBroadcaster(
+ xContext, uno::UNO_QUERY_THROW);
+ XAccessibleEventBroadcasterTester eventBroadcasterTester(xAccessibleEventBroadcaster, mxWindow);
+ eventBroadcasterTester.testAll();
+}
+
+void AccessibleStatusBarTest::testDocument(std::string_view sKind)
+{
+ rtl::OUStringBuffer sURL("private:factory/");
+ sURL.appendAscii(sKind.data(), sKind.length());
+
+ load(sURL.makeStringAndClear());
+
+ std::cout << "got document: " << mxDocument << std::endl;
+
+ Scheduler::ProcessEventsToIdle();
+
+ runAllTests();
+
+ // close document
+ close();
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(AccessibleStatusBarTest);
+} // namespace
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/toolkit/qa/cppunit/a11y/XAccessibleComponentTester.cxx b/toolkit/qa/cppunit/a11y/XAccessibleComponentTester.cxx
new file mode 100644
index 0000000000..fa5fb9f705
--- /dev/null
+++ b/toolkit/qa/cppunit/a11y/XAccessibleComponentTester.cxx
@@ -0,0 +1,291 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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 "XAccessibleComponentTester.hxx"
+
+#include <cppunit/TestAssert.h>
+
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/XAccessibleComponent.hpp>
+#include <com/sun/star/accessibility/XAccessibleContext.hpp>
+#include <com/sun/star/awt/Point.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+
+#include <tools/color.hxx>
+
+#include <test/a11y/AccessibilityTools.hxx>
+
+using namespace css;
+
+/**
+ * @brief Checks the component's bounds
+ *
+ * Checks the X and Y coordinates are non-negative, and that the width and
+ * height are greater than 0.
+ *
+ * Coherence with @c getLocation() is tested in the test for the
+ * latter.
+ */
+void XAccessibleComponentTester::testBounds()
+{
+ auto bounds = mxComponent->getBounds();
+ std::cout << "bounds: " << bounds.Width << "x" << bounds.Height << std::showpos << bounds.X
+ << bounds.Y << std::noshowpos << std::endl;
+ CPPUNIT_ASSERT_GREATEREQUAL(static_cast<sal_Int32>(0), bounds.X);
+ CPPUNIT_ASSERT_GREATEREQUAL(static_cast<sal_Int32>(0), bounds.Y);
+ CPPUNIT_ASSERT_GREATER(static_cast<sal_Int32>(0), bounds.Width);
+ CPPUNIT_ASSERT_GREATER(static_cast<sal_Int32>(0), bounds.Height);
+}
+
+/**
+ * @brief Tests results of XAccessibleComponent::getSize()
+ *
+ * Succeeds if the size is the same as in bounds.
+ */
+void XAccessibleComponentTester::testSize()
+{
+ auto bounds = mxComponent->getBounds();
+ auto size = mxComponent->getSize();
+ CPPUNIT_ASSERT_EQUAL(bounds.Width, size.Width);
+ CPPUNIT_ASSERT_EQUAL(bounds.Height, size.Height);
+}
+
+/**
+ * @brief Tests results of XAccessibleComponent::getBounds()
+ *
+ * First checks 4 inner bounds (upper, lower, left and right) of component
+ * bounding box to contain at least one point of the component. Second 4 outer
+ * bounds are checked to not contain any component points.
+ *
+ * Succeeds if inner bounds contain component points and outer bounds don't
+ * contain any component points.
+ */
+void XAccessibleComponentTester::testContainsPoint()
+{
+ auto bounds = mxComponent->getBounds();
+
+ /* upper end */
+ int curX = 0;
+ while (!mxComponent->containsPoint(awt::Point(curX, 0)) && curX < bounds.Width)
+ curX++;
+ CPPUNIT_ASSERT_MESSAGE("Upper bound of box contains no component points", curX < bounds.Width);
+ std::cout << "Upper bound of box contains point (" << curX << ",0)" << std::endl;
+ /* lower end */
+ curX = 0;
+ while (!mxComponent->containsPoint(awt::Point(curX, bounds.Height - 1)) && curX < bounds.Width)
+ curX++;
+ CPPUNIT_ASSERT_MESSAGE("Lower bound of box contains no component points", curX < bounds.Width);
+ std::cout << "Lower bound of box contains point (" << curX << "," << (bounds.Height - 1) << ")"
+ << std::endl;
+ /* left end */
+ int curY = 0;
+ while (!mxComponent->containsPoint(awt::Point(0, curY)) && curY < bounds.Height)
+ curY++;
+ CPPUNIT_ASSERT_MESSAGE("Left bound of box contains no component points", curY < bounds.Height);
+ std::cout << "Left bound of box contains point (0," << curY << ")" << std::endl;
+ /* right end */
+ curY = 0;
+ while (!mxComponent->containsPoint(awt::Point(bounds.Width - 1, curY)) && curY < bounds.Height)
+ curY++;
+ CPPUNIT_ASSERT_MESSAGE("Right bound of box contains no component points", curY < bounds.Height);
+ std::cout << "Right bound of box contains point (" << (bounds.Width - 1) << "," << curY << ")"
+ << std::endl;
+ /* no match outside the bounds */
+ for (int x = -1; x <= bounds.Width; x++)
+ {
+ CPPUNIT_ASSERT_MESSAGE("Outer upper bound CONTAINS a component point",
+ !mxComponent->containsPoint(awt::Point(x, -1)));
+ CPPUNIT_ASSERT_MESSAGE("Outer lower bound CONTAINS a component point",
+ !mxComponent->containsPoint(awt::Point(x, bounds.Height)));
+ }
+ for (int y = -1; y <= bounds.Height; y++)
+ {
+ CPPUNIT_ASSERT_MESSAGE("Outer left bound CONTAINS a component point",
+ !mxComponent->containsPoint(awt::Point(-1, y)));
+ CPPUNIT_ASSERT_MESSAGE("Outer right bound CONTAINS a component point",
+ !mxComponent->containsPoint(awt::Point(bounds.Width, y)));
+ }
+}
+
+/**
+ * @brief Tests results of XAccessibleComponent::getAccessibleAtPoint()
+ *
+ * Iterates through all children which implement
+ * <code>XAccessibleComponent</code> (if they exist) determines their
+ * boundaries and tries to get each child by <code>getAccessibleAtPoint</code>
+ * passing point which belongs to the child.
+ * Also the point is checked which doesn't belong to child boundary box.
+ *
+ * Succeeds if in the first cases the right children are returned, and in the
+ * second <code>null</code> or another child is returned.
+ */
+void XAccessibleComponentTester::testAccessibleAtPoint()
+{
+ sal_Int64 count = mxContext->getAccessibleChildCount();
+ std::cout << "Found " << count << " children" << std::endl;
+ for (sal_Int64 i = 0; i < count && i < AccessibilityTools::MAX_CHILDREN; i++)
+ {
+ auto child = mxContext->getAccessibleChild(i);
+ uno::Reference<accessibility::XAccessibleContext> childContext(
+ child->getAccessibleContext(), uno::UNO_SET_THROW);
+ std::cout << "* Found child: " << AccessibilityTools::debugString(child) << std::endl;
+ std::cout << " states: "
+ << AccessibilityTools::debugAccessibleStateSet(
+ childContext->getAccessibleStateSet())
+ << std::endl;
+ uno::Reference<accessibility::XAccessibleComponent> xChildComponent(childContext,
+ uno::UNO_QUERY);
+ std::cout << " component: " << xChildComponent << std::endl;
+ if (!xChildComponent)
+ continue;
+
+ auto childBounds = xChildComponent->getBounds();
+ if (childBounds.X == -1)
+ continue;
+ std::cout << " bounds: " << childBounds.Width << "x" << childBounds.Height << std::showpos
+ << childBounds.X << childBounds.Y << std::noshowpos << std::endl;
+
+ std::cout << "finding the point which lies on the component" << std::endl;
+ int curX = 0;
+ int curY = 0;
+ while (!xChildComponent->containsPoint(awt::Point(curX, curY)) && curX < childBounds.Width)
+ {
+ curX++;
+ curY++;
+ }
+ if (curX >= childBounds.Width)
+ {
+ std::cout << "Couldn't find a point with contains" << std::endl;
+ continue;
+ }
+ else
+ {
+ std::cout << "Child found at point +" << childBounds.X + curX << "+"
+ << childBounds.Y + curY << std::endl;
+ }
+
+ // trying the point laying on child
+ auto xAccAtPoint
+ = mxComponent->getAccessibleAtPoint(awt::Point(childBounds.X, childBounds.Y));
+ CPPUNIT_ASSERT_MESSAGE("Child not found at point", xAccAtPoint.is());
+ if (!AccessibilityTools::equals(child, xAccAtPoint))
+ {
+ auto idxExpected = childContext->getAccessibleIndexInParent();
+ auto idxResult = xAccAtPoint->getAccessibleContext()->getAccessibleIndexInParent();
+ std::cout << "The child found (" << AccessibilityTools::debugString(xAccAtPoint)
+ << ") is not the expected one (" << AccessibilityTools::debugString(child)
+ << ")" << std::endl;
+ if (idxExpected < idxResult)
+ {
+ std::cout << "-- it probably is hidden behind? Skipping." << std::endl;
+ }
+ else
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("The child found is NOT the expected one", child,
+ xAccAtPoint);
+ }
+ }
+
+ // trying the point NOT laying on child
+ xAccAtPoint
+ = mxComponent->getAccessibleAtPoint(awt::Point(childBounds.X - 1, childBounds.Y - 1));
+ if (xAccAtPoint.is())
+ {
+ CPPUNIT_ASSERT_MESSAGE("Child found OUTSIDE its bounds",
+ !AccessibilityTools::equals(child, xAccAtPoint));
+ }
+ }
+}
+
+/**
+ * @brief Tests results of XAccessibleComponent::getLocation()
+ *
+ * Succeeds if the location is the same as location of boundary obtained by
+ * the <code>getBounds()</code> method.
+ */
+void XAccessibleComponentTester::testLocation()
+{
+ auto bounds = mxComponent->getBounds();
+ auto location = mxComponent->getLocation();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Invalid X location", bounds.X, location.X);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Invalid Y location", bounds.Y, location.Y);
+}
+
+/**
+ * @brief Tests results of XAccessibleComponent::getLocationOnScreen()
+ * @returns @c true on success.
+ *
+ * Get the screen location of the component and its parent
+ * (if it exists and supports <code>XAccessibleComponent</code>).
+ *
+ * Succeeds component screen location equals to screen location of its parent
+ * plus location of the component relative to the parent.
+ */
+void XAccessibleComponentTester::testLocationOnScreen()
+{
+ auto location = mxComponent->getLocationOnScreen();
+ std::cout << "location on screen: +" << location.X << "+" << location.Y << std::endl;
+
+ auto xParent = mxContext->getAccessibleParent();
+ if (!xParent.is())
+ std::cout << "No parent" << std::endl;
+ else
+ {
+ std::cout << "Found parent: " << AccessibilityTools::debugString(xParent) << std::endl;
+ uno::Reference<accessibility::XAccessibleComponent> xParentComponent(
+ xParent->getAccessibleContext(), uno::UNO_QUERY);
+ if (!xParentComponent.is())
+ std::cout << "Parent is not a Component" << std::endl;
+ else
+ {
+ auto bounds = mxComponent->getBounds();
+ auto parentLocation = xParentComponent->getLocationOnScreen();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Invalid X screen location", parentLocation.X + bounds.X,
+ location.X);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Invalid Y screen location", parentLocation.Y + bounds.Y,
+ location.Y);
+ }
+ }
+}
+
+/**
+ * Just calls the method.
+ */
+void XAccessibleComponentTester::testGrabFocus() { mxComponent->grabFocus(); }
+
+/**
+ * Just calls the method.
+ */
+void XAccessibleComponentTester::testGetForeground()
+{
+ auto color = mxComponent->getForeground();
+ std::cout << "foreground color: " << Color(ColorAlpha, color) << std::endl;
+}
+
+/**
+ * Just calls the method.
+ */
+void XAccessibleComponentTester::testGetBackground()
+{
+ auto color = mxComponent->getBackground();
+ std::cout << "background color: " << Color(ColorAlpha, color) << std::endl;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/toolkit/qa/cppunit/a11y/XAccessibleComponentTester.hxx b/toolkit/qa/cppunit/a11y/XAccessibleComponentTester.hxx
new file mode 100644
index 0000000000..5965374a3f
--- /dev/null
+++ b/toolkit/qa/cppunit/a11y/XAccessibleComponentTester.hxx
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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/uno/Reference.hxx>
+#include <com/sun/star/accessibility/XAccessibleComponent.hpp>
+#include <com/sun/star/accessibility/XAccessibleContext.hpp>
+
+#include <test/a11y/AccessibilityTools.hxx>
+
+class XAccessibleComponentTester
+{
+private:
+ const css::uno::Reference<css::accessibility::XAccessibleComponent> mxComponent;
+ const css::uno::Reference<css::accessibility::XAccessibleContext> mxContext;
+
+public:
+ XAccessibleComponentTester(
+ const css::uno::Reference<css::accessibility::XAccessibleComponent>& component)
+ : mxComponent(component)
+ , mxContext(component, css::uno::UNO_QUERY_THROW)
+ {
+ }
+
+ void testBounds();
+ void testSize();
+ void testContainsPoint();
+ void testAccessibleAtPoint();
+ void testLocation();
+ void testLocationOnScreen();
+ void testGrabFocus();
+ void testGetForeground();
+ void testGetBackground();
+
+ void testAll()
+ {
+ testBounds();
+ testSize();
+ testContainsPoint();
+ testAccessibleAtPoint();
+ testLocation();
+ testLocationOnScreen();
+ testGrabFocus();
+ testGetForeground();
+ testGetBackground();
+ }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/toolkit/qa/cppunit/a11y/XAccessibleContextTester.cxx b/toolkit/qa/cppunit/a11y/XAccessibleContextTester.cxx
new file mode 100644
index 0000000000..9d7fdb992e
--- /dev/null
+++ b/toolkit/qa/cppunit/a11y/XAccessibleContextTester.cxx
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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 "XAccessibleContextTester.hxx"
+
+#include <cppunit/TestAssert.h>
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/accessibility/XAccessibleContext.hpp>
+
+#include <test/a11y/AccessibilityTools.hxx>
+
+/**
+ * @brief Tries to get every child and checks its parent.
+ *
+ * Checks that the parent of every child and the tested component are the same object.
+ */
+void XAccessibleContextTester::testGetAccessibleChild()
+{
+ sal_Int64 count = mxContext->getAccessibleChildCount();
+ for (sal_Int64 i = 0; i < count && i < AccessibilityTools::MAX_CHILDREN; i++)
+ {
+ auto child = mxContext->getAccessibleChild(i);
+ auto childCtx = child->getAccessibleContext();
+
+ std::cout << " Child " << i << ": " << AccessibilityTools::debugString(childCtx)
+ << std::endl;
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("child's parent context is not parent's context!",
+ childCtx->getAccessibleParent()->getAccessibleContext(),
+ mxContext);
+ }
+}
+
+/**
+ * @brief Calls the method.
+ *
+ * Checks that the child count is non-negative.
+ */
+void XAccessibleContextTester::testGetAccessibleChildCount()
+{
+ sal_Int64 childCount = mxContext->getAccessibleChildCount();
+ std::cout << childCount << " children found." << std::endl;
+ CPPUNIT_ASSERT_GREATEREQUAL(static_cast<sal_Int64>(0), childCount);
+}
+
+/**
+ * @brief Get the accessible description of the component.
+ */
+void XAccessibleContextTester::testGetAccessibleDescription()
+{
+ auto desc = mxContext->getAccessibleDescription();
+ std::cout << "The description is '" << desc << "'" << std::endl;
+}
+
+/**
+ * @brief Checks the index in parent
+ *
+ * Checks that the parent's child and the tested component are the same objects.
+ *
+ * Retrieves the index of tested component in its parent.
+ * Then gets the parent's child by this index and compares
+ * it with tested component.
+ */
+void XAccessibleContextTester::testGetAccessibleIndexInParent()
+{
+ sal_Int64 idx = mxContext->getAccessibleIndexInParent();
+ std::cout << "The index in parent is " << idx << std::endl;
+
+ auto parent = mxContext->getAccessibleParent();
+ CPPUNIT_ASSERT(parent.is());
+ auto parentCtx = parent->getAccessibleContext();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Parent's child context at our index is not us!", mxContext,
+ parentCtx->getAccessibleChild(idx)->getAccessibleContext());
+}
+
+/**
+ * @brief Get the accessible name of the component.
+ */
+void XAccessibleContextTester::testGetAccessibleName()
+{
+ auto name = mxContext->getAccessibleName();
+ std::cout << "The name is '" << name << "'" << std::endl;
+}
+
+/**
+ * @brief Just gets the parent.
+ *
+ * Checks that the parent is not null.
+ */
+void XAccessibleContextTester::testGetAccessibleParent()
+{
+ // assume that the component is not ROOT
+ auto parent = mxContext->getAccessibleParent();
+ std::cout << "The parent is " << AccessibilityTools::debugString(parent) << std::endl;
+ CPPUNIT_ASSERT_MESSAGE("parent is not set", parent.is());
+}
+
+/**
+ * @brief Just gets the relation set.
+ *
+ * Checks that the relation set is not null.
+ */
+void XAccessibleContextTester::testGetAccessibleRelationSet()
+{
+ auto relSet = mxContext->getAccessibleRelationSet();
+ CPPUNIT_ASSERT_MESSAGE("relation set is not set", relSet.is());
+}
+
+/**
+ * @brief Get the accessible role of component.
+ *
+ * Checks that the role is a non-negative number.
+ */
+void XAccessibleContextTester::testGetAccessibleRole()
+{
+ sal_Int32 role = mxContext->getAccessibleRole();
+ std::cout << "The role is " << role << " (" << AccessibilityTools::getRoleName(role) << ")"
+ << std::endl;
+ CPPUNIT_ASSERT_GREATEREQUAL(static_cast<sal_Int32>(0), role);
+}
+
+/**
+ * @brief Just gets the state set.
+ *
+ * Checks that the state set is not null.
+ */
+void XAccessibleContextTester::testGetAccessibleStateSet()
+{
+ sal_Int64 stateSet = mxContext->getAccessibleStateSet();
+ std::cout << "The state set is: " << AccessibilityTools::debugAccessibleStateSet(stateSet)
+ << std::endl;
+}
+
+/**
+ * @brief Gets the locale.
+ *
+ * Checks that @c Country and @c Language fields of locale structure are not empty.
+ */
+void XAccessibleContextTester::testGetLocale()
+{
+ auto loc = mxContext->getLocale();
+ std::cout << "The locale is " << loc.Language << "," << loc.Country << std::endl;
+ CPPUNIT_ASSERT_GREATER(static_cast<sal_Int32>(0), loc.Language.getLength());
+ CPPUNIT_ASSERT_GREATER(static_cast<sal_Int32>(0), loc.Country.getLength());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/toolkit/qa/cppunit/a11y/XAccessibleContextTester.hxx b/toolkit/qa/cppunit/a11y/XAccessibleContextTester.hxx
new file mode 100644
index 0000000000..b399028cf8
--- /dev/null
+++ b/toolkit/qa/cppunit/a11y/XAccessibleContextTester.hxx
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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/uno/Reference.hxx>
+#include <com/sun/star/accessibility/XAccessibleContext.hpp>
+
+class XAccessibleContextTester
+{
+protected:
+ const css::uno::Reference<css::accessibility::XAccessibleContext> mxContext;
+
+public:
+ XAccessibleContextTester(const css::uno::Reference<css::accessibility::XAccessibleContext>& ctx)
+ : mxContext(ctx)
+ {
+ }
+
+ void testGetAccessibleChild();
+ void testGetAccessibleChildCount();
+ void testGetAccessibleDescription();
+ void testGetAccessibleIndexInParent();
+ void testGetAccessibleName();
+ void testGetAccessibleParent();
+ void testGetAccessibleRelationSet();
+ void testGetAccessibleRole();
+ void testGetAccessibleStateSet();
+ void testGetLocale();
+
+ void testAll()
+ {
+ testGetAccessibleChild();
+ testGetAccessibleChildCount();
+ testGetAccessibleDescription();
+ testGetAccessibleIndexInParent();
+ testGetAccessibleName();
+ testGetAccessibleParent();
+ testGetAccessibleRelationSet();
+ testGetAccessibleRole();
+ testGetAccessibleStateSet();
+ testGetLocale();
+ }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/toolkit/qa/cppunit/a11y/XAccessibleEventBroadcasterTester.cxx b/toolkit/qa/cppunit/a11y/XAccessibleEventBroadcasterTester.cxx
new file mode 100644
index 0000000000..852c91c341
--- /dev/null
+++ b/toolkit/qa/cppunit/a11y/XAccessibleEventBroadcasterTester.cxx
@@ -0,0 +1,185 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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 "XAccessibleEventBroadcasterTester.hxx"
+
+#include <iostream>
+
+#include <cppunit/TestAssert.h>
+
+#include <com/sun/star/accessibility/AccessibleEventObject.hpp>
+#include <com/sun/star/accessibility/AccessibleStateType.hpp>
+#include <com/sun/star/accessibility/XAccessible.hpp>
+#include <com/sun/star/accessibility/XAccessibleContext.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventListener.hpp>
+#include <com/sun/star/awt/PosSize.hpp>
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/lang/EventObject.hpp>
+
+#include <cppuhelper/implbase.hxx>
+#include <rtl/ref.hxx>
+#include <sal/log.hxx>
+
+#include <test/a11y/AccessibilityTools.hxx>
+
+using namespace css;
+
+namespace
+{
+class EvListener : public cppu::WeakImplHelper<accessibility::XAccessibleEventListener>
+{
+public:
+ bool mbGotEvent;
+
+ EvListener()
+ : mbGotEvent(false)
+ {
+ }
+
+ // XEventListener
+ virtual void SAL_CALL disposing(const lang::EventObject&) override {}
+
+ // XAccessibleEventListener
+ virtual void SAL_CALL notifyEvent(const accessibility::AccessibleEventObject& aEvent) override
+ {
+ std::cout << "Listener got event: " << AccessibilityTools::debugString(aEvent) << std::endl;
+ uno::Reference<accessibility::XAccessible> xOld(aEvent.OldValue, uno::UNO_QUERY);
+ if (xOld.is())
+ std::cout << "Old: " << AccessibilityTools::debugString(xOld) << std::endl;
+
+ uno::Reference<accessibility::XAccessible> xNew(aEvent.NewValue, uno::UNO_QUERY);
+ if (xNew.is())
+ std::cout << "New: " << AccessibilityTools::debugString(xNew) << std::endl;
+
+ mbGotEvent = true;
+ }
+};
+}
+
+XAccessibleEventBroadcasterTester::XAccessibleEventBroadcasterTester(
+ const uno::Reference<accessibility::XAccessibleEventBroadcaster>& xBroadcaster,
+ const uno::Reference<awt::XWindow>& xWindow)
+ : mxBroadcaster(xBroadcaster)
+ , mxWindow(xWindow)
+{
+}
+
+bool XAccessibleEventBroadcasterTester::isTransient(
+ const uno::Reference<accessibility::XAccessibleEventBroadcaster> xBroadcaster)
+{
+ uno::Reference<accessibility::XAccessibleContext> xCtx(xBroadcaster, uno::UNO_QUERY_THROW);
+ return isTransient(xCtx);
+}
+
+bool XAccessibleEventBroadcasterTester::isTransient(
+ const uno::Reference<accessibility::XAccessibleContext> xCtx)
+{
+ return ((xCtx->getAccessibleStateSet() & accessibility::AccessibleStateType::TRANSIENT)
+ && (xCtx->getAccessibleParent()->getAccessibleContext()->getAccessibleStateSet()
+ & accessibility::AccessibleStateType::MANAGES_DESCENDANTS));
+}
+
+/**
+ * @brief Generates an event on @c mxBroadcaster.
+ *
+ * This method indirectly alters the state of @c mxBroadcaster so that an
+ * accessible event will be fired for it. It can be called as many times as
+ * needed and triggers an event each time.
+ */
+void XAccessibleEventBroadcasterTester::fireEvent()
+{
+ awt::Rectangle newPosSize = mxWindow->getPosSize();
+ newPosSize.Width = newPosSize.Width - 20;
+ newPosSize.Height = newPosSize.Height - 20;
+ newPosSize.X = newPosSize.X + 20;
+ newPosSize.Y = newPosSize.Y + 20;
+ mxWindow->setPosSize(newPosSize.X, newPosSize.Y, newPosSize.Width, newPosSize.Height,
+ awt::PosSize::POSSIZE);
+}
+
+/**
+ * @brief Adds a listener and fires events by mean of object relation.
+ *
+ * Asserts that the listener was properly called.
+ */
+void XAccessibleEventBroadcasterTester::testAddEventListener()
+{
+ rtl::Reference<EvListener> xListener(new EvListener);
+ mxBroadcaster->addAccessibleEventListener(xListener);
+ bool transient = isTransient(mxBroadcaster);
+
+ std::cout << "firing event" << std::endl;
+ fireEvent();
+
+ AccessibilityTools::Await([&xListener]() { return xListener->mbGotEvent; });
+
+ if (!transient)
+ CPPUNIT_ASSERT_MESSAGE("listener wasn't called", xListener->mbGotEvent);
+ else
+ CPPUNIT_ASSERT_MESSAGE("Object is Transient, listener isn't expected to be called",
+ !xListener->mbGotEvent);
+
+ mxBroadcaster->removeAccessibleEventListener(xListener);
+}
+
+/**
+ * @brief Similar to @c testAddEventListener() but also removes the listener
+ *
+ * Adds an event listener just like @c testAddEventListener(), and then removes it and verifies an
+ * event doesn't trigger the supposedly removed listener.
+ *
+ * @see testAddEventListener()
+ */
+void XAccessibleEventBroadcasterTester::testRemoveEventListener()
+{
+ /* there is nothing we can really test for transient objects */
+ if (isTransient(mxBroadcaster))
+ {
+ std::cerr << "could not test removing listener on transient object " << mxBroadcaster
+ << std::endl;
+ return;
+ }
+
+ rtl::Reference<EvListener> xListener(new EvListener);
+ mxBroadcaster->addAccessibleEventListener(xListener);
+
+ std::cout << "firing event (with listener)" << std::endl;
+ fireEvent();
+
+ AccessibilityTools::Await([&xListener]() { return xListener->mbGotEvent; });
+
+ CPPUNIT_ASSERT_MESSAGE("listener wasn't called", xListener->mbGotEvent);
+
+ /* reset listener, remove it and try again */
+ xListener->mbGotEvent = false;
+
+ std::cout << "removing listener" << std::endl;
+ mxBroadcaster->removeAccessibleEventListener(xListener);
+
+ std::cout << "firing event (without listener)" << std::endl;
+ fireEvent();
+
+ AccessibilityTools::Wait(500);
+
+ CPPUNIT_ASSERT_MESSAGE("removed listener was called", !xListener->mbGotEvent);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/toolkit/qa/cppunit/a11y/XAccessibleEventBroadcasterTester.hxx b/toolkit/qa/cppunit/a11y/XAccessibleEventBroadcasterTester.hxx
new file mode 100644
index 0000000000..0fc7c23bd3
--- /dev/null
+++ b/toolkit/qa/cppunit/a11y/XAccessibleEventBroadcasterTester.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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/uno/Reference.hxx>
+#include <com/sun/star/accessibility/XAccessibleContext.hpp>
+#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+
+class XAccessibleEventBroadcasterTester
+{
+private:
+ const css::uno::Reference<css::accessibility::XAccessibleEventBroadcaster> mxBroadcaster;
+ const css::uno::Reference<css::awt::XWindow> mxWindow;
+
+ static bool isTransient(
+ const css::uno::Reference<css::accessibility::XAccessibleEventBroadcaster> xBroadcaster);
+ static bool isTransient(const css::uno::Reference<css::accessibility::XAccessibleContext> xCtx);
+
+ void fireEvent();
+
+public:
+ XAccessibleEventBroadcasterTester(
+ const css::uno::Reference<css::accessibility::XAccessibleEventBroadcaster>& xBroadcaster,
+ const css::uno::Reference<css::awt::XWindow>& xWindow);
+
+ void testAddEventListener();
+ void testRemoveEventListener();
+
+ void testAll()
+ {
+ testAddEventListener();
+ testRemoveEventListener();
+ }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/toolkit/qa/cppunit/a11y/XAccessibleExtendedComponentTester.cxx b/toolkit/qa/cppunit/a11y/XAccessibleExtendedComponentTester.cxx
new file mode 100644
index 0000000000..a7137c4ba5
--- /dev/null
+++ b/toolkit/qa/cppunit/a11y/XAccessibleExtendedComponentTester.cxx
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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 "XAccessibleExtendedComponentTester.hxx"
+
+#include <iostream>
+
+#include <com/sun/star/accessibility/XAccessibleExtendedComponent.hpp>
+
+/**
+ * @brief Just calls the method.
+ */
+void XAccessibleExtendedComponentTester::testGetFont()
+{
+ auto font = mxExtendedComponent->getFont();
+ std::cout << "font: " << font << std::endl;
+}
+
+/**
+ * @brief Just calls the method.
+ */
+void XAccessibleExtendedComponentTester::testGetTitledBorderText()
+{
+ auto titleBorderText = mxExtendedComponent->getTitledBorderText();
+ std::cout << "getTitledBorderText(): '" << titleBorderText << "'" << std::endl;
+}
+
+/**
+ * @brief Just calls the method.
+ */
+void XAccessibleExtendedComponentTester::testGetToolTipText()
+{
+ auto toolTipText = mxExtendedComponent->getToolTipText();
+ std::cout << "getToolTipText(): '" << toolTipText << "'" << std::endl;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/toolkit/qa/cppunit/a11y/XAccessibleExtendedComponentTester.hxx b/toolkit/qa/cppunit/a11y/XAccessibleExtendedComponentTester.hxx
new file mode 100644
index 0000000000..1297052822
--- /dev/null
+++ b/toolkit/qa/cppunit/a11y/XAccessibleExtendedComponentTester.hxx
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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/uno/Reference.hxx>
+#include <com/sun/star/accessibility/XAccessibleExtendedComponent.hpp>
+
+class XAccessibleExtendedComponentTester
+{
+protected:
+ const css::uno::Reference<css::accessibility::XAccessibleExtendedComponent> mxExtendedComponent;
+
+public:
+ XAccessibleExtendedComponentTester(
+ const css::uno::Reference<css::accessibility::XAccessibleExtendedComponent>&
+ extendedComponent)
+ : mxExtendedComponent(extendedComponent)
+ {
+ }
+
+ void testGetFont();
+ void testGetTitledBorderText();
+ void testGetToolTipText();
+
+ void testAll()
+ {
+ testGetFont();
+ testGetTitledBorderText();
+ testGetToolTipText();
+ }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/toolkit/qa/unoapi/knownissues.xcl b/toolkit/qa/unoapi/knownissues.xcl
new file mode 100644
index 0000000000..7a2f95577f
--- /dev/null
+++ b/toolkit/qa/unoapi/knownissues.xcl
@@ -0,0 +1,259 @@
+#
+# 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 .
+#
+
+### i86545 ###
+toolkit.AccessibleToolBoxItem::com::sun::star::accessibility::XAccessibleText
+
+### i30818 ###
+toolkit.AccessibleToolBox::com::sun::star::accessibility::XAccessibleEventBroadcaster
+
+### i68852 ###
+toolkit.TabControllerModel::com::sun::star::io::XPersistObject
+
+### i79111 ###
+toolkit.UnoControlButtonModel::com::sun::star::awt::UnoControlButtonModel
+
+### i79110 ###
+toolkit.UnoControlCheckBoxModel::com::sun::star::awt::UnoControlCheckBoxModel
+
+### i84314 ###
+toolkit.UnoControlImageControlModel::com::sun::star::awt::UnoControlImageControlModel
+
+### i86542 ###
+toolkit.UnoControlProgressBarModel::com::sun::star::awt::UnoControlProgressBarModel
+
+### i86543 ###
+toolkit.UnoControlRadioButtonModel::com::sun::star::awt::UnoControlRadioButtonModel
+
+### i79098 ###
+toolkit.UnoControlScrollBarModel::com::sun::star::awt::UnoControlScrollBarModel
+
+### i86544 ###
+toolkit.UnoTreeModel::com::sun::star::awt::tree::TreeControlModel
+
+### i74011 ###
+toolkit.UnoControlDateField::com::sun::star::awt::XWindow
+toolkit.UnoSpinButtonControl::com::sun::star::awt::XWindow
+toolkit.UnoControlPatternField::com::sun::star::awt::XWindow
+toolkit.UnoControlRadioButton::com::sun::star::awt::XWindow
+toolkit.UnoControlButton::com::sun::star::awt::XWindow
+toolkit.UnoControlTimeField::com::sun::star::awt::XWindow
+toolkit.UnoControlFormattedField::com::sun::star::awt::XWindow
+toolkit.UnoControlContainer::com::sun::star::awt::XWindow
+toolkit.UnoControlGroupBox::com::sun::star::awt::XWindow
+toolkit.UnoControlFixedText::com::sun::star::awt::XWindow
+toolkit.UnoControlListBox::com::sun::star::awt::XWindow
+toolkit.UnoControlImageControl::com::sun::star::awt::XWindow
+toolkit.UnoControlDialog::com::sun::star::awt::XWindow
+toolkit.UnoControlEdit::com::sun::star::awt::XWindow
+toolkit.UnoControlCurrencyField::com::sun::star::awt::XWindow
+toolkit.UnoControlFileControl::com::sun::star::awt::XWindow
+toolkit.UnoControlComboBox::com::sun::star::awt::XWindow
+toolkit.UnoControlNumericField::com::sun::star::awt::XWindow
+toolkit.UnoControlCheckBox::com::sun::star::awt::XWindow
+toolkit.UnoScrollBarControl::com::sun::star::awt::XWindow
+
+### i86296 ###
+toolkit.UnoControlContainerModel::com::sun::star::awt::UnoControlContainerModel
+
+### i86297 ###
+toolkit.UnoControlFixedTextModel::com::sun::star::awt::UnoControlFixedTextModel
+
+### i86299 ###
+toolkit.UnoTreeModel::com::sun::star::awt::UnoControlModel
+
+### i86300 ###
+toolkit.UnoTreeModel::com::sun::star::beans::XMultiPropertySet
+
+### i86007 ###
+toolkit.AccessibleButton
+# -> disabled in toolkit.sce
+
+### i86008 ###
+toolkit.AccessibleComboBox
+# -> disabled in toolkit.sce
+
+### i86110 ###
+toolkit.AccessibleEdit
+toolkit.AccessibleList
+toolkit.AccessibleListBox
+toolkit.AccessibleListItem
+toolkit.AccessibleRadioButton
+# -> disabled in toolkit.sce
+
+### i86009 ###
+toolkit.AccessibleMenuItem
+# -> disabled in toolkit.sce
+
+### i86107 ###
+toolkit.AccessibleRadioButton
+# -> disabled in toolkit.sce
+
+### i86287 ###
+toolkit.AccessibleToolBox
+# -> disabled in toolkit.sce
+
+### i86011 ###
+toolkit.UnoControlFileControl
+# -> disabled in toolkit.sce
+
+### i86013 ###
+toolkit.UnoControlFormattedField
+# -> disabled in toolkit.sce
+
+### i86019 ###
+toolkit.UnoControlListBox
+# -> disabled in toolkit.sce
+
+### i86298 ###
+toolkit.UnoTreeControl
+# -> disabled in toolkit.sce
+
+### i52607 ###
+toolkit.AccessiblePopupMenu
+# -> disabled in toolkit.sce
+
+### i86660 ###
+toolkit.UnoControlDateField::com::sun::star::awt::XView
+toolkit.UnoSpinButtonControl::com::sun::star::awt::XView
+toolkit.UnoControlPatternField::com::sun::star::awt::XView
+toolkit.UnoControlRadioButton::com::sun::star::awt::XView
+toolkit.UnoControlButton::com::sun::star::awt::XView
+toolkit.UnoControlTimeField::com::sun::star::awt::XView
+toolkit.UnoControlFormattedField::com::sun::star::awt::XView
+toolkit.UnoControlGroupBox::com::sun::star::awt::XView
+toolkit.UnoControlContainer::com::sun::star::awt::XView
+toolkit.UnoControlFixedText::com::sun::star::awt::XView
+toolkit.UnoControlListBox::com::sun::star::awt::XView
+toolkit.UnoControlEdit::com::sun::star::awt::XView
+toolkit.UnoControlImageControl::com::sun::star::awt::XView
+toolkit.UnoControlDialog::com::sun::star::awt::XView
+toolkit.UnoControlFileControl::com::sun::star::awt::XView
+toolkit.UnoControlCurrencyField::com::sun::star::awt::XView
+toolkit.UnoControlComboBox::com::sun::star::awt::XView
+toolkit.UnoControlNumericField::com::sun::star::awt::XView
+toolkit.UnoControlCheckBox::com::sun::star::awt::XView
+toolkit.UnoScrollBarControl::com::sun::star::awt::XView
+
+### i37643 ###
+toolkit.AccessibleStatusBarItem::com::sun::star::accessibility::XAccessibleEventBroadcaster
+
+### i87864 ###
+toolkit.UnoControlContainerModel::com::sun::star::lang::XComponent
+toolkit.UnoTreeModel::com::sun::star::lang::XComponent
+toolkit.UnoControlTimeFieldModel::com::sun::star::lang::XComponent
+toolkit.UnoControlDateField::com::sun::star::lang::XComponent
+toolkit.UnoControlButtonModel::com::sun::star::lang::XComponent
+toolkit.UnoControlPatternFieldModel::com::sun::star::lang::XComponent
+toolkit.UnoSpinButtonControl::com::sun::star::lang::XComponent
+toolkit.UnoControlDateFieldModel::com::sun::star::lang::XComponent
+toolkit.UnoControlPatternField::com::sun::star::lang::XComponent
+toolkit.UnoControlRadioButtonModel::com::sun::star::lang::XComponent
+toolkit.UnoControlFormattedFieldModel::com::sun::star::lang::XComponent
+toolkit.UnoControlRadioButton::com::sun::star::lang::XComponent
+toolkit.UnoControlButton::com::sun::star::lang::XComponent
+toolkit.UnoControlTimeField::com::sun::star::lang::XComponent
+toolkit.UnoControlFormattedField::com::sun::star::lang::XComponent
+toolkit.UnoControlFixedLineModel::com::sun::star::lang::XComponent
+toolkit.UnoControlDialogModel::com::sun::star::lang::XComponent
+toolkit.UnoControlFileControlModel::com::sun::star::lang::XComponent
+toolkit.UnoControlGroupBox::com::sun::star::lang::XComponent
+toolkit.UnoControlContainer::com::sun::star::lang::XComponent
+toolkit.UnoControlFixedText::com::sun::star::lang::XComponent
+toolkit.UnoControlListBox::com::sun::star::lang::XComponent
+toolkit.UnoControlCheckBoxModel::com::sun::star::lang::XComponent
+toolkit.UnoControlEditModel::com::sun::star::lang::XComponent
+toolkit.UnoControlEdit::com::sun::star::lang::XComponent
+toolkit.UnoControlImageControl::com::sun::star::lang::XComponent
+toolkit.UnoControlDialog::com::sun::star::lang::XComponent
+toolkit.UnoControlGroupBoxModel::com::sun::star::lang::XComponent
+toolkit.UnoControlImageControlModel::com::sun::star::lang::XComponent
+toolkit.UnoControlNumericFieldModel::com::sun::star::lang::XComponent
+toolkit.UnoControlFileControl::com::sun::star::lang::XComponent
+toolkit.UnoControlCurrencyField::com::sun::star::lang::XComponent
+toolkit.UnoControlComboBoxModel::com::sun::star::lang::XComponent
+toolkit.UnoControlComboBox::com::sun::star::lang::XComponent
+toolkit.UnoControlNumericField::com::sun::star::lang::XComponent
+toolkit.UnoControlScrollBarModel::com::sun::star::lang::XComponent
+toolkit.UnoControlProgressBarModel::com::sun::star::lang::XComponent
+toolkit.UnoControlListBoxModel::com::sun::star::lang::XComponent
+toolkit.UnoControlFixedTextModel::com::sun::star::lang::XComponent
+toolkit.UnoSpinButtonControlModel::com::sun::star::lang::XComponent
+toolkit.UnoControlCurrencyFieldModel::com::sun::star::lang::XComponent
+toolkit.UnoControlCheckBox::com::sun::star::lang::XComponent
+toolkit.UnoScrollBarControl::com::sun::star::lang::XComponent
+
+### i89415 ###
+toolkit.UnoControlContainer::com::sun::star::awt::XControl
+
+### i89417 ###
+toolkit.UnoControlContainer::com::sun::star::accessibility::XAccessible
+
+### i89418 ###
+toolkit.UnoSpinButtonControl::com::sun::star::awt::XSpinValue
+
+### i88332 ###
+toolkit.AccessibleCheckBox
+# -> disabled in toolkit.sce
+
+### i88605 ###
+toolkit.AccessibleToolBoxItem
+# -> disabled in toolkit.sce
+
+### i89019 ###
+toolkit.AccessibleWindow::com::sun::star::accessibility::XAccessibleEventBroadcaster
+
+### i90354 ###
+toolkit.AccessibleScrollBar::com::sun::star::accessibility::XAccessibleComponent
+
+### i90356 ###
+toolkit.UnoScrollBarControl::com::sun::star::awt::XScrollBar
+
+### i94344 ###
+toolkit.AccessibleTabPage::com::sun::star::accessibility::XAccessibleText
+
+### i109643 ###
+toolkit.AccessibleMenu::com::sun::star::accessibility::XAccessibleValue
+toolkit.AccessibleMenuBar::com::sun::star::accessibility::XAccessibleEventBroadcaster
+toolkit.AccessibleMenuBar::com::sun::star::accessibility::XAccessibleSelection
+
+### i111113 ###
+toolkit.AccessibleStatusBarItem::com::sun::star::accessibility::XAccessibleComponent
+toolkit.AccessibleStatusBarItem::com::sun::star::accessibility::XAccessibleContext
+
+### i111195 ###
+toolkit.AccessibleScrollBar::com::sun::star::accessibility::XAccessibleValue
+
+### i113489 ###
+toolkit.AccessibleMenu::com::sun::star::accessibility::XAccessibleText
+toolkit.AccessibleMenuBar::com::sun::star::accessibility::XAccessibleComponent
+toolkit.AccessibleMenuSeparator::com::sun::star::accessibility::XAccessibleComponent
+
+### i114213 ###
+toolkit.AccessibleMenu::com::sun::star::accessibility::XAccessibleSelection
+
+### i114636 ###
+toolkit.AccessibleScrollBar::com::sun::star::accessibility::XAccessibleAction
+toolkit.AccessibleScrollBar::com::sun::star::accessibility::XAccessibleContext
+toolkit.AccessibleScrollBar::com::sun::star::accessibility::XAccessibleEventBroadcaster
+
+### fd#35666 ###
+toolkit.UnoControlDialogModel::com::sun::star::io::XPersistObject
+
+### fd#35772 ###
+toolkit.Toolkit::com::sun::star::awt::XMessageBoxFactory
diff --git a/toolkit/qa/unoapi/testdocuments/poliball.gif b/toolkit/qa/unoapi/testdocuments/poliball.gif
new file mode 100644
index 0000000000..dda461bd34
--- /dev/null
+++ b/toolkit/qa/unoapi/testdocuments/poliball.gif
Binary files differ
diff --git a/toolkit/qa/unoapi/toolkit_1.sce b/toolkit/qa/unoapi/toolkit_1.sce
new file mode 100644
index 0000000000..3cee05dc3e
--- /dev/null
+++ b/toolkit/qa/unoapi/toolkit_1.sce
@@ -0,0 +1,40 @@
+#
+# 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 .
+#
+
+#i86007 -o toolkit.AccessibleButton
+#i88332 -o toolkit.AccessibleCheckBox
+#i86008 -o toolkit.AccessibleComboBox
+-o toolkit.AccessibleDropDownComboBox
+-o toolkit.AccessibleDropDownListBox
+#i86110 -o toolkit.AccessibleEdit
+-o toolkit.AccessibleFixedText
+#i86110 -o toolkit.AccessibleList
+#i86110 -o toolkit.AccessibleListBox
+#i86110 -o toolkit.AccessibleListItem
+-o toolkit.AccessibleMenu
+-o toolkit.AccessibleMenuBar
+#i86009 -o toolkit.AccessibleMenuItem
+-o toolkit.AccessibleMenuSeparator
+#i52607 -o toolkit.AccessiblePopupMenu
+#i86107,i86110 -o toolkit.AccessibleRadioButton
+-o toolkit.AccessibleScrollBar
+-o toolkit.AccessibleStatusBarItem
+#i109643 -o toolkit.AccessibleTabControl
+#i109643 -o toolkit.AccessibleTabPage
+#i86287 -o toolkit.AccessibleToolBox
+#i88605 -o toolkit.AccessibleToolBoxItem
diff --git a/toolkit/qa/unoapi/toolkit_2.sce b/toolkit/qa/unoapi/toolkit_2.sce
new file mode 100644
index 0000000000..2c5957f34f
--- /dev/null
+++ b/toolkit/qa/unoapi/toolkit_2.sce
@@ -0,0 +1,36 @@
+#
+# 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 .
+#
+
+-o toolkit.AccessibleWindow
+-o toolkit.MutableTreeDataModel
+-o toolkit.MutableTreeNode
+-o toolkit.TabController
+-o toolkit.TabControllerModel
+-o toolkit.Toolkit
+-o toolkit.UnoControlButton
+-o toolkit.UnoControlButtonModel
+-o toolkit.UnoControlCheckBox
+-o toolkit.UnoControlCheckBoxModel
+-o toolkit.UnoControlComboBox
+-o toolkit.UnoControlComboBoxModel
+-o toolkit.UnoControlContainer
+-o toolkit.UnoControlContainerModel
+-o toolkit.UnoControlCurrencyField
+-o toolkit.UnoControlCurrencyFieldModel
+-o toolkit.UnoControlDateField
+-o toolkit.UnoControlDateFieldModel
diff --git a/toolkit/qa/unoapi/toolkit_3.sce b/toolkit/qa/unoapi/toolkit_3.sce
new file mode 100644
index 0000000000..91f07709e2
--- /dev/null
+++ b/toolkit/qa/unoapi/toolkit_3.sce
@@ -0,0 +1,37 @@
+#
+# 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 .
+#
+
+#allegedly was i80788, but still broken: -o toolkit.UnoControlDialog
+-o toolkit.UnoControlDialogModel
+-o toolkit.UnoControlEdit
+-o toolkit.UnoControlEditModel
+#i86011 -o toolkit.UnoControlFileControl
+-o toolkit.UnoControlFileControlModel
+-o toolkit.UnoControlFixedLineModel
+-o toolkit.UnoControlFixedText
+-o toolkit.UnoControlFixedTextModel
+#i86013 -o toolkit.UnoControlFormattedField
+-o toolkit.UnoControlFormattedFieldModel
+-o toolkit.UnoControlGroupBox
+-o toolkit.UnoControlGroupBoxModel
+-o toolkit.UnoControlImageControl
+-o toolkit.UnoControlImageControlModel
+#i86019 -o toolkit.UnoControlListBox
+-o toolkit.UnoControlListBoxModel
+-o toolkit.UnoControlNumericField
+-o toolkit.UnoControlNumericFieldModel
diff --git a/toolkit/qa/unoapi/toolkit_4.sce b/toolkit/qa/unoapi/toolkit_4.sce
new file mode 100644
index 0000000000..d8cdcbe380
--- /dev/null
+++ b/toolkit/qa/unoapi/toolkit_4.sce
@@ -0,0 +1,31 @@
+#
+# 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 .
+#
+
+-o toolkit.UnoControlPatternField
+-o toolkit.UnoControlPatternFieldModel
+-o toolkit.UnoControlProgressBarModel
+-o toolkit.UnoControlRadioButton
+-o toolkit.UnoControlRadioButtonModel
+-o toolkit.UnoControlScrollBarModel
+-o toolkit.UnoControlTimeField
+-o toolkit.UnoControlTimeFieldModel
+-o toolkit.UnoScrollBarControl
+-o toolkit.UnoSpinButtonControl
+-o toolkit.UnoSpinButtonControlModel
+#i86298 -o toolkit.UnoTreeControl
+-o toolkit.UnoTreeModel
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: */
diff --git a/toolkit/test/accessibility/AWB.sxw b/toolkit/test/accessibility/AWB.sxw
new file mode 100644
index 0000000000..57931aed1d
--- /dev/null
+++ b/toolkit/test/accessibility/AWB.sxw
Binary files differ
diff --git a/toolkit/test/accessibility/AccTreeNode.java b/toolkit/test/accessibility/AccTreeNode.java
new file mode 100644
index 0000000000..1ce4676842
--- /dev/null
+++ b/toolkit/test/accessibility/AccTreeNode.java
@@ -0,0 +1,346 @@
+/*
+ * 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 .
+ */
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleComponent;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleEditableText;
+import com.sun.star.accessibility.XAccessibleSelection;
+import com.sun.star.accessibility.XAccessibleTable;
+import com.sun.star.accessibility.XAccessibleText;
+import com.sun.star.uno.UnoRuntime;
+
+/**
+ * The node type for the AccessibleTreeModel.
+ * This implements all the child-handling based on the appropriate
+ * NodeHandlers. Trivial nodes can be implemented by any Object
+ * type.
+ */
+class AccTreeNode
+ extends AccessibleTreeNode
+{
+ private class HandlerDescriptor
+ {
+ private HandlerDescriptor (NodeHandler aHandler)
+ {
+ maHandler = aHandler;
+ mnChildCount = -1;
+ }
+ private NodeHandler maHandler;
+ private int mnChildCount;
+ }
+ /// NodeHandlers for this node
+ private ArrayList<HandlerDescriptor> maHandlers;
+
+ // The accessible context of this node.
+ private XAccessibleContext mxContext;
+ private XAccessibleComponent mxComponent;
+ private XAccessibleText mxText;
+ private XAccessibleTable mxTable;
+
+ public AccTreeNode (XAccessibleContext xContext, Object aDisplay, AccessibleTreeNode aParent)
+ {
+ super (aDisplay, aParent);
+
+ maHandlers = new ArrayList<HandlerDescriptor>(5);
+ mxContext = xContext;
+ }
+
+ /** Update the internal data extracted from the corresponding accessible
+ object. This is done by replacing every handler by a new one. An
+ update method at each handler would be better of course.
+ */
+ @Override
+ public void update ()
+ {
+ for (int i=0; i<maHandlers.size(); i++)
+ {
+ System.out.println ("replacing handler " + i);
+ HandlerDescriptor aDescriptor = maHandlers.get(i);
+ aDescriptor.maHandler = aDescriptor.maHandler.createHandler (mxContext);
+ aDescriptor.mnChildCount =
+ aDescriptor.maHandler.getChildCount ();
+ }
+ }
+
+ public XAccessibleContext getContext ()
+ {
+ return mxContext;
+ }
+
+ public XAccessibleComponent getComponent ()
+ {
+ if (mxComponent == null && mxContext != null)
+ mxComponent = UnoRuntime.queryInterface(
+ XAccessibleComponent.class, mxContext);
+ return mxComponent;
+ }
+
+ public XAccessibleText getText ()
+ {
+ if (mxText == null && mxContext != null)
+ mxText = UnoRuntime.queryInterface(
+ XAccessibleText.class, mxContext);
+ return mxText;
+ }
+
+ public XAccessibleEditableText getEditText ()
+ {
+ return UnoRuntime.queryInterface(
+ XAccessibleEditableText.class, mxContext);
+ }
+
+ public XAccessibleTable getTable ()
+ {
+ if (mxTable == null && mxContext != null)
+ mxTable = UnoRuntime.queryInterface(
+ XAccessibleTable.class, mxContext);
+ return mxTable;
+ }
+
+
+ public XAccessibleSelection getSelection ()
+ {
+ return UnoRuntime.queryInterface(
+ XAccessibleSelection.class, mxContext);
+ }
+
+ public void addHandler( NodeHandler aHandler )
+ {
+ if (aHandler != null)
+ maHandlers.add (new HandlerDescriptor (aHandler));
+ }
+
+
+ /** iterate over handlers and return child sum */
+ private HandlerDescriptor getHandlerDescriptor (int i)
+ {
+ HandlerDescriptor aDescriptor = maHandlers.get(i);
+ if (aDescriptor.mnChildCount < 0)
+ aDescriptor.mnChildCount =
+ aDescriptor.maHandler.getChildCount ();
+ return aDescriptor;
+ }
+
+ @Override
+ public int getChildCount()
+ {
+ int nChildCount = 0;
+ for (int i = 0; i < maHandlers.size(); i++)
+ {
+ HandlerDescriptor aDescriptor = getHandlerDescriptor (i);
+ nChildCount += aDescriptor.mnChildCount;
+ }
+ return nChildCount;
+ }
+
+ /** iterate over handlers until the child is found */
+ @Override
+ public AccessibleTreeNode getChild (int nIndex)
+ throws IndexOutOfBoundsException
+ {
+ if( nIndex >= 0 )
+ {
+ for(int i = 0; i < maHandlers.size(); i++)
+ {
+ // check if this handler has the child, and if not
+ // search with next handler
+ HandlerDescriptor aDescriptor = getHandlerDescriptor (i);
+ if (nIndex < aDescriptor.mnChildCount)
+ return aDescriptor.maHandler.getChild (this, nIndex);
+ else
+ nIndex -= aDescriptor.mnChildCount;
+ }
+ }
+ else
+ throw new IndexOutOfBoundsException();
+
+ // nothing found?
+ return null;
+ }
+
+ @Override
+ public AccessibleTreeNode getChildNoCreate (int nIndex)
+ throws IndexOutOfBoundsException
+ {
+ if( nIndex >= 0 )
+ {
+ for(int i = 0; i < maHandlers.size(); i++)
+ {
+ // check if this handler has the child, and if not
+ // search with next handler
+ HandlerDescriptor aDescriptor = getHandlerDescriptor (i);
+ if (nIndex < aDescriptor.mnChildCount)
+ return aDescriptor.maHandler.getChildNoCreate (nIndex);
+ else
+ nIndex -= aDescriptor.mnChildCount;
+ }
+ }
+ else
+ throw new IndexOutOfBoundsException();
+
+ // nothing found?
+ return null;
+ }
+
+ @Override
+ public boolean removeChild (int nIndex)
+ throws IndexOutOfBoundsException
+ {
+ boolean bStatus = false;
+ if (nIndex >= 0)
+ {
+ for (int i=0; i<maHandlers.size(); i++)
+ {
+ // check if this handler has the child, and if not
+ // search with next handler
+ HandlerDescriptor aDescriptor = getHandlerDescriptor (i);
+ if (nIndex < aDescriptor.mnChildCount)
+ {
+ bStatus = aDescriptor.maHandler.removeChild (nIndex);
+ aDescriptor.mnChildCount = aDescriptor.maHandler.getChildCount ();
+ break;
+ }
+ else
+ nIndex -= aDescriptor.mnChildCount;
+ }
+ }
+ else
+ throw new IndexOutOfBoundsException();
+
+ return bStatus;
+ }
+
+
+ @Override
+ public int indexOf (AccessibleTreeNode aNode)
+ {
+ int nBaseIndex = 0;
+ if (aNode != null)
+ {
+ for (int i=0; i<maHandlers.size(); i++)
+ {
+ HandlerDescriptor aDescriptor = getHandlerDescriptor (i);
+ int nIndex = aDescriptor.maHandler.indexOf (aNode);
+ if (nIndex >= 0)
+ return nBaseIndex + nIndex;
+ else
+ nBaseIndex += aDescriptor.mnChildCount;
+ }
+ }
+
+ return -1;
+ }
+
+ /** this node is a leaf if have no handlers, or is those
+ handlers show no children */
+ @Override
+ public boolean isLeaf()
+ {
+ return maHandlers.isEmpty();
+ }
+
+ @Override
+ public boolean equals (Object aOther)
+ {
+ return (this == aOther) || (aOther!=null && aOther.equals(mxContext));
+ }
+
+
+ /** iterate over handlers until the child is found */
+ public void getActions(java.util.List<String> aActions)
+ {
+ for(int i = 0; i < maHandlers.size(); i++)
+ {
+ HandlerDescriptor aDescriptor = getHandlerDescriptor (i);
+ NodeHandler aHandler = aDescriptor.maHandler;
+ String[] aHandlerActions = aHandler.getActions (this);
+ aActions.addAll(Arrays.asList(aHandlerActions));
+ }
+ }
+
+ @Override
+ public void performAction( int nIndex )
+ {
+ if( nIndex >= 0 )
+ {
+ for(int i = 0; i < maHandlers.size(); i++)
+ {
+ // check if this handler has the child, and if not
+ // search with next handler
+ HandlerDescriptor aDescriptor = getHandlerDescriptor (i);
+ NodeHandler aHandler = aDescriptor.maHandler;
+ int nCount = aHandler.getActions(this).length;
+ if( nCount > nIndex )
+ {
+ aHandler.performAction(this, nIndex );
+ return;
+ }
+ else
+ nIndex -= nCount;
+ }
+ }
+ }
+
+ /** Try to add the specified accessible object as new accessible child of the
+ AccessibleTreeHandler.
+ Note that child is used in another context than
+ it is used in the other methods of this class.
+ */
+ public AccessibleTreeNode addAccessibleChild (XAccessible xChild)
+ {
+ for(int i = 0; i < maHandlers.size(); i++)
+ {
+ HandlerDescriptor aDescriptor = getHandlerDescriptor (i);
+ if (aDescriptor.maHandler instanceof AccessibleTreeHandler)
+ {
+ AccessibleTreeHandler aHandler = (AccessibleTreeHandler)aDescriptor.maHandler;
+ AccessibleTreeNode aNode = aHandler.addAccessibleChild (this, xChild);
+ aDescriptor.mnChildCount = aHandler.getChildCount ();
+ return aNode;
+ }
+ }
+ return null;
+ }
+
+ public java.util.List<Integer> updateChildren (java.lang.Class class1, java.lang.Class<AccessibleExtendedComponentHandler> class2)
+ {
+ ArrayList<Integer> aChildIndices = new ArrayList<Integer>();
+ int nOffset = 0;
+ for(int i=0; i < maHandlers.size(); i++)
+ {
+ HandlerDescriptor aDescriptor = getHandlerDescriptor (i);
+ if ((class1.isInstance(aDescriptor.maHandler))
+ || (class2 !=null && class2.isInstance(aDescriptor.maHandler)))
+ {
+ aDescriptor.maHandler.update(this);
+ // Get updated number of children.
+ int nChildCount = aDescriptor.maHandler.getChildCount ();
+ aDescriptor.mnChildCount = nChildCount;
+ // Fill in the indices of the updated children.
+ for (int j=0; j<nChildCount; j++)
+ aChildIndices.add(j+nOffset);
+ }
+ nOffset += aDescriptor.mnChildCount;
+ }
+ return aChildIndices;
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibilityTree.java b/toolkit/test/accessibility/AccessibilityTree.java
new file mode 100644
index 0000000000..fdf44177a7
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibilityTree.java
@@ -0,0 +1,379 @@
+/*
+ * 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 .
+ */
+
+import java.awt.Cursor;
+import java.awt.event.ActionEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+
+import javax.swing.AbstractAction;
+import javax.swing.JPopupMenu;
+import javax.swing.JTree;
+import javax.swing.event.TreeExpansionEvent;
+import javax.swing.event.TreeExpansionListener;
+import javax.swing.event.TreeWillExpandListener;
+import javax.swing.tree.TreePath;
+
+import com.sun.star.accessibility.XAccessibleContext;
+
+
+
+/** This is the tree component that is responsible for displaying the
+ contents of the tree model on the screen.
+*/
+public class AccessibilityTree
+ implements TreeExpansionListener, TreeWillExpandListener
+{
+ /** Create a new accessibility tree. Use the specified message display
+ for displaying messages and the specified canvas to draw the
+ graphical representations of accessible objects on.
+ */
+ public AccessibilityTree ()
+ {
+ maTree = new JTree ();
+
+ AccessibilityTreeModel aModel =
+ new AccessibilityTreeModel (
+ new StringNode ("Please press Update button", null));
+ maTree.setModel (aModel);
+
+ maTree.addMouseListener (new MouseListener (this));
+
+ // Listen to expansions and collapses to change the mouse cursor.
+ mnExpandLevel = 0;
+ maTree.addTreeWillExpandListener (this);
+ maTree.addTreeExpansionListener (this);
+ }
+
+ public JTree getComponent ()
+ {
+ return maTree;
+ }
+
+ // Change cursor during expansions to show the user that this is a
+ // lengthy operation.
+ public void treeWillExpand (TreeExpansionEvent e)
+ {
+ if (mnExpandLevel == 0)
+ {
+ maTree.setCursor (new Cursor (Cursor.WAIT_CURSOR));
+ }
+ mnExpandLevel += 1;
+ }
+ public void treeWillCollapse (TreeExpansionEvent e)
+ {
+ if (mnExpandLevel == 0)
+ {
+ maTree.setCursor (new Cursor (Cursor.WAIT_CURSOR));
+ }
+ mnExpandLevel += 1;
+ }
+ public void treeExpanded (TreeExpansionEvent e)
+ {
+ mnExpandLevel -= 1;
+ if (mnExpandLevel == 0)
+ {
+ maTree.setCursor (new Cursor (Cursor.DEFAULT_CURSOR));
+ }
+ }
+ public void treeCollapsed (TreeExpansionEvent e)
+ {
+ mnExpandLevel -= 1;
+ if (mnExpandLevel == 0)
+ {
+ maTree.setCursor (new Cursor (Cursor.DEFAULT_CURSOR));
+ }
+ }
+
+
+
+ public void SetCanvas (Canvas aCanvas)
+ {
+ ((AccessibilityTreeModel)maTree.getModel()).setCanvas(aCanvas);
+ }
+
+ /** Expand the nodes in the subtree rooted in aNode according to the
+ specified expander. The tree is locked during the expansion.
+ */
+ private void expandTree (AccessibleTreeNode aNode, Expander aExpander)
+ {
+ if (mnExpandLevel == 0)
+ {
+ maTree.setEnabled (false);
+ }
+ mnExpandLevel += 1;
+
+ ((AccessibilityTreeModel)maTree.getModel()).lock ();
+
+ try
+ {
+ expandTree (new TreePath (aNode.createPath()), aExpander);
+ }
+ catch (Exception e)
+ {
+ // Ignore
+ }
+
+ mnExpandLevel -= 1;
+ if (mnExpandLevel == 0)
+ {
+ maTree.setEnabled (true);
+ ((AccessibilityTreeModel)maTree.getModel()).unlock (aNode);
+ }
+ }
+
+ private TreePath expandTree( TreePath aPath, Expander aExpander )
+ {
+ // return first expanded object
+ TreePath aFirst = null;
+
+ try
+ {
+ // get 'our' object
+ Object aObj = aPath.getLastPathComponent();
+
+ // expand this object, if the Expander tells us so
+ if( aExpander.expand( aObj ) )
+ {
+ maTree.expandPath (aPath);
+ aFirst = aPath;
+ }
+
+ // visit all children
+ if (aObj instanceof AccessibleTreeNode)
+ {
+ AccessibleTreeNode aNode = (AccessibleTreeNode)aObj;
+ int nLength = aNode.getChildCount();
+ for( int i = 0; i < nLength; i++ )
+ {
+ TreePath aRet = expandTree(
+ aPath.pathByAddingChild( aNode.getChild( i ) ),
+ aExpander );
+ if( aFirst == null )
+ aFirst = aRet;
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ System.out.println ("caught exception while expanding tree path "
+ + aPath + ": " + e);
+ e.printStackTrace ();
+ }
+
+ return aFirst;
+ }
+
+
+ /** Expand all nodes and their subtrees that represent shapes. Call
+ * this method from the outside. */
+ public void expandShapes ()
+ {
+ expandShapes ((AccessibleTreeNode)maTree.getModel().getRoot());
+ }
+ private void expandShapes (AccessibleTreeNode aNode)
+ {
+ expandTree (aNode, new ShapeExpander());
+ }
+
+ /** Expand all nodes */
+ public void expandAll ()
+ {
+ expandAll ((AccessibleTreeNode)maTree.getModel().getRoot());
+ }
+ private void expandAll (AccessibleTreeNode aNode)
+ {
+ expandTree (aNode, new AllExpander());
+ }
+
+
+
+ /*
+ public Dimension getPreferredSize ()
+ {
+ Dimension aPreferredSize = super.getPreferredSize();
+ Dimension aMinimumSize = super.getMinimumSize();
+ if (aPreferredSize.width < aMinimumSize.width)
+ aPreferredSize.width = aMinimumSize.width;
+ return aPreferredSize;
+ }
+ */
+
+ private class MouseListener extends MouseAdapter
+ {
+ public MouseListener (AccessibilityTree aTree)
+ {
+ maTree=aTree;
+ }
+ @Override
+ public void mousePressed(MouseEvent e) { popupTrigger(e); }
+ @Override
+ public void mouseClicked(MouseEvent e) { popupTrigger(e); }
+ @Override
+ public void mouseEntered(MouseEvent e) { popupTrigger(e); }
+ @Override
+ public void mouseExited(MouseEvent e) { popupTrigger(e); }
+ @Override
+ public void mouseReleased(MouseEvent e) { popupTrigger(e); }
+
+ private boolean popupTrigger( MouseEvent e )
+ {
+ boolean bIsPopup = e.isPopupTrigger();
+ if( !bIsPopup )
+ return false;
+
+ int selRow = maTree.getComponent().getRowForLocation(e.getX(), e.getY());
+ if (selRow == -1)
+ return bIsPopup;
+
+ TreePath aPath = maTree.getComponent().getPathForLocation(e.getX(), e.getY());
+
+ // check for actions
+ Object aObject = aPath.getLastPathComponent();
+ JPopupMenu aMenu = new JPopupMenu();
+ if( aObject instanceof AccTreeNode )
+ {
+ AccTreeNode aNode = (AccTreeNode)aObject;
+
+ ArrayList<String> aActions = new ArrayList<String>();
+ aMenu.add (new AccessibilityTree.ShapeExpandAction(maTree, aNode));
+ aMenu.add (new AccessibilityTree.SubtreeExpandAction(maTree, aNode));
+
+ aNode.getActions(aActions);
+ for( int i = 0; i < aActions.size(); i++ )
+ {
+ aMenu.add( new NodeAction(
+ aActions.get(i),
+ aNode, i ) );
+ }
+ }
+ else if (aObject instanceof AccessibleTreeNode)
+ {
+ AccessibleTreeNode aNode = (AccessibleTreeNode)aObject;
+ String[] aActionNames = aNode.getActions();
+ int nCount=aActionNames.length;
+ if (nCount > 0)
+ {
+ for (int i=0; i<nCount; i++)
+ aMenu.add( new NodeAction(
+ aActionNames[i],
+ aNode,
+ i));
+ }
+ else
+ aMenu = null;
+ }
+ if (aMenu != null)
+ aMenu.show (maTree.getComponent(),
+ e.getX(), e.getY());
+
+ return bIsPopup;
+ }
+
+ private final AccessibilityTree maTree;
+ }
+
+ private class NodeAction extends AbstractAction
+ {
+ private final int mnIndex;
+ private final AccessibleTreeNode maNode;
+
+ private NodeAction( String aName, AccessibleTreeNode aNode, int nIndex )
+ {
+ super( aName );
+ maNode = aNode;
+ mnIndex = nIndex;
+ }
+
+ public void actionPerformed(ActionEvent e)
+ {
+ maNode.performAction(mnIndex);
+ }
+ }
+
+ // This action expands all shapes in the subtree rooted in the specified node.
+ private class ShapeExpandAction extends AbstractAction
+ {
+ private final AccessibilityTree maTree;
+ private final AccTreeNode maNode;
+ public ShapeExpandAction (AccessibilityTree aTree, AccTreeNode aNode)
+ {
+ super ("Expand Shapes");
+ maTree = aTree;
+ maNode = aNode;
+ }
+ public void actionPerformed (ActionEvent e)
+ {
+ maTree.expandShapes (maNode);
+ }
+ }
+
+ // This action expands all nodes in the subtree rooted in the specified node.
+ private class SubtreeExpandAction extends AbstractAction
+ {
+ private final AccessibilityTree maTree;
+ private final AccTreeNode maNode;
+ public SubtreeExpandAction (AccessibilityTree aTree, AccTreeNode aNode)
+ {
+ super ("Expand Subtree");
+ maTree = aTree;
+ maNode = aNode;
+ }
+ public void actionPerformed (ActionEvent e)
+ {
+ maTree.expandAll (maNode);
+ }
+ }
+
+ /** Predicate class to determine whether a node should be expanded
+ * For use with expandTree method */
+ private abstract class Expander
+ {
+ abstract public boolean expand (Object aObject);
+ }
+
+ /** expand all nodes */
+ private class AllExpander extends Expander
+ {
+ @Override
+ public boolean expand(Object aObject) { return true; }
+ }
+
+ /** expand all nodes with accessibility roles > 100 */
+ private class ShapeExpander extends Expander
+ {
+ @Override
+ public boolean expand (Object aObject)
+ {
+ if (aObject instanceof AccTreeNode)
+ {
+ AccTreeNode aNode = (AccTreeNode)aObject;
+ XAccessibleContext xContext = aNode.getContext();
+ if (xContext != null && xContext.getAccessibleRole() >= 100)
+ return true;
+ }
+ return false;
+ }
+ }
+
+
+
+ private final JTree maTree;
+ private int mnExpandLevel;
+}
diff --git a/toolkit/test/accessibility/AccessibilityTreeModel.java b/toolkit/test/accessibility/AccessibilityTreeModel.java
new file mode 100644
index 0000000000..b021746bc2
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibilityTreeModel.java
@@ -0,0 +1,471 @@
+/*
+ * 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 .
+ */
+
+import java.util.ArrayList;
+
+import javax.swing.event.TreeModelEvent;
+import javax.swing.tree.TreePath;
+
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleEventBroadcaster;
+import com.sun.star.accessibility.XAccessibleEventListener;
+import com.sun.star.uno.UnoRuntime;
+
+public class AccessibilityTreeModel
+ extends AccessibilityTreeModelBase
+{
+ private boolean mbVerbose = false;
+
+ public AccessibilityTreeModel (AccessibleTreeNode aRoot)
+ {
+ // create default node (unless we have a 'proper' node)
+ setRoot (aRoot);
+
+ maNodeMap = new NodeMap();
+
+ mxListener = new QueuedListener(new EventListener (this));
+ }
+
+ public void clear ()
+ {
+ maNodeMap.Clear();
+ }
+
+ /** Lock the tree. While the tree is locked, events from the outside are
+ not processed. Lock the tree when you change its internal structure.
+ */
+ public void lock ()
+ {
+ mnLockCount += 1;
+ }
+
+ /** Unlock the tree. After unlocking the tree as many times as locking
+ it, a treeStructureChange event is sent to the event listeners.
+ @param aNodeHint
+ If not null and treeStructureChange events are thrown then this
+ node is used as root of the modified subtree.
+ */
+ public void unlock (AccessibleTreeNode aNodeHint)
+ {
+ mnLockCount -= 1;
+ if (mnLockCount == 0)
+ fireTreeStructureChanged (
+ new TreeModelEvent (this,
+ new TreePath (aNodeHint.createPath())));
+ }
+
+
+ @Override
+ public synchronized void setRoot (AccessibleTreeNode aRoot)
+ {
+ if (getRoot() == null)
+ super.setRoot (aRoot);
+ else
+ {
+ lock ();
+ maNodeMap.ForEach (new NodeMapCallback () {
+ @Override
+ public void Apply (AccTreeNode aNode)
+ {
+ if (maCanvas != null)
+ maCanvas.removeNode (aNode);
+ removeAccListener (aNode);
+ }
+ });
+ maNodeMap.Clear ();
+
+ setRoot (aRoot);
+ unlock (aRoot);
+ }
+ }
+
+
+
+ // child management:
+
+
+
+
+ /** Delegate the request to the parent and then register listeners at
+ the child and add the child to the canvas.
+ */
+ @Override
+ public synchronized Object getChild (Object aParent, int nIndex)
+ {
+ AccessibleTreeNode aChild = (AccessibleTreeNode)super.getChild (aParent, nIndex);
+
+ if (aChild == null)
+ System.out.println ("getChild: child not found");
+ else
+ // Keep translation table up-to-date.
+ addNode (aChild);
+
+ return aChild;
+ }
+
+ /** Remove a node (and all children) from the tree model.
+ */
+ private boolean removeChild (AccessibleTreeNode aNode)
+ {
+ try
+ {
+ if( aNode == null )
+ {
+ System.out.println ("can't remove null node");
+ return false;
+ }
+ else
+ {
+ // depth-first removal of children
+ while (aNode.getChildCount() > 0) {
+ if ( ! removeChild (aNode.getChildNoCreate (0)))
+ break;
+ }
+
+ // Remove node from its parent.
+ AccessibleTreeNode aParent = aNode.getParent();
+ if (aParent != null)
+ {
+ int nIndex = aParent.indexOf(aNode);
+ aParent.removeChild (nIndex);
+ }
+
+ maNodeMap.RemoveNode (aNode);
+ }
+ }
+ catch (Exception e)
+ {
+ System.out.println ("caught exception while removing child "
+ + aNode + " : " + e);
+ e.printStackTrace ();
+ return false;
+ }
+ return true;
+ }
+
+ public void removeNode (XAccessibleContext xNode)
+ {
+ if (xNode != null)
+ {
+ AccessibleTreeNode aNode = maNodeMap.GetNode (xNode);
+ AccessibleTreeNode aRootNode = (AccessibleTreeNode)getRoot();
+ TreeModelEvent aEvent = createEvent (aRootNode, aNode);
+ removeChild (aNode);
+ if (mbVerbose)
+ System.out.println (aNode);
+ fireTreeNodesRemoved (aEvent);
+ maCanvas.repaint ();
+ }
+ }
+
+
+ /** Add a new child to a parent.
+ @return
+ Returns the new or existing representation of the specified
+ accessible object.
+ */
+ private AccessibleTreeNode addChild (AccTreeNode aParentNode, XAccessible xNewChild)
+ {
+ AccessibleTreeNode aChildNode = null;
+ try
+ {
+ // First make sure that the accessible object does not already have
+ // a representation.
+ aChildNode = maNodeMap.GetNode(xNewChild);
+ if (aChildNode == null)
+ aChildNode = aParentNode.addAccessibleChild (xNewChild);
+ else
+ System.out.println ("node already present");
+ }
+ catch (Exception e)
+ {
+ System.out.println ("caught exception while adding child "
+ + xNewChild + " to parent " + aParentNode + ": " + e);
+ e.printStackTrace ();
+ }
+ return aChildNode;
+ }
+
+ public void addChild (XAccessibleContext xParent, XAccessible xChild)
+ {
+ AccessibleTreeNode aParentNode = maNodeMap.GetNode (xParent);
+ if (aParentNode instanceof AccTreeNode)
+ {
+ AccessibleTreeNode aChild = addChild ((AccTreeNode)aParentNode, xChild);
+ if (addNode (aChild))
+ {
+ if (maCanvas != null)
+ maCanvas.updateNode ((AccTreeNode)aParentNode);
+
+ // A call to fireTreeNodesInserted for xNew
+ // should be sufficient but at least the
+ // StringNode object that contains the number of
+ // children also changes and we do not know its
+ // index relative to its parent. Therefore the
+ // more expensive fireTreeStructureChanged is
+ // necessary.
+ fireTreeNodesInserted (createChildUpdateEvent (xParent));
+ updateNode (xParent, AccessibleTreeHandler.class);
+ }
+ maCanvas.repaint ();
+ }
+ }
+
+
+ /** Add the child node to the internal tree structure.
+ @param aNode
+ The node to insert into the internal tree structure.
+ */
+ private boolean addNode (AccessibleTreeNode aNode)
+ {
+ boolean bRet = false;
+ try
+ {
+ if ( ! maNodeMap.ValueIsMember (aNode))
+ {
+ if (aNode instanceof AccTreeNode)
+ {
+ AccTreeNode aChild = (AccTreeNode)aNode;
+ XAccessibleContext xChild = aChild.getContext();
+ registerAccListener (aChild);
+ if (maCanvas != null)
+ maCanvas.addNode (aChild);
+ maNodeMap.InsertNode (xChild, aChild);
+ }
+ bRet = true;
+ }
+
+ }
+ catch (Exception e)
+ {
+ System.out.println ("caught exception while adding node "
+ + aNode + ": " + e);
+ e.printStackTrace ();
+ }
+ return bRet;
+ }
+
+
+
+
+ /** create path to node, suitable for TreeModelEvent constructor
+ * @see javax.swing.event.TreeModelEvent#TreeModelEvent
+ */
+ private Object[] createPath (AccessibleTreeNode aNode)
+ {
+ ArrayList<AccessibleTreeNode> aPath = new ArrayList<AccessibleTreeNode>();
+ aNode.createPath (aPath);
+ return aPath.toArray();
+ }
+
+
+ // listeners (and helper methods)
+
+ // We are registered with listeners as soon as objects are in the
+ // tree cache, and we should get removed as soon as they are out.
+
+
+ private void fireTreeNodesChanged(TreeModelEvent e)
+ {
+ for(int i = 0; i < maTMListeners.size(); i++)
+ {
+ maTMListeners.get(i).treeNodesChanged(e);
+ }
+ }
+
+ protected void fireTreeNodesInserted(final TreeModelEvent e)
+ {
+ for(int i = 0; i < maTMListeners.size(); i++)
+ {
+ maTMListeners.get(i).treeNodesInserted(e);
+ }
+ }
+
+ private void fireTreeNodesRemoved(final TreeModelEvent e)
+ {
+ for(int i = 0; i < maTMListeners.size(); i++)
+ {
+ maTMListeners.get(i).treeNodesRemoved(e);
+ }
+ }
+
+ private void fireTreeStructureChanged(final TreeModelEvent e)
+ {
+ for(int i = 0; i < maTMListeners.size(); i++)
+ {
+ maTMListeners.get(i).treeStructureChanged(e);
+ }
+ }
+
+ /** Create a TreeModelEvent object that informs listeners that one child
+ has been removed from or inserted into its parent.
+ */
+ private TreeModelEvent createChildUpdateEvent (XAccessibleContext xParent)
+ {
+ AccessibleTreeNode aParentNode = maNodeMap.GetNode (xParent);
+ return createEvent (aParentNode, xParent);
+ }
+
+ private TreeModelEvent createEvent (AccessibleTreeNode aParentNode, XAccessibleContext xChild)
+ {
+ AccessibleTreeNode aChildNode = null;
+ if (xChild != null)
+ aChildNode = maNodeMap.GetNode (xChild);
+ return createEvent (aParentNode, aChildNode);
+ }
+
+
+
+ protected TreeModelEvent createEvent (
+ AccessibleTreeNode aParentNode,
+ AccessibleTreeNode aChildNode)
+ {
+ Object[] aPathToParent = createPath (aParentNode);
+
+ int nIndexInParent = -1;
+ if (aChildNode != null)
+ nIndexInParent = aParentNode.indexOf (aChildNode);
+ if (mbVerbose)
+ System.out.println (aChildNode + " " + nIndexInParent);
+
+ if (nIndexInParent == -1)
+ // This event may be passed only to treeStructureChanged of the listeners.
+ return new TreeModelEvent (this,
+ aPathToParent);
+ else
+ // General purpose event for removing or inserting known nodes.
+ return new TreeModelEvent (this,
+ aPathToParent,
+ new int[] {nIndexInParent},
+ new Object[] {aChildNode} );
+ }
+
+
+
+
+ /** Create a TreeModelEvent that indicates changes at those children of
+ the specified node with the specified indices.
+ */
+ private TreeModelEvent createChangeEvent (AccTreeNode aNode, java.util.List<Integer> aChildIndices)
+ {
+ // Build a list of child objects that are indicated by the given indices.
+ int nCount = aChildIndices.size();
+ Object aChildObjects[] = new Object[nCount];
+ int nChildIndices[] = new int[nCount];
+ for (int i=0; i<nCount; i++)
+ {
+ int nIndex = aChildIndices.get(i);
+ aChildObjects[i] = aNode.getChild (nIndex);
+ nChildIndices[i] = nIndex;
+ }
+
+ return new TreeModelEvent (this,
+ createPath(aNode),
+ nChildIndices,
+ aChildObjects);
+ }
+
+
+
+ private XAccessibleEventBroadcaster getBroadcaster (Object aObject)
+ {
+ if (aObject instanceof AccTreeNode)
+ return UnoRuntime.queryInterface (
+ XAccessibleEventBroadcaster.class, ((AccTreeNode)aObject).getContext());
+ else
+ return null;
+ }
+
+ private void registerAccListener( Object aObject )
+ {
+ // register this as listener for XAccessibleEventBroadcaster
+ // implementations
+ XAccessibleEventBroadcaster xBroadcaster = getBroadcaster( aObject );
+ if (xBroadcaster != null)
+ {
+ xBroadcaster.addAccessibleEventListener( mxListener );
+ }
+ }
+
+ private void removeAccListener( Object aObject )
+ {
+ XAccessibleEventBroadcaster xBroadcaster = getBroadcaster( aObject );
+ if (xBroadcaster != null)
+ {
+ xBroadcaster.removeAccessibleEventListener( mxListener );
+ }
+ }
+
+
+
+ public void setCanvas (Canvas aCanvas)
+ {
+ maCanvas = aCanvas;
+ }
+
+ public Canvas getCanvas ()
+ {
+ return maCanvas;
+ }
+
+ public void updateNode (XAccessibleContext xSource, java.lang.Class class1)
+ {
+ updateNode (xSource, class1,null);
+ }
+
+ /** Get a list of children of the node associated with xSource that are
+ affected by the given handlers. Fire events that these children may
+ have changed in the tree view. Update the canvas representation of
+ xSource.
+ */
+ public AccTreeNode updateNode (XAccessibleContext xSource,
+ java.lang.Class class1, java.lang.Class<AccessibleExtendedComponentHandler> class2)
+ {
+ AccessibleTreeNode aTreeNode = maNodeMap.GetNode (xSource);
+ AccTreeNode aNode = null;
+ if (mbVerbose)
+ System.out.println ("updating node " + xSource + " " + aTreeNode);
+ if (aTreeNode instanceof AccTreeNode)
+ {
+ aNode = (AccTreeNode) aTreeNode;
+ // Get list of affected children.
+ java.util.List<Integer> aChildIndices = aNode.updateChildren (
+ class1, class2);
+ // Fire events that these children may have changed.
+ fireTreeNodesChanged (
+ createChangeEvent (aNode, aChildIndices));
+ }
+ return aNode;
+ }
+
+ /** The listener to be registered with the accessible objects.
+ * Could be set to 'this' for same-thread event delivery, or to an
+ * instance of QueuedListener for multi-threaded delivery. May
+ * not be changed, since this would trip the
+ * register/removeAccListener logic. */
+ private final XAccessibleEventListener mxListener;
+
+ // Map to translate from accessible object to corresponding tree node.
+ private final NodeMap maNodeMap;
+
+ // If the lock count is higher then zero, then no events are processed.
+ private int mnLockCount;
+
+ private Canvas maCanvas;
+}
diff --git a/toolkit/test/accessibility/AccessibilityTreeModelBase.java b/toolkit/test/accessibility/AccessibilityTreeModelBase.java
new file mode 100644
index 0000000000..5ff2d96c9e
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibilityTreeModelBase.java
@@ -0,0 +1,140 @@
+/*
+ * 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 .
+ */
+
+import java.util.ArrayList;
+
+import javax.swing.event.TreeModelListener;
+import javax.swing.tree.TreeModel;
+import javax.swing.tree.TreePath;
+
+public class AccessibilityTreeModelBase
+ implements TreeModel
+{
+ public AccessibilityTreeModelBase ()
+ {
+ setRoot (null);
+ maTMListeners = new ArrayList<TreeModelListener>();
+ }
+
+ public synchronized void addTreeModelListener(TreeModelListener l)
+ {
+ maTMListeners.add(l);
+ }
+
+ public synchronized void removeTreeModelListener(TreeModelListener l)
+ {
+ maTMListeners.remove(l);
+ }
+
+ public synchronized int getChildCount(Object aParent)
+ {
+ return (aParent instanceof AccessibleTreeNode) ?
+ ((AccessibleTreeNode)aParent).getChildCount() : 0;
+ }
+
+ public synchronized Object getChild (Object aParent, int nIndex)
+ {
+ Object aChild = null;
+ try
+ {
+ if (aParent instanceof AccessibleTreeNode)
+ aChild = ((AccessibleTreeNode)aParent).getChild(nIndex);
+ else
+ System.out.println ("getChild called for unknown parent node");
+ }
+ catch (com.sun.star.lang.IndexOutOfBoundsException e)
+ {
+ aChild = ("no child " + nIndex + " from " + aParent + ": " + e);
+ }
+ return aChild;
+ }
+
+ public synchronized Object getChildNoCreate (Object aParent, int nIndex)
+ {
+ Object aChild = null;
+ try
+ {
+ if (aParent instanceof AccessibleTreeNode)
+ aChild = ((AccessibleTreeNode)aParent).getChildNoCreate(nIndex);
+ else
+ System.out.println ("getChild called for unknown parent node");
+ }
+ catch (com.sun.star.lang.IndexOutOfBoundsException e)
+ { }
+ return aChild;
+ }
+
+ /** iterate over all children and look for child */
+ public synchronized int getIndexOfChild (Object aParent, Object aChild)
+ {
+ int nIndex = -1;
+ try
+ {
+ if ((aParent instanceof AccessibleTreeNode) && (aChild instanceof AccessibleTreeNode))
+ {
+ AccessibleTreeNode aParentNode = (AccessibleTreeNode) aParent;
+ AccessibleTreeNode aChildNode = (AccessibleTreeNode) aChild;
+
+ int nChildCount = aParentNode.getChildCount();
+ for( int i = 0; i < nChildCount; i++ )
+ {
+ if (aChildNode.equals (aParentNode.getChild (i)))
+ {
+ nIndex = i;
+ break;
+ }
+ }
+ }
+ }
+ catch (com.sun.star.lang.IndexOutOfBoundsException e)
+ {
+ // Return -1 by falling through.
+ }
+
+ // not found?
+ return nIndex;
+ }
+
+ public boolean isLeaf (Object aNode)
+ {
+ return (aNode instanceof AccessibleTreeNode) ?
+ ((AccessibleTreeNode)aNode).isLeaf() : true;
+ }
+
+
+
+ public synchronized Object getRoot()
+ {
+ return maRoot;
+ }
+
+ public void valueForPathChanged(TreePath path, Object newValue)
+ { }
+
+ protected synchronized void setRoot (AccessibleTreeNode aRoot)
+ {
+ maRoot = aRoot;
+ }
+
+
+ // The list of TreeModelListener objects.
+ protected ArrayList<TreeModelListener> maTMListeners;
+
+ // The root node of the tree. Use setRoot to change it.
+ private AccessibleTreeNode maRoot = null;
+}
diff --git a/toolkit/test/accessibility/AccessibilityWorkBench.java b/toolkit/test/accessibility/AccessibilityWorkBench.java
new file mode 100644
index 0000000000..918b8cf6dd
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibilityWorkBench.java
@@ -0,0 +1,591 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.frame.XFrame;
+import com.sun.star.frame.XTerminateListener;
+import com.sun.star.uno.UnoRuntime;
+
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.awt.XExtendedToolkit;
+
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.tree.*;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.event.TreeSelectionEvent;
+import ov.ObjectViewContainer;
+
+/** This class manages the GUI of the work bench.
+ @see AccessibilityTreeModel
+ for the implementation of the tree view on the left side which also
+ manages the registration of accessibility listeners.
+ @see Canvas
+ for the graphical view of the accessible objects.
+*/
+public class AccessibilityWorkBench
+ extends JFrame
+ implements ActionListener, XTerminateListener, TreeSelectionListener
+
+{
+ private static final String msVersion = "v1.7.2";
+ private String msOptionsFileName = ".AWBrc";
+
+ public static void main (String args[])
+ {
+ int nPortNumber = 5678;
+
+ for (int i=0; i<args.length; i++)
+ {
+ if (args[i].equals ("-h") || args[i].equals ("--help") || args[i].equals ("-?"))
+ {
+ System.out.println ("usage: AccessibilityWorkBench <option>*");
+ System.out.println ("options:");
+ System.out.println (" -p <port-number> Port on which to connect to StarOffice.");
+ System.out.println (" Defaults to 5678.");
+ System.exit (0);
+ }
+ else if (args[i].equals ("-p"))
+ {
+ nPortNumber = Integer.parseInt (args[++i]);
+ }
+ }
+
+ saWorkBench = new AccessibilityWorkBench (nPortNumber);
+ }
+
+
+
+
+ /** Return the one instance of the AccessibilityWorkBench
+ @return
+ Returns null when the AccessibilityWorkBench could not be
+ created successfully.
+ */
+ public static AccessibilityWorkBench Instance ()
+ {
+ return saWorkBench;
+ }
+
+
+
+ /** Create an accessibility work bench that listens at the specified
+ port to Office applications.
+ */
+ private AccessibilityWorkBench (int nPortNumber)
+ {
+ mbInitialized = false;
+
+ Layout ();
+
+ MessageArea.println (System.getProperty ("os.name") + " / "
+ + System.getProperty ("os.arch") + " / "
+ + System.getProperty ("os.version"));
+ MessageArea.println ("Using port " + nPortNumber);
+ office = new SimpleOffice (nPortNumber);
+
+ maAccessibilityTree.getComponent().addTreeSelectionListener (this);
+
+ addWindowListener (new WindowAdapter ()
+ { @Override
+ public void windowClosing (WindowEvent e)
+ { System.exit(0); }
+ });
+
+ initialize ();
+ }
+
+
+
+
+ /** Create and arrange the widgets of the GUI.
+ */
+ private void Layout ()
+ {
+ setSize (new Dimension (8000,600));
+
+ // Create new layout.
+ GridBagLayout aLayout = new GridBagLayout ();
+ getContentPane().setLayout (aLayout);
+
+ // Accessible Tree.
+ maAccessibilityTree = new AccessibilityTree ();
+ JScrollPane aTreeScrollPane = new JScrollPane(
+ maAccessibilityTree.getComponent(),
+ JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
+ JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
+ aTreeScrollPane.setPreferredSize (new Dimension (400,300));
+
+ // Object view shows details about the currently selected accessible
+ // object.
+ maObjectViewContainer = new ObjectViewContainer ();
+ JScrollPane aObjectViewContainerScrollPane = new JScrollPane(
+ maObjectViewContainer,
+ JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ aObjectViewContainerScrollPane.setPreferredSize (new Dimension (400,300));
+
+ // Split pane for tree view and object view.
+ JSplitPane aLeftViewSplitPane = new JSplitPane (
+ JSplitPane.VERTICAL_SPLIT,
+ aTreeScrollPane,
+ aObjectViewContainerScrollPane
+ );
+ aLeftViewSplitPane.setDividerLocation (300);
+
+ // Canvas.
+ maCanvas = new Canvas ();
+ maCanvas.setTree (maAccessibilityTree.getComponent());
+ maAccessibilityTree.SetCanvas (maCanvas);
+ JScrollPane aScrolledCanvas = new JScrollPane(maCanvas,
+ JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ aScrolledCanvas.getViewport().setBackground (Color.RED);
+ aScrolledCanvas.setPreferredSize (new Dimension(600,400));
+
+ // Split pane for tree view and canvas.
+ JSplitPane aViewSplitPane = new JSplitPane (
+ JSplitPane.HORIZONTAL_SPLIT,
+ aLeftViewSplitPane,
+ aScrolledCanvas
+ );
+ aViewSplitPane.setOneTouchExpandable(true);
+ aViewSplitPane.setDividerLocation (400);
+
+ // Text output area.
+ MessageArea aMessageArea = MessageArea.Instance ();
+
+ // Split pane for the two views and the message area.
+ JSplitPane aSplitPane = new JSplitPane (JSplitPane.VERTICAL_SPLIT,
+ aViewSplitPane, aMessageArea);
+ aSplitPane.setOneTouchExpandable(true);
+ addGridElement (aViewSplitPane, 0,0, 2,1, 3,3,
+ GridBagConstraints.CENTER, GridBagConstraints.BOTH);
+
+ // Button bar.
+ maButtonBar = new JPanel();
+ maButtonBar.setLayout (new FlowLayout());
+ addGridElement (maButtonBar, 0,3, 2,1, 1,0,
+ GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL);
+
+ // Buttons.
+ aConnectButton = createButton ("Connect", "connect");
+ aUpdateButton = createButton ("Update", "update");
+ aShapesButton = createButton ("Expand Shapes", "shapes");
+ aExpandButton = createButton ("Expand All", "expand");
+ aQuitButton = createButton ("Quit", "quit");
+ UpdateButtonStates ();
+
+ Options.Instance().Load (msOptionsFileName);
+
+ setJMenuBar (CreateMenuBar ());
+
+ setTitle("Accessibility Workbench " + msVersion);
+
+ pack ();
+ setVisible (true);
+ validate ();
+ repaint();
+ }
+
+
+
+
+ /** Shortcut method for adding an object to a GridBagLayout.
+ */
+ private void addGridElement (JComponent object,
+ int x, int y, int width, int height, int weightx, int weighty,
+ int anchor, int fill)
+ {
+ GridBagConstraints constraints = new GridBagConstraints ();
+ constraints.gridx = x;
+ constraints.gridy = y;
+ constraints.gridwidth = width;
+ constraints.gridheight = height;
+ constraints.weightx = weightx;
+ constraints.weighty = weighty;
+ constraints.anchor = anchor;
+ constraints.fill = fill;
+ getContentPane().add (object, constraints);
+ }
+
+
+
+
+ /** Create a new button and place at the right most position into the
+ button bar.
+ */
+ private JButton createButton (String title, String command)
+ {
+ JButton aButton = new JButton (title);
+ aButton.setEnabled (false);
+ aButton.setActionCommand (command);
+ aButton.addActionListener (this);
+
+ maButtonBar.add (aButton);
+ return aButton;
+ }
+
+
+
+
+ /** Create a menu bar for the application.
+ @return
+ Returns the new menu bar. The returned reference is also
+ remembered in the data member <member>maMenuBar</member>.
+ */
+ private JMenuBar CreateMenuBar ()
+ {
+ // Menu bar.
+ JMenuBar aMenuBar = new JMenuBar ();
+
+ // File menu.
+ JMenu aFileMenu = new JMenu ("File");
+ aMenuBar.add (aFileMenu);
+ JMenuItem aItem;
+ aItem = new JMenuItem ("Quit");
+ aFileMenu.add (aItem);
+ aItem.addActionListener (this);
+
+ // View menu.
+ JMenu aViewMenu = new JMenu ("View");
+ aMenuBar.add (aViewMenu);
+ ButtonGroup aGroup = new ButtonGroup ();
+ JRadioButtonMenuItem aRadioButton = new JRadioButtonMenuItem ("Whole Screen");
+ aGroup.add (aRadioButton);
+ aViewMenu.add (aRadioButton);
+ aRadioButton.addActionListener (this);
+ aRadioButton = new JRadioButtonMenuItem ("200%");
+ aGroup.add (aRadioButton);
+ aViewMenu.add (aRadioButton);
+ aRadioButton.addActionListener (this);
+ aRadioButton = new JRadioButtonMenuItem ("100%");
+ aGroup.add (aRadioButton);
+ aViewMenu.add (aRadioButton);
+ aRadioButton.addActionListener (this);
+ aRadioButton = new JRadioButtonMenuItem ("50%");
+ aGroup.add (aRadioButton);
+ aViewMenu.add (aRadioButton);
+ aRadioButton.addActionListener (this);
+ aRadioButton = new JRadioButtonMenuItem ("25%");
+ aGroup.add (aRadioButton);
+ aViewMenu.add (aRadioButton);
+ aRadioButton.addActionListener (this);
+ aRadioButton = new JRadioButtonMenuItem ("10%");
+ aGroup.add (aRadioButton);
+ aViewMenu.add (aRadioButton);
+ aRadioButton.addActionListener (this);
+
+ // Options menu.
+ JMenu aOptionsMenu = new JMenu ("Options");
+ aMenuBar.add (aOptionsMenu);
+ JCheckBoxMenuItem aCBItem;
+ aCBItem = new JCheckBoxMenuItem ("Show Descriptions", maCanvas.getShowDescriptions());
+ aOptionsMenu.add (aCBItem);
+ aCBItem.addActionListener (this);
+
+ aCBItem = new JCheckBoxMenuItem ("Show Names", maCanvas.getShowNames());
+ aOptionsMenu.add (aCBItem);
+ aCBItem.addActionListener (this);
+
+ aCBItem = new JCheckBoxMenuItem ("Show Text", maCanvas.getShowText());
+ aOptionsMenu.add (aCBItem);
+ aCBItem.addActionListener (this);
+
+ aCBItem = new JCheckBoxMenuItem ("Antialiased Rendering", maCanvas.getAntialiasing());
+ aOptionsMenu.add (aCBItem);
+ aCBItem.addActionListener (this);
+
+ // Help menu.
+ JMenu aHelpMenu = new JMenu ("Help");
+ aMenuBar.add (aHelpMenu);
+
+ aItem = new JMenuItem ("Help");
+ aHelpMenu.add (aItem);
+ aItem.addActionListener (this);
+
+ aItem = new JMenuItem ("News");
+ aHelpMenu.add (aItem);
+ aItem.addActionListener (this);
+
+ aItem = new JMenuItem ("About");
+ aHelpMenu.add (aItem);
+ aItem.addActionListener (this);
+
+ return aMenuBar;
+ }
+
+
+
+
+ /** Initialize the AWB. This includes clearing the canvas, add
+ listeners, creation of a new tree model for the tree list box and
+ the update of the button states.
+
+ This method may be called any number of times. Note that all
+ actions will be carried out every time. The main purpose of a
+ second call is that of a re-initialization after a reconnect.
+ */
+ private void initialize ()
+ {
+ maCanvas.clear();
+
+ AccessibilityTreeModel aModel = null;
+ aModel = new AccessibilityTreeModel (createTreeModelRoot());
+
+ aModel.setCanvas (maCanvas);
+ maAccessibilityTree.getComponent().setModel (aModel);
+
+ if (office != null)
+ {
+ // Add terminate listener.
+ if (office.getDesktop() != null)
+ office.getDesktop().addTerminateListener (this);
+
+ XExtendedToolkit xToolkit = office.getExtendedToolkit();
+ // Remove old top window listener.
+ if (maTopWindowListener != null)
+ xToolkit.removeTopWindowListener (maQueuedTopWindowListener);
+ // Add top window listener.
+ if (xToolkit != null)
+ {
+ MessageArea.println ("registering at extended toolkit");
+ maTopWindowListener = new TopWindowListener (aModel, office);
+ maQueuedTopWindowListener = new QueuedTopWindowListener (maTopWindowListener);
+ xToolkit.addTopWindowListener (maQueuedTopWindowListener);
+ maTopWindowListener.Initialize ();
+ }
+ else
+ maTopWindowListener = null;
+ }
+
+ mbInitialized = true;
+ UpdateButtonStates ();
+ }
+
+
+
+
+ /** Update the states of the buttons according to the internal state of
+ the AWB.
+ */
+ private void UpdateButtonStates ()
+ {
+ aConnectButton.setEnabled (mbInitialized);
+ aQuitButton.setEnabled (mbInitialized);
+ aUpdateButton.setEnabled (mbInitialized);
+ aExpandButton.setEnabled (mbInitialized);
+ aShapesButton.setEnabled (mbInitialized);
+ }
+
+
+
+ /** Callback for GUI actions from the buttons.
+ */
+ public void actionPerformed (java.awt.event.ActionEvent e)
+ {
+ if (e.getActionCommand().equals("connect"))
+ {
+ office.connect();
+ initialize ();
+ }
+ else if (e.getActionCommand().equals("quit"))
+ {
+ AccessibilityTreeModel aModel = (AccessibilityTreeModel)maAccessibilityTree.getComponent().getModel();
+ aModel.clear();
+ System.exit (0);
+ }
+ else if (e.getActionCommand().equals("update"))
+ {
+ initialize ();
+ }
+ else if (e.getActionCommand().equals("shapes"))
+ {
+ Cursor aCursor = getCursor();
+ setCursor (new Cursor (Cursor.WAIT_CURSOR));
+ maAccessibilityTree.expandShapes();
+ setCursor (aCursor);
+ }
+ else if (e.getActionCommand().equals("expand"))
+ {
+ Cursor aCursor = getCursor();
+ setCursor (new Cursor (Cursor.WAIT_CURSOR));
+ maAccessibilityTree.expandAll();
+ setCursor (aCursor);
+ }
+ else if (e.getActionCommand().equals ("Quit"))
+ {
+ System.out.println ("exiting");
+ System.exit (0);
+ }
+ else if (e.getActionCommand().equals ("Show Descriptions"))
+ {
+ maCanvas.setShowDescriptions ( ! maCanvas.getShowDescriptions());
+ Options.Instance().Save (msOptionsFileName);
+ }
+ else if (e.getActionCommand().equals ("Show Names"))
+ {
+ maCanvas.setShowNames ( ! maCanvas.getShowNames());
+ Options.Instance().Save (msOptionsFileName);
+ }
+ else if (e.getActionCommand().equals ("Antialiased Rendering"))
+ {
+ maCanvas.setAntialiasing ( ! maCanvas.getAntialiasing());
+ Options.Instance().Save (msOptionsFileName);
+ }
+ else if (e.getActionCommand().equals ("Help"))
+ {
+ HelpWindow.Instance().loadFile ("help.html");
+ }
+ else if (e.getActionCommand().equals ("News"))
+ {
+ try{
+ HelpWindow.Instance().loadFile ("news.html");
+ } catch (Exception ex) {}
+ }
+ else if (e.getActionCommand().equals ("About"))
+ {
+ HelpWindow.Instance().loadFile ("about.html");
+ }
+ else if (e.getActionCommand().equals ("Whole Screen"))
+ {
+ maCanvas.setZoomMode (Canvas.WHOLE_SCREEN);
+ Options.Instance().Save (msOptionsFileName);
+ }
+ else if (e.getActionCommand().equals ("200%"))
+ {
+ maCanvas.setZoomMode (200);
+ Options.Instance().Save (msOptionsFileName);
+ }
+ else if (e.getActionCommand().equals ("100%"))
+ {
+ maCanvas.setZoomMode (100);
+ Options.Instance().Save (msOptionsFileName);
+ }
+ else if (e.getActionCommand().equals ("50%"))
+ {
+ maCanvas.setZoomMode (50);
+ Options.Instance().Save (msOptionsFileName);
+ }
+ else if (e.getActionCommand().equals ("25%"))
+ {
+ maCanvas.setZoomMode (25);
+ Options.Instance().Save (msOptionsFileName);
+ }
+ else if (e.getActionCommand().equals ("10%"))
+ {
+ maCanvas.setZoomMode (10);
+ Options.Instance().Save (msOptionsFileName);
+ }
+ else
+ {
+ System.err.println("unknown command " + e.getActionCommand());
+ }
+ }
+
+
+
+
+ /** Create an AccessibilityTreeModel root which contains the documents
+ (top windows) that are present at the moment.
+ */
+ private AccessibleTreeNode createTreeModelRoot()
+ {
+ // create root node
+ VectorNode aRoot = new VectorNode ("Accessibility Tree", null);
+ if (maTopWindowListener != null)
+ maTopWindowListener.Initialize ();
+ return aRoot;
+ }
+
+
+ // TreeSelectionListener
+ public void valueChanged (TreeSelectionEvent aEvent)
+ {
+ TreePath aPath = aEvent.getPath();
+ Object aObject = aPath.getLastPathComponent();
+ if (aObject instanceof AccTreeNode)
+ {
+ AccTreeNode aNode = (AccTreeNode) aObject;
+ XAccessibleContext xContext = aNode.getContext();
+ maObjectViewContainer.SetObject (xContext);
+ }
+ }
+
+
+
+
+ // XEventListener
+ public void disposing( com.sun.star.lang.EventObject aSourceObj )
+ {
+ XFrame xFrame = UnoRuntime.queryInterface(XFrame.class, aSourceObj.Source);
+
+ if( xFrame != null )
+ System.out.println("frame disposed");
+ else
+ System.out.println("controller disposed");
+ }
+
+
+
+
+ // XTerminateListener
+ public void queryTermination (final com.sun.star.lang.EventObject aEvent) throws RuntimeException
+ {
+ System.out.println ("Terminate Event : " + aEvent);
+ }
+
+
+
+
+ // XTerminateListener
+ public void notifyTermination (final com.sun.star.lang.EventObject aEvent) throws RuntimeException
+ {
+ System.out.println ("Notify Termination Event : " + aEvent);
+ }
+
+
+
+ /// The Singleton Workbench object.
+ private static AccessibilityWorkBench
+ saWorkBench = null;
+
+ private SimpleOffice
+ office;
+
+ private JPanel
+ maButtonBar;
+ private Canvas
+ maCanvas;
+ private AccessibilityTree
+ maAccessibilityTree;
+ private ObjectViewContainer
+ maObjectViewContainer;
+ private JButton
+ aConnectButton,
+ aQuitButton,
+ aUpdateButton,
+ aExpandButton,
+ aShapesButton;
+ private boolean
+ mbInitialized;
+ private TopWindowListener
+ maTopWindowListener;
+ private QueuedTopWindowListener
+ maQueuedTopWindowListener;
+}
diff --git a/toolkit/test/accessibility/AccessibleActionHandler.java b/toolkit/test/accessibility/AccessibleActionHandler.java
new file mode 100644
index 0000000000..868ea1105c
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleActionHandler.java
@@ -0,0 +1,91 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleAction;
+import com.sun.star.lang.IndexOutOfBoundsException;
+
+class AccessibleActionHandler
+ extends NodeHandler
+{
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ XAccessibleAction xEComponent =
+ UnoRuntime.queryInterface (
+ XAccessibleAction.class, xContext);
+ if (xEComponent != null)
+ return new AccessibleActionHandler (xEComponent);
+ else
+ return null;
+ }
+
+ public AccessibleActionHandler ()
+ {
+ }
+
+ private AccessibleActionHandler (XAccessibleAction xAction)
+ {
+ if (xAction != null)
+ maChildList.setSize (1 + xAction.getAccessibleActionCount());
+ }
+
+ protected static XAccessibleAction getAction (AccTreeNode aParent)
+ {
+ return UnoRuntime.queryInterface (
+ XAccessibleAction.class, aParent.getContext());
+ }
+
+ @Override
+ public AccessibleTreeNode createChild (
+ AccessibleTreeNode aParent,
+ int nIndex)
+ {
+ AccessibleTreeNode aChild = null;
+
+ if (aParent instanceof AccTreeNode)
+ {
+ XAccessibleAction xAction = getAction ((AccTreeNode)aParent);
+ if( xAction != null )
+ {
+ if (nIndex == 0)
+ aChild = new StringNode ("Number of actions: " + xAction.getAccessibleActionCount(),
+ aParent);
+ else
+ {
+ nIndex -= 1;
+ try
+ {
+ aChild = new AccessibleActionNode (
+ "Action " + nIndex + " : "
+ + xAction.getAccessibleActionDescription (nIndex),
+ aParent,
+ nIndex);
+ }
+ catch( IndexOutOfBoundsException e )
+ {
+ aChild = new StringNode ("ERROR", aParent);
+ }
+ }
+ }
+ }
+
+ return aChild;
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleActionNode.java b/toolkit/test/accessibility/AccessibleActionNode.java
new file mode 100644
index 0000000000..c1c927574c
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleActionNode.java
@@ -0,0 +1,67 @@
+/*
+ * 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 .
+ */
+
+import javax.swing.JOptionPane;
+
+/**
+ Base class for all tree nodes.
+ */
+class AccessibleActionNode
+ extends StringNode
+{
+ public AccessibleActionNode (String aDisplayObject,
+ AccessibleTreeNode aParent,
+ int nActionIndex)
+ {
+ super (aDisplayObject, aParent);
+ mnActionIndex = nActionIndex;
+ }
+
+ @Override
+ public String[] getActions ()
+ {
+ return new String[] {"Perform Action"};
+ }
+
+ /** perform action */
+ @Override
+ public void performAction (int nIndex)
+ {
+ if (nIndex != 0)
+ return;
+ boolean bResult = false;
+ if (getParent() instanceof AccTreeNode)
+ try
+ {
+ bResult = AccessibleActionHandler.getAction(
+ (AccTreeNode)getParent()).doAccessibleAction (
+ mnActionIndex);
+ }
+ catch (com.sun.star.lang.IndexOutOfBoundsException e)
+ {
+ }
+
+ JOptionPane.showMessageDialog (null,
+ "performed action " + mnActionIndex
+ + (bResult?" with":" without") + " success",
+ "Action " + mnActionIndex,
+ JOptionPane.INFORMATION_MESSAGE);
+ }
+
+ private final int mnActionIndex;
+}
diff --git a/toolkit/test/accessibility/AccessibleCellHandler.java b/toolkit/test/accessibility/AccessibleCellHandler.java
new file mode 100644
index 0000000000..716e1374ef
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleCellHandler.java
@@ -0,0 +1,168 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleTable;
+import com.sun.star.accessibility.XAccessible;
+
+
+class AccessibleCellHandler extends NodeHandler
+{
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ if (xContext == null)
+ return null;
+
+ AccessibleCellHandler aCellHandler = null;
+ XAccessible xParent = xContext.getAccessibleParent();
+ if (xParent != null)
+ {
+ XAccessibleTable xTable =
+ UnoRuntime.queryInterface (
+ XAccessibleTable.class, xParent.getAccessibleContext());
+ if (xTable != null)
+ aCellHandler = new AccessibleCellHandler (xTable);
+ }
+ return aCellHandler;
+ }
+
+ public AccessibleCellHandler ()
+ {
+ }
+
+ private AccessibleCellHandler (XAccessibleTable xTable)
+ {
+ if (xTable != null)
+ maChildList.setSize (8);
+ }
+
+ @Override
+ public AccessibleTreeNode createChild (AccessibleTreeNode aParent, int nIndex)
+ {
+ AccessibleTreeNode aChild = null;
+ XAccessibleTable xTable = null;
+ XAccessibleContext xContext = null;
+ AccessibleTreeNode aGrandParent = aParent.getParent();
+ if (aGrandParent instanceof AccTreeNode)
+ {
+ xTable = ((AccTreeNode)aGrandParent).getTable();
+ xContext = ((AccTreeNode)aGrandParent).getContext();
+ }
+ if (aParent instanceof AccTreeNode)
+ {
+ xContext = ((AccTreeNode)aParent).getContext();
+ }
+ try
+ {
+ if( xTable != null && xContext != null )
+ {
+ switch( nIndex )
+ {
+ case 0:
+ {
+ long nChild = xContext.getAccessibleIndexInParent();
+ int nRow = xTable.getAccessibleRow( nChild );
+
+ aChild = new StringNode ("# table row: " + nRow, aParent);
+ }
+ break;
+ case 1:
+ {
+ long nChild = xContext.getAccessibleIndexInParent();
+ int nCol = xTable.getAccessibleColumn( nChild );
+
+ aChild = new StringNode ("# table column: " + nCol, aParent);
+ }
+ break;
+ case 2:
+ {
+ long nChild = xContext.getAccessibleIndexInParent();
+ int nRow = xTable.getAccessibleRow( nChild );
+ int nCol = xTable.getAccessibleColumn( nChild );
+ int nExt = xTable.getAccessibleRowExtentAt( nRow, nCol );
+
+ aChild = new StringNode ("# table row extend: " + nExt, aParent);
+ }
+ break;
+ case 3:
+ {
+ long nChild = xContext.getAccessibleIndexInParent();
+ int nRow = xTable.getAccessibleRow( nChild );
+ int nCol = xTable.getAccessibleColumn( nChild );
+ int nExt = xTable.getAccessibleColumnExtentAt( nRow, nCol );
+
+ aChild = new StringNode ("# table column extend: " + nExt, aParent);
+ }
+ break;
+ case 4:
+ {
+ long nChild = xContext.getAccessibleIndexInParent();
+ int nRow = xTable.getAccessibleRow( nChild );
+ int nCol = xTable.getAccessibleColumn( nChild );
+ XAccessible xChild =
+ xTable.getAccessibleCellAt( nRow, nCol );
+
+ aChild = new StringNode ("# cell name retrieved from table: " + xChild.getAccessibleContext().getAccessibleName(), aParent);
+ }
+ break;
+ case 5:
+ {
+ int nChild = xContext.getAccessibleIndexInParent();
+ int nRow = xTable.getAccessibleRow( nChild );
+ int nCol = xTable.getAccessibleColumn( nChild );
+ boolean bSelected =
+ xTable.isAccessibleSelected( nRow, nCol );
+
+ aChild = new StringNode ("cell is selected: " + bSelected, aParent);
+ }
+ break;
+ case 6:
+ {
+ long nChild = xContext.getAccessibleIndexInParent();
+ int nRow = xTable.getAccessibleRow( nChild );
+ boolean bSelected =
+ xTable.isAccessibleRowSelected( nRow );
+
+ aChild = new StringNode ("table row is selected: " + bSelected, aParent);
+ }
+ break;
+ case 7:
+ {
+ long nChild = xContext.getAccessibleIndexInParent();
+ int nCol = xTable.getAccessibleColumn( nChild );
+ boolean bSelected =
+ xTable.isAccessibleColumnSelected( nCol );
+
+ aChild = new StringNode ("table column is selected: " + bSelected, aParent);
+ }
+ break;
+ default:
+ aChild = new StringNode ("unknown child index " + nIndex, aParent);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ // Return empty child.
+ }
+
+ return aChild;
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleComponentHandler.java b/toolkit/test/accessibility/AccessibleComponentHandler.java
new file mode 100644
index 0000000000..229612b8dd
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleComponentHandler.java
@@ -0,0 +1,121 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleComponent;
+
+
+class AccessibleComponentHandler
+ extends NodeHandler
+{
+
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ XAccessibleComponent xComponent =
+ UnoRuntime.queryInterface (
+ XAccessibleComponent.class, xContext);
+ if (xComponent != null)
+ return new AccessibleComponentHandler (xComponent);
+ else
+ return null;
+
+ }
+
+ public AccessibleComponentHandler ()
+ {
+ }
+
+ private AccessibleComponentHandler (XAccessibleComponent xComponent)
+ {
+ if (xComponent != null)
+ maChildList.setSize (6);
+ }
+
+ @Override
+ public AccessibleTreeNode createChild (AccessibleTreeNode aParent, int nIndex)
+ {
+ AccessibleTreeNode aChild = null;
+ if (aParent instanceof AccTreeNode)
+ {
+ XAccessibleComponent xComponent =
+ ((AccTreeNode)aParent).getComponent();
+
+ if (xComponent != null)
+ {
+ int nColor;
+ switch (nIndex)
+ {
+ case 0:
+ com.sun.star.awt.Point aLocation = xComponent.getLocation();
+ aChild = new StringNode (
+ "Location: " + aLocation.X + ", " + aLocation.Y,
+ aParent);
+ break;
+ case 1:
+ com.sun.star.awt.Point aScreenLocation = xComponent.getLocationOnScreen();
+ aChild = new StringNode (
+ "Location on Screen: " + aScreenLocation.X + ", " + aScreenLocation.Y,
+ aParent);
+ break;
+ case 2:
+ com.sun.star.awt.Size aSize = xComponent.getSize();
+ aChild = new StringNode (
+ "Size: "+ aSize.Width + ", " + aSize.Height,
+ aParent);
+ break;
+ case 3:
+ com.sun.star.awt.Rectangle aBBox = xComponent.getBounds();
+ aChild = new StringNode (
+ "Bounding Box: "+ aBBox.X + ", " + aBBox.Y + ","
+ + aBBox.Width + ", " + aBBox.Height,
+ aParent);
+ break;
+ case 4:
+ nColor = xComponent.getForeground();
+ aChild = new StringNode ("Foreground color: R"
+ + (nColor>>16&0xff)
+ + "G" + (nColor>>8&0xff)
+ + "B" + (nColor&0xff)
+ + "A" + (nColor>>24&0xff),
+ aParent);
+ break;
+ case 5:
+ nColor = xComponent.getBackground();
+ aChild = new StringNode ("Background color: R"
+ + (nColor>>16&0xff)
+ + "G" + (nColor>>8&0xff)
+ + "B" + (nColor&0xff)
+ + "A" + (nColor>>24&0xff),
+ aParent);
+ break;
+ }
+ }
+ }
+ return aChild;
+ }
+
+ @Override
+ public void update (AccessibleTreeNode aNode)
+ {
+ maChildList.clear();
+ if (aNode instanceof AccTreeNode && ((AccTreeNode)aNode).getComponent() != null)
+ maChildList.setSize (4);
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleContextHandler.java b/toolkit/test/accessibility/AccessibleContextHandler.java
new file mode 100644
index 0000000000..62bd4b8132
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleContextHandler.java
@@ -0,0 +1,88 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleContext;
+import tools.NameProvider;
+
+class AccessibleContextHandler
+ extends NodeHandler
+{
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ if (xContext != null)
+ return new AccessibleContextHandler (xContext);
+ else
+ return null;
+ }
+
+ public AccessibleContextHandler ()
+ {
+ super ();
+ }
+
+ private AccessibleContextHandler (XAccessibleContext xContext)
+ {
+ super();
+ if (xContext != null)
+ maChildList.setSize (4);
+ }
+
+ @Override
+ public AccessibleTreeNode createChild (AccessibleTreeNode aParent, int nIndex)
+ {
+ XAccessibleContext xContext = null;
+ if (aParent instanceof AccTreeNode)
+ xContext = ((AccTreeNode)aParent).getContext();
+
+ String sChild = "";
+ if (xContext != null)
+ {
+ switch( nIndex )
+ {
+ case 0:
+ sChild = "Description: " +
+ xContext.getAccessibleDescription();
+ break;
+ case 1:
+ int nRole = xContext.getAccessibleRole();
+ sChild = "Role: " + nRole + " (" + NameProvider.getRoleName(nRole) + ")";
+ break;
+ case 2:
+ XAccessible xParent = xContext.getAccessibleParent();
+ sChild = "Has parent: " + (xParent!=null ? "yes" : "no");
+ break;
+ case 3:
+ sChild = "";
+ long xStateSet = xContext.getAccessibleStateSet();
+ for (short i=0; i<=30; i++)
+ {
+ if ((xStateSet & (1<<i)) != 0)
+ {
+ if (sChild.compareTo ("") != 0)
+ sChild += ", ";
+ sChild += NameProvider.getStateName(1<<i);
+ }
+ }
+ sChild = "State set: " + sChild;
+ }
+ }
+ return new StringNode (sChild, aParent);
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleEditableTextHandler.java b/toolkit/test/accessibility/AccessibleEditableTextHandler.java
new file mode 100644
index 0000000000..ae5df14618
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleEditableTextHandler.java
@@ -0,0 +1,53 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleEditableText;
+
+
+class AccessibleEditableTextHandler extends NodeHandler
+{
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ XAccessibleEditableText xText =
+ UnoRuntime.queryInterface (
+ XAccessibleEditableText.class, xContext);
+ if (xText != null)
+ return new AccessibleEditableTextHandler (xText);
+ else
+ return null;
+ }
+
+ public AccessibleEditableTextHandler ()
+ {
+ }
+
+ private AccessibleEditableTextHandler (XAccessibleEditableText xText)
+ {
+ if (xText != null)
+ maChildList.setSize (1);
+ }
+
+ @Override
+ public AccessibleTreeNode createChild (AccessibleTreeNode aParent, int nIndex)
+ {
+ return new StringNode ("XAccessibleEditableText is supported", aParent);
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleExtendedComponentHandler.java b/toolkit/test/accessibility/AccessibleExtendedComponentHandler.java
new file mode 100644
index 0000000000..f34ed1b5fc
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleExtendedComponentHandler.java
@@ -0,0 +1,93 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleExtendedComponent;
+
+
+class AccessibleExtendedComponentHandler
+ extends NodeHandler
+{
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ XAccessibleExtendedComponent xEComponent =
+ UnoRuntime.queryInterface (
+ XAccessibleExtendedComponent.class, xContext);
+ if (xEComponent != null)
+ return new AccessibleExtendedComponentHandler (xEComponent);
+ else
+ return null;
+ }
+
+ public AccessibleExtendedComponentHandler ()
+ {
+ }
+
+ private AccessibleExtendedComponentHandler (XAccessibleExtendedComponent xEComponent)
+ {
+ if (xEComponent != null)
+ maChildList.setSize (0);
+ }
+
+ private static XAccessibleExtendedComponent getComponent (AccTreeNode aNode)
+ {
+ return UnoRuntime.queryInterface (
+ XAccessibleExtendedComponent.class,
+ aNode.getContext());
+ }
+
+
+ @Override
+ public AccessibleTreeNode createChild (AccessibleTreeNode aParent, int nIndex)
+ {
+ AccessibleTreeNode aChild = null;
+ if (aParent instanceof AccTreeNode)
+ {
+ XAccessibleExtendedComponent xEComponent = getComponent ((AccTreeNode)aParent);
+
+ if (xEComponent != null)
+ {
+ int nColor;
+ switch( nIndex )
+ {
+ case 0:
+ nColor = xEComponent.getForeground();
+ aChild = new StringNode ("Deprecated Foreground color: R"
+ + (nColor>>16&0xff)
+ + "G" + (nColor>>8&0xff)
+ + "B" + (nColor&0xff)
+ + "A" + (nColor>>24&0xff),
+ aParent);
+ break;
+ case 1:
+ nColor = xEComponent.getBackground();
+ aChild = new StringNode ("Deprecated Background color: R"
+ + (nColor>>16&0xff)
+ + "G" + (nColor>>8&0xff)
+ + "B" + (nColor&0xff)
+ + "A" + (nColor>>24&0xff),
+ aParent);
+ break;
+ }
+ }
+ }
+ return aChild;
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleHyperlinkHandler.java b/toolkit/test/accessibility/AccessibleHyperlinkHandler.java
new file mode 100644
index 0000000000..41a161ac5a
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleHyperlinkHandler.java
@@ -0,0 +1,53 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleHyperlink;
+
+
+class AccessibleHyperlinkHandler extends AccessibleTreeHandler
+{
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ XAccessibleHyperlink xLink =
+ UnoRuntime.queryInterface (
+ XAccessibleHyperlink.class, xContext);
+ if (xLink != null)
+ return new AccessibleHyperlinkHandler (xLink);
+ else
+ return null;
+ }
+
+ public AccessibleHyperlinkHandler ()
+ {
+ }
+
+ private AccessibleHyperlinkHandler (XAccessibleHyperlink xLink)
+ {
+ if (xLink != null)
+ maChildList.setSize (1);
+ }
+
+ @Override
+ public AccessibleTreeNode getChild (AccessibleTreeNode aParent, int nIndex)
+ {
+ return new StringNode ("interface XAccessibleHyperlink is supported", aParent);
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleHypertextHandler.java b/toolkit/test/accessibility/AccessibleHypertextHandler.java
new file mode 100644
index 0000000000..603d68997d
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleHypertextHandler.java
@@ -0,0 +1,53 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleHypertext;
+
+
+class AccessibleHypertextHandler extends AccessibleTreeHandler
+{
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ XAccessibleHypertext xText =
+ UnoRuntime.queryInterface (
+ XAccessibleHypertext.class, xContext);
+ if (xText != null)
+ return new AccessibleHypertextHandler (xText);
+ else
+ return null;
+ }
+
+ public AccessibleHypertextHandler ()
+ {
+ }
+
+ private AccessibleHypertextHandler (XAccessibleHypertext xText)
+ {
+ if (xText != null)
+ maChildList.setSize (1);
+ }
+
+ @Override
+ public AccessibleTreeNode getChild (AccessibleTreeNode aParent, int nIndex)
+ {
+ return new StringNode ("interface XAccessibleHypertext is supported", aParent);
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleImageHandler.java b/toolkit/test/accessibility/AccessibleImageHandler.java
new file mode 100644
index 0000000000..a02077b7d2
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleImageHandler.java
@@ -0,0 +1,70 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleImage;
+
+
+class AccessibleImageHandler extends NodeHandler
+{
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ XAccessibleImage xImage =
+ UnoRuntime.queryInterface (
+ XAccessibleImage.class, xContext);
+ if (xImage != null)
+ return new AccessibleImageHandler (xImage);
+ else
+ return null;
+ }
+
+ public AccessibleImageHandler ()
+ {
+ }
+
+ private AccessibleImageHandler (XAccessibleImage xImage)
+ {
+ if (xImage != null)
+ maChildList.setSize (1);
+ }
+
+ private static XAccessibleImage getImage (AccTreeNode aNode)
+ {
+ return UnoRuntime.queryInterface (
+ XAccessibleImage.class, aNode.getContext());
+ }
+
+ @Override
+ public AccessibleTreeNode createChild (AccessibleTreeNode aParent, int nIndex)
+ {
+ if (aParent instanceof AccTreeNode)
+ {
+ XAccessibleImage xImage = getImage ((AccTreeNode)aParent);
+ if (xImage != null)
+ return new StringNode (
+ "Image: " +
+ xImage.getAccessibleImageDescription() + " (" +
+ xImage.getAccessibleImageWidth() + "x" +
+ xImage.getAccessibleImageHeight() + ")",
+ aParent);
+ }
+ return null;
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleRelationHandler.java b/toolkit/test/accessibility/AccessibleRelationHandler.java
new file mode 100644
index 0000000000..1f7eebada2
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleRelationHandler.java
@@ -0,0 +1,115 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.AccessibleRelation;
+import com.sun.star.accessibility.XAccessibleRelationSet;
+import com.sun.star.lang.IndexOutOfBoundsException;
+
+import tools.NameProvider;
+
+class AccessibleRelationHandler
+ extends NodeHandler
+{
+ @Override
+ public NodeHandler createHandler( XAccessibleContext xContext )
+ {
+ AccessibleRelationHandler aHandler = null;
+ if (xContext != null)
+ {
+ XAccessibleRelationSet xRelation = xContext.getAccessibleRelationSet();
+ if (xRelation != null)
+ aHandler = new AccessibleRelationHandler(xContext);
+ }
+ return aHandler;
+ }
+
+ public AccessibleRelationHandler()
+ {
+ }
+
+ private AccessibleRelationHandler( XAccessibleContext xContext )
+ {
+ XAccessibleRelationSet xRelation = xContext.getAccessibleRelationSet();
+ if (xRelation != null)
+ maChildList.setSize( 1 );
+ }
+
+ @Override
+ public AccessibleTreeNode createChild( AccessibleTreeNode aParent,
+ int nIndex )
+ {
+ XAccessibleRelationSet xRelation = null;
+ AccessibleTreeNode aChild = null;
+
+ if( aParent instanceof AccTreeNode )
+ {
+ xRelation =
+ ((AccTreeNode)aParent).getContext().getAccessibleRelationSet();
+ }
+ if( xRelation == null )
+ return aChild;
+
+
+ VectorNode aVNode = new VectorNode( "RelationSet", aParent);
+ int nCount = xRelation.getRelationCount();
+ try
+ {
+ for( int i = 0; i < nCount; i++ )
+ {
+ AccessibleRelation aRelation = xRelation.getRelation( i );
+
+ StringBuffer aBuffer = new StringBuffer();
+ aBuffer.append (NameProvider.getRelationName (aRelation.RelationType));
+ aBuffer.append( ": " );
+
+ for( int j = 0; j < aRelation.TargetSet.length; j++ )
+ {
+ Object aTarget = aRelation.TargetSet[j];
+ XAccessible xAccTarget =
+ UnoRuntime.queryInterface(
+ XAccessible.class, aTarget );
+ if( xAccTarget == null )
+ {
+ aBuffer.append( aTarget.toString() );
+ }
+ else
+ {
+ aBuffer.append( xAccTarget.getAccessibleContext().
+ getAccessibleName() );
+ }
+ aBuffer.append( ", " );
+ }
+ aBuffer.delete( aBuffer.length() - 2, aBuffer.length() );
+
+ aVNode.addChild( new StringNode( aBuffer.toString(),
+ aParent ) );
+ }
+
+ aChild = aVNode;
+ }
+ catch( IndexOutOfBoundsException e )
+ {
+ aChild = new StringNode( "IndexOutOfBounds", aParent );
+ }
+
+ return aChild;
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleSelectionHandler.java b/toolkit/test/accessibility/AccessibleSelectionHandler.java
new file mode 100644
index 0000000000..41eae0d980
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleSelectionHandler.java
@@ -0,0 +1,145 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleSelection;
+import com.sun.star.lang.IndexOutOfBoundsException;
+
+
+
+class AccessibleSelectionHandler
+ extends NodeHandler
+{
+ @Override
+ public NodeHandler createHandler( XAccessibleContext xContext )
+ {
+ XAccessibleSelection xSelection =
+ UnoRuntime.queryInterface(
+ XAccessibleSelection.class, xContext);
+ return (xSelection == null) ? null :
+ new AccessibleSelectionHandler(xSelection);
+ }
+
+ public AccessibleSelectionHandler()
+ {
+ }
+
+ private AccessibleSelectionHandler( XAccessibleSelection xSelection )
+ {
+ if (xSelection != null)
+ maChildList.setSize( 2 );
+ }
+
+ @Override
+ public AccessibleTreeNode createChild( AccessibleTreeNode aParent,
+ int nIndex )
+ {
+ if( !(aParent instanceof AccTreeNode) )
+ return null;
+
+ XAccessibleSelection xSelection = ((AccTreeNode)aParent).getSelection();
+ if( xSelection == null )
+ return null;
+
+ AccessibleTreeNode aChild = null;
+
+ switch( nIndex )
+ {
+ case 0:
+ aChild = new StringNode(
+ "getSelectedAccessibleChildCount: " +
+ xSelection.getSelectedAccessibleChildCount(),
+ aParent );
+ break;
+ case 1:
+ {
+ VectorNode aVNode =
+ new VectorNode( "Selected Children", aParent);
+ long nSelected = 0;
+ long nCount = ((AccTreeNode)aParent).getContext().
+ getAccessibleChildCount();
+ try
+ {
+ for( long i = 0; i < nCount; i++ )
+ {
+ try
+ {
+ if( xSelection.isAccessibleChildSelected( i ) )
+ {
+ XAccessible xSelChild = xSelection.
+ getSelectedAccessibleChild(nSelected);
+ XAccessible xNChild =
+ ((AccTreeNode)aParent).
+ getContext().getAccessibleChild( i );
+ aVNode.addChild( new StringNode(
+ i + ": " +
+ xNChild.getAccessibleContext().
+ getAccessibleDescription() + " (" +
+ (xSelChild.equals(xNChild) ? "OK" : "XXX") +
+ ")", aParent ) );
+ }
+ }
+ catch (com.sun.star.lang.DisposedException e)
+ {
+ aVNode.addChild( new StringNode(
+ i + ": caught DisposedException while creating",
+ aParent ));
+ }
+ }
+ aChild = aVNode;
+ }
+ catch( IndexOutOfBoundsException e )
+ {
+ aChild = new StringNode( "IndexOutOfBounds",
+ aParent );
+ }
+ }
+ break;
+ default:
+ aChild = new StringNode( "ERROR", aParent );
+ break;
+ }
+
+ return aChild;
+ }
+
+
+ @Override
+ public String[] getActions (AccessibleTreeNode aNode)
+ {
+ if( aNode instanceof AccTreeNode )
+ {
+ XAccessibleSelection xSelection =
+ ((AccTreeNode)aNode).getSelection();
+ if( xSelection != null )
+ {
+ return new String[] { "Select..." };
+ }
+ }
+ return new String[0];
+ }
+
+ @Override
+ public void performAction (AccessibleTreeNode aNode, int nIndex)
+ {
+ SelectionDialog selectionDialog = new SelectionDialog( (AccTreeNode)aNode );
+ selectionDialog.setVisible(true);
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleTableHandler.java b/toolkit/test/accessibility/AccessibleTableHandler.java
new file mode 100644
index 0000000000..a72fe61a35
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleTableHandler.java
@@ -0,0 +1,103 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleTable;
+
+
+class AccessibleTableHandler extends NodeHandler
+{
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ XAccessibleTable xTable =
+ UnoRuntime.queryInterface (
+ XAccessibleTable.class, xContext);
+ if (xTable != null)
+ return new AccessibleTableHandler (xTable);
+ else
+ return null;
+ }
+
+ public AccessibleTableHandler ()
+ {
+ }
+
+ private AccessibleTableHandler (XAccessibleTable xTable)
+ {
+ if (xTable != null)
+ maChildList.setSize (4);
+ }
+
+ @Override
+ public AccessibleTreeNode createChild (AccessibleTreeNode aParent, int nIndex)
+ {
+ AccessibleTreeNode aChild = null;
+ XAccessibleTable xTable = null;
+ if (aParent instanceof AccTreeNode)
+ xTable = ((AccTreeNode)aParent).getTable();
+ try
+ {
+ if( xTable != null )
+ {
+ switch( nIndex )
+ {
+ case 0:
+ aChild = new StringNode ("# table rows: " + xTable.getAccessibleRowCount(), aParent);
+ break;
+ case 1:
+ aChild = new StringNode ("# table columns: " + xTable.getAccessibleColumnCount(), aParent);
+ break;
+ case 2:
+ {
+ String sText = "selected rows: ";
+ int[] aSelected = xTable.getSelectedAccessibleRows();
+ for( int i=0; i < aSelected.length; i++ )
+ {
+ sText += aSelected[i];
+ sText += " ";
+ }
+ aChild = new StringNode (sText, aParent);
+ }
+ break;
+ case 3:
+ {
+ String sText = "selected columns: ";
+ int[] aSelected = xTable.getSelectedAccessibleColumns();
+ for( int i=0; i < aSelected.length; i++ )
+ {
+ sText += aSelected[i];
+ sText += " ";
+ }
+ aChild = new StringNode (sText, aParent);
+ }
+ break;
+ default:
+ aChild = new StringNode ("unknown child index " + nIndex, aParent);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ // Return empty child.
+ }
+
+ return aChild;
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleTextHandler.java b/toolkit/test/accessibility/AccessibleTextHandler.java
new file mode 100644
index 0000000000..714bcb5910
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleTextHandler.java
@@ -0,0 +1,821 @@
+/*
+ * 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 .
+ */
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.FlowLayout;
+import java.awt.Graphics;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.BoxLayout;
+import javax.swing.Icon;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JColorChooser;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.text.JTextComponent;
+
+import com.sun.star.accessibility.AccessibleTextType;
+import com.sun.star.accessibility.TextSegment;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleEditableText;
+import com.sun.star.accessibility.XAccessibleText;
+import com.sun.star.awt.Point;
+import com.sun.star.awt.Rectangle;
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.beans.UnknownPropertyException;
+import com.sun.star.lang.IndexOutOfBoundsException;
+import com.sun.star.uno.UnoRuntime;
+
+
+class AccessibleTextHandler extends NodeHandler
+{
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ XAccessibleText xText = UnoRuntime.queryInterface (
+ XAccessibleText.class, xContext);
+ if (xText != null)
+ return new AccessibleTextHandler (xText);
+ else
+ return null;
+ }
+
+ public AccessibleTextHandler ()
+ {
+ }
+
+ private AccessibleTextHandler (XAccessibleText xText)
+ {
+ if (xText != null)
+ maChildList.setSize (8);
+ }
+
+ @Override
+ public AccessibleTreeNode createChild (AccessibleTreeNode aParent, int nIndex)
+ {
+ AccessibleTreeNode aChild = null;
+ XAccessibleText xText = null;
+ if (aParent instanceof AccTreeNode)
+ xText = ((AccTreeNode)aParent).getText();
+
+ try
+ {
+ if( xText != null )
+ {
+ switch( nIndex )
+ {
+ case 0:
+ aChild = new StringNode (xText.getText(), aParent);
+ break;
+ case 1:
+ aChild = new StringNode ("# chars: " + xText.getCharacterCount(), aParent);
+ break;
+ case 2:
+ aChild = new StringNode (characters( xText ), aParent);
+ break;
+ case 3:
+ aChild = new StringNode ("selection: "
+ + "[" + xText.getSelectionStart()
+ + "," + xText.getSelectionEnd()
+ + "] \"" + xText.getSelectedText() + "\"",
+ aParent);
+ break;
+ case 4:
+ aChild = new StringNode ("getCaretPosition: " + xText.getCaretPosition(), aParent);
+ break;
+ case 5:
+ {
+ VectorNode aVec = new VectorNode("portions", aParent);
+ aChild = aVec;
+ aVec.addChild(
+ textAtIndexNode( xText, "Character",
+ AccessibleTextType.CHARACTER,
+ aParent ) );
+ aVec.addChild(
+ textAtIndexNode( xText, "Word",
+ AccessibleTextType.WORD,
+ aParent ) );
+ aVec.addChild(
+ textAtIndexNode( xText, "Sentence",
+ AccessibleTextType.SENTENCE,
+ aParent ) );
+ aVec.addChild(
+ textAtIndexNode( xText, "Paragraph",
+ AccessibleTextType.PARAGRAPH,
+ aParent ) );
+ aVec.addChild(
+ textAtIndexNode( xText, "Line",
+ AccessibleTextType.LINE,
+ aParent ) );
+ aVec.addChild(
+ textAtIndexNode( xText, "Attribute",
+ AccessibleTextType.ATTRIBUTE_RUN,
+ aParent ) );
+ aVec.addChild(
+ textAtIndexNode( xText, "Glyph",
+ AccessibleTextType.GLYPH,
+ aParent ) );
+ }
+ break;
+ case 6:
+ aChild = new StringNode (bounds( xText ), aParent);
+ break;
+ case 7:
+ aChild = getAttributes( xText, aParent );
+ break;
+ default:
+ aChild = new StringNode ("unknown child index " + nIndex, aParent);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ // Return empty child.
+ }
+
+ return aChild;
+ }
+
+
+ private String textAtIndexNodeString(
+ int nStart, int nEnd,
+ String sWord, String sBefore, String sBehind)
+ {
+ return "[" + nStart + "," + nEnd + "] "
+ + "\"" + sWord + "\" \t"
+ + "(" + sBefore + "," + sBehind + ")";
+ }
+
+ /** Create a text node that lists all strings of a particular text type
+ */
+ private AccessibleTreeNode textAtIndexNode(
+ XAccessibleText xText,
+ String sName,
+ short nTextType,
+ AccessibleTreeNode aParent)
+ {
+ VectorNode aNode = new VectorNode (sName, aParent);
+
+ // get word at all positions;
+ // for nicer display, compare current word to previous one and
+ // make a new node for every interval, not for every word
+ int nLength = xText.getCharacterCount();
+ if( nLength > 0 )
+ {
+ try
+ {
+ // sWord + nStart mark the current word
+ // make a node as soon as a new one is found; close the last
+ // one at the end
+ TextSegment sWord = xText.getTextAtIndex(0, nTextType);
+ TextSegment sBefore = xText.getTextBeforeIndex(0, nTextType);
+ TextSegment sBehind = xText.getTextBehindIndex(0, nTextType);
+ int nStart = 0;
+ for(int i = 1; i < nLength; i++)
+ {
+ TextSegment sTmp = xText.getTextAtIndex(i, nTextType);
+ TextSegment sTBef = xText.getTextBeforeIndex(i, nTextType);
+ TextSegment sTBeh = xText.getTextBehindIndex(i, nTextType);
+ if( ! ( sTmp.equals( sWord ) && sTBef.equals( sBefore ) &&
+ sTBeh.equals( sBehind ) ) )
+ {
+ aNode.addChild (new StringNode (textAtIndexNodeString(
+ nStart, i,
+ sWord.SegmentText, sBefore.SegmentText, sBehind.SegmentText), aNode));
+ sWord = sTmp;
+ sBefore = sTBef;
+ sBehind = sTBeh;
+ nStart = i;
+ }
+
+ // don't generate more than 50 children.
+ if (aNode.getChildCount() > 50)
+ {
+ sWord.SegmentText = "...";
+ break;
+ }
+ }
+ aNode.addChild (new StringNode (textAtIndexNodeString(
+ nStart, nLength,
+ sWord.SegmentText, sBefore.SegmentText, sBehind.SegmentText), aNode));
+ }
+ catch( IndexOutOfBoundsException e )
+ {
+ aNode.addChild (new StringNode (e.toString(), aNode));
+ }
+ catch (com.sun.star.lang.IllegalArgumentException e)
+ {
+ aNode.addChild (new StringNode (e.toString(), aNode));
+ }
+ }
+
+ return aNode;
+ }
+
+
+
+ /** getCharacter (display as array string) */
+ private String characters(XAccessibleText xText)
+ {
+ // get count (max. 30)
+ int nChars = xText.getCharacterCount();
+ if( nChars > 30 )
+ nChars = 30;
+
+ // build up string
+ StringBuffer aChars = new StringBuffer();
+ try
+ {
+ aChars.append( '[' );
+ for( int i = 0; i < nChars; i++)
+ {
+ aChars.append( xText.getCharacter(i) );
+ aChars.append( ',' );
+ }
+ if( nChars > 0)
+ {
+ if( nChars == xText.getCharacterCount() )
+ aChars.deleteCharAt( aChars.length() - 1 );
+ else
+ aChars.append( "..." );
+ }
+ aChars.append( ']' );
+ }
+ catch( IndexOutOfBoundsException e )
+ {
+ aChars.append( " ERROR " );
+ }
+
+ // return result
+ return "getCharacters: " + aChars;
+ }
+
+
+ /** iterate over characters, and translate their positions
+ * back and forth */
+ private String bounds( XAccessibleText xText )
+ {
+ StringBuffer aBuffer = new StringBuffer( "bounds: " );
+ try
+ {
+ // iterate over characters
+ int nCount = xText.getCharacterCount();
+ for(int i = 0; i < nCount; i++ )
+ {
+ // get bounds for this character
+ Rectangle aRect = xText.getCharacterBounds( i );
+
+ // get the character by 'clicking' into the middle of
+ // the bounds
+ Point aMiddle = new Point();
+ aMiddle.X = aRect.X + (aRect.Width / 2) - 1;
+ aMiddle.Y = aRect.Y + (aRect.Height / 2 ) - 1;
+ int nIndex = xText.getIndexAtPoint( aMiddle );
+
+ // get the character, or a '#' for an illegal index
+ if( (nIndex >= 0) && (nIndex < xText.getCharacter(i)) )
+ aBuffer.append( xText.getCharacter(nIndex) );
+ else
+ aBuffer.append( '#' );
+ }
+ }
+ catch( IndexOutOfBoundsException e )
+ { } // ignore errors
+
+ return aBuffer.toString();
+ }
+
+
+ private AccessibleTreeNode getAttributes( XAccessibleText xText,
+ AccessibleTreeNode aParent)
+ {
+ String[] aAttributeList = new String[] {
+ "CharBackColor",
+ "CharColor",
+ "CharEscapement",
+ "CharHeight",
+ "CharPosture",
+ "CharStrikeout",
+ "CharUnderline",
+ "CharWeight",
+ "ParaAdjust",
+ "ParaBottomMargin",
+ "ParaFirstLineIndent",
+ "ParaLeftMargin",
+ "ParaLineSpacing",
+ "ParaRightMargin",
+ "ParaTabStops"};
+
+ AccessibleTreeNode aRet;
+
+ try
+ {
+ VectorNode aPortions = new VectorNode ("getAttributes", aParent);
+
+ int nIndex = 0;
+ int nLength = xText.getCharacterCount();
+ while( nIndex < nLength )
+ {
+ // get attribute run
+ String aPortion = null;
+ try
+ {
+ aPortion = xText.getTextAtIndex(
+ nIndex, AccessibleTextType.ATTRIBUTE_RUN).SegmentText;
+ }
+ catch(com.sun.star.lang.IllegalArgumentException e)
+ {
+ aPortion = "";
+ }
+
+ // get attributes and make node with attribute children
+ PropertyValue[] aValues = xText.getCharacterAttributes(nIndex, aAttributeList);
+ VectorNode aAttrs = new VectorNode (aPortion, aPortions);
+ for( int i = 0; i < aValues.length; i++ )
+ {
+ new StringNode( aValues[i].Name + ": " + aValues[i].Value,
+ aAttrs );
+ }
+
+ // get next portion, but advance at least one
+ nIndex += (aPortion.length() > 0) ? aPortion.length() : 1;
+ }
+
+ aRet = aPortions;
+ }
+ catch( UnknownPropertyException e )
+ {
+ aRet = new StringNode( "Exception caught:" + e, aParent );
+ }
+ catch( IndexOutOfBoundsException e )
+ {
+ aRet = new StringNode( "Exception caught:" + e, aParent );
+ }
+
+ return aRet;
+ }
+
+
+ private static String[] aTextActions =
+ new String[] { "select...", "copy..." };
+ private static String[] aEditableTextActions =
+ new String[] { "select...", "copy...",
+ "cut...", "paste...", "edit...", "format..." };
+
+ @Override
+ public String[] getActions (AccessibleTreeNode aNode)
+ {
+ XAccessibleEditableText xEText = null;
+ if (aNode instanceof AccTreeNode)
+ xEText = ((AccTreeNode)aNode).getEditText ();
+
+ return (xEText == null) ? aTextActions : aEditableTextActions;
+ }
+
+ @Override
+ public void performAction (AccessibleTreeNode aNode, int nIndex)
+ {
+ if ( ! (aNode instanceof AccTreeNode))
+ return;
+
+ AccTreeNode aATNode = (AccTreeNode)aNode;
+ TextActionDialog aDialog = null;
+
+ // create proper dialog
+ switch( nIndex )
+ {
+ case 0:
+ aDialog = new TextActionDialog( aATNode,
+ "Select range:",
+ "select" )
+ {
+ @Override
+ boolean action(
+ JTextComponent aText, AccTreeNode aNode )
+ throws IndexOutOfBoundsException
+ {
+ return aNode.getText().setSelection(
+ getSelectionStart(),
+ getSelectionEnd() );
+ }
+ };
+ break;
+ case 1:
+ aDialog = new TextActionDialog( aATNode,
+ "Select range and copy:",
+ "copy" )
+ {
+ @Override
+ boolean action(
+ JTextComponent aText, AccTreeNode aNode )
+ throws IndexOutOfBoundsException
+ {
+ return aNode.getText().copyText(
+ getSelectionStart(),
+ getSelectionEnd() );
+ }
+ };
+ break;
+ case 2:
+ aDialog = new TextActionDialog( aATNode,
+ "Select range and cut:",
+ "cut" )
+ {
+ @Override
+ boolean action(
+ JTextComponent aText, AccTreeNode aNode )
+ throws IndexOutOfBoundsException
+ {
+ return aNode.getEditText().cutText(
+ getSelectionStart(),
+ getSelectionEnd() );
+ }
+ };
+ break;
+ case 3:
+ aDialog = new TextActionDialog( aATNode,
+ "Place Caret and paste:",
+ "paste" )
+ {
+ @Override
+ boolean action(
+ JTextComponent aText, AccTreeNode aNode )
+ throws IndexOutOfBoundsException
+ {
+ return aNode.getEditText().pasteText(
+ aText.getCaretPosition() );
+ }
+ };
+ break;
+ case 4:
+ aDialog = new TextEditDialog( aATNode, "Edit text:",
+ "edit" );
+ break;
+ case 5:
+ aDialog = new TextAttributeDialog( aATNode );
+ break;
+ }
+
+ if( aDialog != null )
+ aDialog.setVisible(true);
+ }
+
+}
+
+/**
+ * Display a dialog with a text field and a pair of cancel/do-it buttons
+ */
+abstract class TextActionDialog extends JDialog
+ implements ActionListener
+{
+ private AccTreeNode aNode;
+ JTextArea aText;
+ private String sName;
+ private JCheckBox aIndexToggle;
+
+ public TextActionDialog( AccTreeNode aNd,
+ String sExplanation,
+ String sButtonText )
+ {
+ super( AccessibilityWorkBench.Instance() );
+
+ aNode = aNd;
+ sName = sButtonText;
+ init( sExplanation, aNode.getText().getText(), sButtonText );
+ setSize( 350, 225 );
+ }
+
+ /** build dialog */
+ protected void init( String sExplanation,
+ String sText,
+ String sButtonText )
+ {
+ setTitle( sName );
+
+ // vertical stacking of the elements
+ Container aContent = getContentPane();
+
+ // label with explanation
+ if( sExplanation.length() > 0 )
+ aContent.add( new JLabel( sExplanation ), BorderLayout.NORTH );
+
+ // the text field
+ aText = new JTextArea();
+ aText.setText( sText );
+ aText.setColumns( Math.min( Math.max( 40, sText.length() ), 20 ) );
+ aText.setRows( sText.length() / 40 + 1 );
+ aText.setLineWrap( true );
+ aText.setEditable( false );
+ aContent.add( aText, BorderLayout.CENTER );
+
+ JPanel aButtons = new JPanel();
+ aButtons.setLayout( new FlowLayout() );
+ aIndexToggle = new JCheckBox( "reverse selection" );
+ aButtons.add( aIndexToggle );
+ JButton aActionButton = new JButton( sButtonText );
+ aActionButton.setActionCommand( "Action" );
+ aActionButton.addActionListener( this );
+ aButtons.add( aActionButton );
+ JButton aCancelButton = new JButton( "cancel" );
+ aCancelButton.setActionCommand( "Cancel" );
+ aCancelButton.addActionListener( this );
+ aButtons.add( aCancelButton );
+
+ // add Panel with buttons
+ aContent.add( aButtons, BorderLayout.SOUTH );
+ }
+
+ private void cancel()
+ {
+ setVisible(false);
+ dispose();
+ }
+
+ private void action()
+ {
+ String sError = null;
+ try
+ {
+ boolean bSuccess = action( aText, aNode );
+ if( !bSuccess )
+ sError = "Can't execute";
+ }
+ catch( IndexOutOfBoundsException e )
+ {
+ sError = "Index out of bounds";
+ }
+
+ if( sError != null )
+ JOptionPane.showMessageDialog( AccessibilityWorkBench.Instance(),
+ sError, sName,
+ JOptionPane.ERROR_MESSAGE);
+
+ cancel();
+ }
+
+ public void actionPerformed(ActionEvent e)
+ {
+ String sCommand = e.getActionCommand();
+
+ if( "Cancel".equals( sCommand ) )
+ cancel();
+ else if( "Action".equals( sCommand ) )
+ action();
+ }
+
+
+ int getSelectionStart() { return getSelection(true); }
+ int getSelectionEnd() { return getSelection(false); }
+ private int getSelection(boolean bStart)
+ {
+ return ( bStart ^ aIndexToggle.isSelected() )
+ ? aText.getSelectionStart() : aText.getSelectionEnd();
+ }
+
+
+
+ /** override this for dialog-specific action */
+ abstract boolean action( JTextComponent aText, AccTreeNode aNode )
+ throws IndexOutOfBoundsException;
+}
+
+
+class TextEditDialog extends TextActionDialog
+{
+ public TextEditDialog( AccTreeNode aNode,
+ String sExplanation,
+ String sButtonText )
+ {
+ super( aNode, sExplanation, sButtonText );
+ }
+
+ @Override
+ protected void init( String sExplanation,
+ String sText,
+ String sButtonText )
+ {
+ super.init( sExplanation, sText, sButtonText );
+ aText.setEditable( true );
+ }
+
+
+ /** edit the text */
+ @Override
+ boolean action( JTextComponent aText, AccTreeNode aNode )
+ {
+ // is this text editable? if not, fudge you and return
+ XAccessibleEditableText xEdit = aNode.getEditText();
+ return ( xEdit == null ) ? false :
+ updateText( xEdit, aText.getText() );
+ }
+
+
+ /** update the text */
+ private boolean updateText( XAccessibleEditableText xEdit, String sNew )
+ {
+ String sOld = xEdit.getText();
+
+ // false alarm? Early out if no change was done!
+ if( sOld.equals( sNew ) )
+ return false;
+
+ // get the minimum length of both strings
+ int nMinLength = sOld.length();
+ if( sNew.length() < nMinLength )
+ nMinLength = sNew.length();
+
+ // count equal characters from front and end
+ int nFront = 0;
+ while( (nFront < nMinLength) &&
+ (sNew.charAt(nFront) == sOld.charAt(nFront)) ) {
+ nFront++;
+ }
+ int nBack = 0;
+ while( (nBack < nMinLength) &&
+ ( sNew.charAt(sNew.length()-nBack-1) ==
+ sOld.charAt(sOld.length()-nBack-1) ) ) {
+ nBack++;
+ }
+ if( nFront + nBack > nMinLength )
+ nBack = nMinLength - nFront;
+
+ // so... the first nFront and the last nBack characters
+ // are the same. Change the others!
+ String sDel = sOld.substring( nFront, sOld.length() - nBack );
+ String sIns = sNew.substring( nFront, sNew.length() - nBack );
+
+ System.out.println("edit text: " +
+ sOld.substring(0, nFront) +
+ " [ " + sDel + " -> " + sIns + " ] " +
+ sOld.substring(sOld.length() - nBack) );
+
+ boolean bRet = false;
+ try
+ {
+ // edit the text, and use
+ // (set|insert|delete|replace)Text as needed
+ if( nFront+nBack == 0 )
+ bRet = xEdit.setText( sIns );
+ else if( sDel.length() == 0 )
+ bRet = xEdit.insertText( sIns, nFront );
+ else if( sIns.length() == 0 )
+ bRet = xEdit.deleteText( nFront, sOld.length()-nBack );
+ else
+ bRet = xEdit.replaceText(nFront, sOld.length()-nBack,sIns);
+ }
+ catch( IndexOutOfBoundsException e )
+ {
+ bRet = false;
+ }
+
+ return bRet;
+ }
+}
+
+
+class TextAttributeDialog extends TextActionDialog
+{
+ public TextAttributeDialog(
+ AccTreeNode aNode )
+ {
+ super( aNode, "Choose attributes, select text, and press 'Set':",
+ "set" );
+ }
+
+ private JCheckBox aBold, aUnderline, aItalics;
+ private Color aForeground, aBackground;
+
+ @Override
+ protected void init( String sExplanation,
+ String sText,
+ String sButtonText )
+ {
+ super.init( sExplanation, sText, sButtonText );
+
+ aForeground = Color.black;
+ aBackground = Color.white;
+
+ JPanel aAttr = new JPanel();
+ aAttr.setLayout( new BoxLayout( aAttr, BoxLayout.Y_AXIS ) );
+
+ aBold = new JCheckBox( "bold" );
+ aUnderline = new JCheckBox( "underline" );
+ aItalics = new JCheckBox( "italics" );
+
+ JButton aForeButton = new JButton("Foreground", new ColorIcon(true));
+ aForeButton.addActionListener( new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ aForeground = JColorChooser.showDialog(
+ TextAttributeDialog.this,
+ "Select Foreground Color",
+ aForeground);
+ }
+ } );
+
+ JButton aBackButton = new JButton("Background", new ColorIcon(false));
+ aBackButton.addActionListener( new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ aBackground = JColorChooser.showDialog(
+ TextAttributeDialog.this,
+ "Select Background Color",
+ aBackground);
+ }
+ } );
+
+ aAttr.add( aBold );
+ aAttr.add( aUnderline );
+ aAttr.add( aItalics );
+ aAttr.add( aForeButton );
+ aAttr.add( aBackButton );
+
+ getContentPane().add( aAttr, BorderLayout.WEST );
+ }
+
+
+ private class ColorIcon implements Icon
+ {
+ private boolean bForeground;
+ private static final int nHeight = 16;
+ private static final int nWidth = 16;
+
+ public ColorIcon(boolean bWhich) { bForeground = bWhich; }
+ public int getIconHeight() { return nHeight; }
+ public int getIconWidth() { return nWidth; }
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ g.setColor( getColor() );
+ g.fillRect( x, y, nHeight, nWidth );
+ g.setColor( c.getForeground() );
+ g.drawRect( x, y, nHeight, nWidth );
+ }
+ Color getColor()
+ {
+ return bForeground ? aForeground : aBackground;
+ }
+ }
+
+
+
+ /** edit the text */
+ @Override
+ boolean action( JTextComponent aText, AccTreeNode aNode )
+ throws IndexOutOfBoundsException
+ {
+ // is this text editable? if not, fudge you and return
+ XAccessibleEditableText xEdit = aNode.getEditText();
+ boolean bSuccess = false;
+ if( xEdit != null )
+ {
+ PropertyValue[] aSequence = new PropertyValue[6];
+ aSequence[0] = new PropertyValue();
+ aSequence[0].Name = "CharWeight";
+ aSequence[0].Value = Integer.valueOf( aBold.isSelected() ? 150 : 100 );
+ aSequence[1] = new PropertyValue();
+ aSequence[1].Name = "CharUnderline";
+ aSequence[1].Value = Integer.valueOf( aUnderline.isSelected() ? 1 : 0 );
+ aSequence[2] = new PropertyValue();
+ aSequence[2].Name = "CharBackColor";
+ aSequence[2].Value = Integer.valueOf( aBackground.getRGB() );
+ aSequence[3] = new PropertyValue();
+ aSequence[3].Name = "CharColor";
+ aSequence[3].Value = Integer.valueOf( aForeground.getRGB() );
+ aSequence[4] = new PropertyValue();
+ aSequence[4].Name = "CharPosture";
+ aSequence[4].Value = Integer.valueOf( aItalics.isSelected() ? 1 : 0 );
+ aSequence[5] = new PropertyValue();
+ aSequence[5].Name = "CharBackTransparent";
+ aSequence[5].Value = Boolean.FALSE;
+
+ bSuccess = xEdit.setAttributes( getSelectionStart(),
+ getSelectionEnd(),
+ aSequence );
+ }
+ return bSuccess;
+ }
+
+}
diff --git a/toolkit/test/accessibility/AccessibleTreeHandler.java b/toolkit/test/accessibility/AccessibleTreeHandler.java
new file mode 100644
index 0000000000..09fe790251
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleTreeHandler.java
@@ -0,0 +1,130 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.lang.IndexOutOfBoundsException;
+
+
+/**
+ * Map the tree of accessibility objects into their
+ * AccessibilityTreeModel counterparts.
+ */
+class AccessibleTreeHandler
+ extends NodeHandler
+{
+ private XAccessibleContext mxContext;
+
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ if (xContext != null)
+ return new AccessibleTreeHandler (xContext);
+ else
+ return null;
+ }
+
+ public AccessibleTreeHandler ()
+ {
+ super();
+ mxContext = null;
+ }
+
+ private AccessibleTreeHandler (XAccessibleContext xContext)
+ {
+ super();
+ mxContext = xContext;
+ if (mxContext != null)
+ // Add one to the number of children to include the string node
+ // that tells you how many children there are.
+ synchronized (maChildList)
+ {
+ maChildList.setSize (1 + mxContext.getAccessibleChildCount());
+ }
+ }
+
+ @Override
+ public AccessibleTreeNode createChild (AccessibleTreeNode aParent, int nIndex)
+ {
+ AccessibleTreeNode aChild = null;
+ if (mxContext != null)
+ {
+ if (nIndex == 0)
+ aChild = new StringNode ("Child count: " + mxContext.getAccessibleChildCount(),
+ aParent);
+ else
+ {
+ // Lower index to skip the string node.
+ nIndex -= 1;
+ try
+ {
+ XAccessible xChild = mxContext.getAccessibleChild (nIndex);
+ aChild = NodeFactory.Instance().createDefaultNode (
+ xChild, aParent);
+ }
+ catch( IndexOutOfBoundsException e )
+ {
+ aChild = new StringNode ("ERROR: no child with index " + nIndex, aParent);
+ }
+ }
+ }
+ else
+ aChild = new StringNode ("XAccessibleContext interface not supported", aParent);
+ return aChild;
+ }
+
+ /** Try to add the specified accessible child into the lists of
+ children. The insertion position is determined from the
+ getIndexInParent method of the child.
+ */
+ public AccessibleTreeNode addAccessibleChild (AccessibleTreeNode aParent, XAccessible xChild)
+ {
+ AccessibleTreeNode aChild = null;
+
+ if (xChild != null)
+ {
+ XAccessibleContext xContext = xChild.getAccessibleContext();
+ if (xContext != null)
+ {
+ long nIndex = xContext.getAccessibleIndexInParent() + 1;
+ synchronized (maChildList)
+ {
+ if ((nIndex >= 0) || (nIndex <= maChildList.size()))
+ {
+ aChild = NodeFactory.Instance().createDefaultNode (xChild, aParent);
+ maChildList.add (nIndex, aChild);
+ }
+ }
+ }
+ }
+ return aChild;
+ }
+
+
+ /** Update only the child count node. Trust on other ways to update the
+ accessible children.
+ */
+ @Override
+ public void update (AccessibleTreeNode aNode)
+ {
+ synchronized (maChildList)
+ {
+ maChildList.set (0, null);
+ }
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleTreeNode.java b/toolkit/test/accessibility/AccessibleTreeNode.java
new file mode 100644
index 0000000000..22fa035f95
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleTreeNode.java
@@ -0,0 +1,113 @@
+/*
+ * 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 .
+ */
+
+import java.util.ArrayList;
+
+import com.sun.star.lang.IndexOutOfBoundsException;
+
+/**
+ Base class for all tree nodes.
+ */
+abstract class AccessibleTreeNode
+{
+ /// The parent node. It is null for the root node.
+ private AccessibleTreeNode maParent;
+
+ /// The object to be displayed.
+ private final Object maDisplayObject;
+
+ public AccessibleTreeNode (Object aDisplayObject, AccessibleTreeNode aParent)
+ {
+ maDisplayObject = aDisplayObject;
+ maParent = aParent;
+ }
+
+ public void update ()
+ {
+ // Empty
+ }
+
+ public AccessibleTreeNode getParent ()
+ {
+ return maParent;
+ }
+
+ public int getChildCount ()
+ {
+ return 0;
+ }
+
+ public AccessibleTreeNode getChild (int nIndex)
+ throws IndexOutOfBoundsException
+ {
+ throw new IndexOutOfBoundsException();
+ }
+
+ public AccessibleTreeNode getChildNoCreate (int nIndex)
+ throws IndexOutOfBoundsException
+ {
+ throw new IndexOutOfBoundsException();
+ }
+
+ public boolean removeChild (int nIndex)
+ throws IndexOutOfBoundsException
+ {
+ throw new IndexOutOfBoundsException();
+ }
+
+ public abstract int indexOf (AccessibleTreeNode aNode);
+
+ /** Create a path to this node by first asking the parent for its path
+ and then appending this object.
+ */
+ public void createPath (java.util.List<AccessibleTreeNode> aPath)
+ {
+ if (maParent != null)
+ maParent.createPath (aPath);
+ aPath.add (this);
+ }
+
+ public Object[] createPath ()
+ {
+ ArrayList<AccessibleTreeNode> aPath = new ArrayList<AccessibleTreeNode> (1);
+ createPath (aPath);
+ return aPath.toArray();
+ }
+
+ public boolean isLeaf()
+ {
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return maDisplayObject.toString();
+ }
+
+ /** get names of supported actions */
+ public String[] getActions ()
+ {
+ return new String[] {};
+ }
+
+ /** perform action */
+ public void performAction (int nIndex)
+ {
+ }
+}
diff --git a/toolkit/test/accessibility/AccessibleUNOHandler.java b/toolkit/test/accessibility/AccessibleUNOHandler.java
new file mode 100644
index 0000000000..1ee522b277
--- /dev/null
+++ b/toolkit/test/accessibility/AccessibleUNOHandler.java
@@ -0,0 +1,126 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.lang.XServiceInfo;
+import com.sun.star.lang.XTypeProvider;
+import com.sun.star.uno.Type;
+
+
+/** This handler displays lower level UNO information. These are the
+ supported services, interfaces, and the implementation name.
+*/
+class AccessibleUNOHandler
+ extends NodeHandler
+{
+ @Override
+ public NodeHandler createHandler (XAccessibleContext xContext)
+ {
+ if (xContext == null)
+ return null;
+ else
+ {
+ AccessibleUNOHandler h = new AccessibleUNOHandler();
+ h.maChildList.setSize (3);
+ return h;
+ }
+ }
+
+ private XServiceInfo GetServiceInfo (AccessibleTreeNode aNode)
+ {
+ XServiceInfo xServiceInfo = null;
+ if (aNode instanceof AccTreeNode)
+ xServiceInfo = UnoRuntime.queryInterface(
+ XServiceInfo.class, ((AccTreeNode)aNode).getContext());
+ return xServiceInfo;
+ }
+ private XTypeProvider GetTypeProvider (AccessibleTreeNode aNode)
+ {
+ XTypeProvider xTypeProvider = null;
+ if (aNode instanceof AccTreeNode)
+ xTypeProvider = UnoRuntime.queryInterface(
+ XTypeProvider.class, ((AccTreeNode)aNode).getContext());
+ return xTypeProvider;
+ }
+
+ @Override
+ public AccessibleTreeNode createChild (AccessibleTreeNode aParent,
+ int nIndex)
+ {
+ AccessibleTreeNode aChild = null;
+ XServiceInfo xServiceInfo;
+ switch (nIndex)
+ {
+ case 0 : // Implementation name.
+ xServiceInfo = GetServiceInfo (aParent);
+ aChild = new StringNode ("Implementation name: " +
+ (xServiceInfo!=null ? xServiceInfo.getImplementationName()
+ : "<XServiceInfo not supported>"),
+ aParent);
+ break;
+ case 1 :
+ xServiceInfo = GetServiceInfo (aParent);
+ if (xServiceInfo == null)
+ aChild = new StringNode (
+ "Supported services: <XServiceInfo not supported>",
+ aParent);
+ else
+ aChild = CreateServiceTree (aParent, xServiceInfo);
+ break;
+ case 2 :
+ XTypeProvider xTypeProvider = GetTypeProvider (aParent);
+ if (xTypeProvider == null)
+ aChild = new StringNode (
+ "Supported interfaces: <XTypeProvider not supported>",
+ aParent);
+ else
+ aChild = CreateInterfaceTree (aParent, xTypeProvider);
+ break;
+ }
+
+ return aChild;
+ }
+
+
+ private AccessibleTreeNode CreateServiceTree (AccessibleTreeNode aParent,
+ XServiceInfo xServiceInfo)
+ {
+ String[] aServiceNames = xServiceInfo.getSupportedServiceNames();
+ VectorNode aNode = new VectorNode ("Supported Services", aParent);
+
+ int nCount = aServiceNames.length;
+ for (int i=0; i<nCount; i++)
+ aNode.addChild (new StringNode (aServiceNames[i], aParent));
+
+ return aNode;
+ }
+
+ private AccessibleTreeNode CreateInterfaceTree (AccessibleTreeNode aParent,
+ XTypeProvider xTypeProvider)
+ {
+ Type[] aTypes = xTypeProvider.getTypes();
+ VectorNode aNode = new VectorNode ("Supported Interfaces", aParent);
+
+ int nCount = aTypes.length;
+ for (int i=0; i<nCount; i++)
+ aNode.addChild (new StringNode (aTypes[i].getTypeName(), aParent));
+
+ return aNode;
+ }
+}
diff --git a/toolkit/test/accessibility/Canvas.java b/toolkit/test/accessibility/Canvas.java
new file mode 100644
index 0000000000..e9149ff82e
--- /dev/null
+++ b/toolkit/test/accessibility/Canvas.java
@@ -0,0 +1,463 @@
+/*
+ * 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 .
+ */
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.Toolkit;
+import java.awt.event.InputEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.geom.Rectangle2D;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTree;
+import javax.swing.JViewport;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.TreePath;
+
+/** This canvas displays accessible objects graphically. Each accessible
+ object with graphical representation is represented by an
+ CanvasShape object and has to be added by the
+ <member>addAccessible</member> member function.
+
+ <p>The canvas listens to selection events of the associated JTree and
+ highlights the first selected node of that tree.</p>
+*/
+class Canvas
+ extends JPanel
+ implements MouseListener, MouseMotionListener, TreeSelectionListener//, Scrollable
+{
+ // This constant can be passed to SetZoomMode to always show the whole screen.
+ public static final int WHOLE_SCREEN = -1;
+
+ public Canvas ()
+ {
+ super (true);
+ maObjects = new java.util.HashMap<AccTreeNode, CanvasShape> ();
+ maNodes = new ArrayList<AccTreeNode> ();
+ maObjectList = new ArrayList<CanvasShape> ();
+ addMouseListener (this);
+ addMouseMotionListener (this);
+ maBoundingBox = new Rectangle (0,0,100,100);
+ maTree = null;
+ mnHOffset = 0;
+ mnVOffset = 0;
+ mnScale = 1;
+ setShowText(false);
+ setShowDescriptions (true);
+ setShowNames (true);
+ setAntialiasing (true);
+ }
+
+ /** Tell the canvas which tree view to use to highlight accessible
+ objects.
+ */
+ public void setTree (JTree aTree)
+ {
+ if (maTree != null)
+ maTree.removeTreeSelectionListener (this);
+ maTree = aTree;
+ if (maTree != null)
+ maTree.addTreeSelectionListener (this);
+ }
+
+
+
+
+ public void addNode (AccTreeNode aNode)
+ {
+ if (maNodes.indexOf (aNode) == -1)
+ {
+ maNodes.add (aNode);
+
+ CanvasShape aObject = maObjects.get (aNode);
+ if (aObject == null)
+ {
+ aObject = new CanvasShape (aNode);
+ // Update bounding box that includes all objects.
+ if (maObjects.isEmpty())
+ maBoundingBox = aObject.getBBox();
+ else
+ maBoundingBox = maBoundingBox.union (aObject.getBBox());
+
+ maObjects.put (aNode, aObject);
+ maObjectList.add (aObject);
+
+ }
+ repaint ();
+ }
+ }
+
+ public void removeNode (AccTreeNode aNode)
+ {
+ int i = maNodes.indexOf (aNode);
+ if( i != -1 )
+ {
+ CanvasShape aObject = maObjects.get(aNode);
+ maObjectList.remove (aObject);
+ maObjects.remove (aNode);
+ maNodes.remove (aNode);
+ repaint ();
+ }
+ }
+
+ public void updateNode (AccTreeNode aNode)
+ {
+ int i = maNodes.indexOf (aNode);
+ if (i != -1)
+ {
+ CanvasShape aObject = maObjects.get(aNode);
+ if (aObject != null)
+ aObject.update();
+ }
+ }
+
+ public void updateNodeGeometry (AccTreeNode aNode)
+ {
+ CanvasShape aObject = maObjects.get(aNode);
+ if (aObject != null)
+ aObject.updateGeometry();
+ }
+
+ public void clear ()
+ {
+ while (maNodes.size() > 0) {
+ removeNode (maNodes.get(0));
+ }
+ maNodes.clear();
+ maObjects.clear();
+ maObjectList.clear();
+ }
+
+ public boolean getShowDescriptions ()
+ {
+ return Options.GetBoolean ("ShowDescriptions");
+ }
+
+ public void setShowDescriptions (boolean bNewValue)
+ {
+ Options.SetBoolean ("ShowDescriptions", bNewValue);
+ repaint ();
+ }
+
+ public boolean getShowNames ()
+ {
+ return Options.GetBoolean ("ShowNames");
+ }
+
+ public void setShowNames (boolean bNewValue)
+ {
+ Options.SetBoolean ("ShowNames", bNewValue);
+ repaint ();
+ }
+
+ public boolean getAntialiasing ()
+ {
+ return Options.GetBoolean ("Antialiasing");
+ }
+
+ public void setAntialiasing (boolean bNewValue)
+ {
+ Options.SetBoolean ("Antialiasing", bNewValue);
+ repaint ();
+ }
+
+ public boolean getShowText ()
+ {
+ return Options.GetBoolean ("ShowText");
+ }
+
+ private void setShowText (boolean bNewValue)
+ {
+ Options.SetBoolean ("ShowText", bNewValue);
+ repaint ();
+ }
+
+ public void setZoomMode (int nZoomMode)
+ {
+ Options.SetInteger ("ZoomMode", nZoomMode);
+ repaint ();
+ }
+
+ private int getZoomMode ()
+ {
+ return Options.GetInteger ("ZoomMode", WHOLE_SCREEN);
+ }
+
+
+ @Override
+ public void paintComponent (Graphics g)
+ {
+ synchronized (g)
+ {
+ super.paintComponent (g);
+
+ Graphics2D g2 = (Graphics2D)g;
+ if (getAntialiasing())
+ g2.setRenderingHint (RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+ else
+ g2.setRenderingHint (RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_OFF);
+
+ setupTransformation ();
+
+ // Draw the screen representation to give a hint of the location of the
+ // accessible object on the screen.
+ Dimension aScreenSize = Toolkit.getDefaultToolkit().getScreenSize();
+ Rectangle2D.Double aScreen = new Rectangle2D.Double (
+ mnHOffset,
+ mnVOffset,
+ mnScale*aScreenSize.getWidth(),
+ mnScale*aScreenSize.getHeight());
+ // Fill the screen rectangle and draw a frame around it to increase its visibility.
+ g2.setColor (new Color (250,240,230));
+ g2.fill (aScreen);
+ g2.setColor (Color.BLACK);
+ g2.draw (aScreen);
+
+ synchronized (maObjectList)
+ {
+ int nCount = maObjectList.size();
+ boolean bShowDescriptions = getShowDescriptions();
+ boolean bShowNames = getShowNames();
+ boolean bShowText = getShowText();
+ for (int i=0; i<nCount; i++)
+ {
+ CanvasShape aCanvasShape = maObjectList.get(i);
+ aCanvasShape.paint (
+ g2,
+ mnHOffset, mnVOffset, mnScale,
+ bShowDescriptions, bShowNames, bShowText);
+ }
+ }
+
+ // Paint highlighted frame around active object as the last thing.
+ if (maActiveObject != null)
+ maActiveObject.paint_highlight (
+ g2);
+ }
+ }
+
+
+
+
+ /** Set up the transformation so that the graphical display can show a
+ centered representation of the whole screen.
+ */
+ private void setupTransformation ()
+ {
+ // Turn off scrollbars when showing the whole screen. Otherwise show them when needed.
+ JViewport aViewport = (JViewport)getParent();
+ JScrollPane aScrollPane = (JScrollPane)aViewport.getParent();
+ int nZoomMode = getZoomMode();
+ if (nZoomMode == WHOLE_SCREEN)
+ {
+ if (aScrollPane.getHorizontalScrollBarPolicy()
+ != JScrollPane.HORIZONTAL_SCROLLBAR_NEVER)
+ aScrollPane.setHorizontalScrollBarPolicy (JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ if (aScrollPane.getVerticalScrollBarPolicy()
+ != JScrollPane.VERTICAL_SCROLLBAR_NEVER)
+ aScrollPane.setVerticalScrollBarPolicy (JScrollPane.VERTICAL_SCROLLBAR_NEVER);
+ }
+ else
+ {
+ if (aScrollPane.getHorizontalScrollBarPolicy()
+ != JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED)
+ aScrollPane.setHorizontalScrollBarPolicy (JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ if (aScrollPane.getVerticalScrollBarPolicy()
+ != JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED)
+ aScrollPane.setVerticalScrollBarPolicy (JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+ }
+
+ Dimension aScreenSize = Toolkit.getDefaultToolkit().getScreenSize();
+ Dimension aWidgetSize = aViewport.getSize();
+ {
+ if ((aScreenSize.getWidth() > 0) && (aScreenSize.getHeight() > 0))
+ {
+ if (nZoomMode == WHOLE_SCREEN)
+ {
+ // Calculate the scales that would map the screen onto the
+ // widget in both of the coordinate axes and select the
+ // smaller
+ // of the two: it maps the screen onto the widget in both
+ // axes at the same time.
+ double nHScale = (aWidgetSize.getWidth() - 10) / aScreenSize.getWidth();
+ double nVScale = (aWidgetSize.getHeight() - 10) / aScreenSize.getHeight();
+ if (nHScale < nVScale)
+ mnScale = nHScale;
+ else
+ mnScale = nVScale;
+ }
+ else
+ {
+ mnScale = nZoomMode / 100.0;
+ }
+
+ // Calculate offsets that center the scaled screen inside the widget.
+ mnHOffset = (aWidgetSize.getWidth() - mnScale*aScreenSize.getWidth()) / 2.0;
+ mnVOffset = (aWidgetSize.getHeight() - mnScale*aScreenSize.getHeight()) / 2.0;
+ if (mnHOffset < 0)
+ mnHOffset = 0;
+ if (mnVOffset < 0)
+ mnVOffset = 0;
+
+ setPreferredSize (new Dimension (
+ (int)(2*mnHOffset + mnScale * aScreenSize.getWidth()),
+ (int)(2*mnVOffset + mnScale * aScreenSize.getHeight())));
+ revalidate ();
+ }
+ else
+ {
+ // In case of a degenerate (not yet initialized?) screen size
+ // use some meaningless default values.
+ mnScale = 1;
+ mnHOffset = 0;
+ mnVOffset = 0;
+ }
+ }
+ }
+
+
+
+ /** Call getAccessibleAt to determine accessible object under mouse.
+ */
+ public void mouseClicked (MouseEvent e)
+ {
+ }
+
+ public void mousePressed (MouseEvent e)
+ {
+ CanvasShape aObjectUnderMouse = FindCanvasShapeUnderMouse (e);
+ highlightObject (aObjectUnderMouse);
+ if ((e.getModifiers() & InputEvent.CTRL_MASK) != 0)
+ {
+ maTree.expandPath (aObjectUnderMouse.getPath());
+ }
+ }
+
+ public void mouseReleased (MouseEvent e)
+ {
+ }
+
+ public void mouseEntered (MouseEvent e)
+ {
+ }
+
+ public void mouseExited (MouseEvent e)
+ {
+ // Deselect currently active object.
+ if (maActiveObject != null)
+ {
+ maActiveObject.unhighlight ();
+ maActiveObject = null;
+ repaint ();
+ }
+ }
+
+ public void mouseDragged (MouseEvent e)
+ {
+ }
+
+ public void mouseMoved (MouseEvent e)
+ {
+ if ((e.getModifiers() & InputEvent.SHIFT_MASK) != 0)
+ highlightObject (FindCanvasShapeUnderMouse (e));
+ }
+
+ private CanvasShape FindCanvasShapeUnderMouse (MouseEvent e)
+ {
+ CanvasShape aObjectUnderMouse = null;
+ int nCount = maObjectList.size();
+ for (int i=nCount-1; i>=0; --i)
+ {
+ CanvasShape aObject = maObjectList.get(i);
+ if (aObject != null && aObject.contains (e.getX(),e.getY()))
+ {
+ aObjectUnderMouse = aObject;
+ break;
+ }
+ }
+ return aObjectUnderMouse;
+ }
+
+ private boolean highlightObject (CanvasShape aNewActiveObject)
+ {
+ if (aNewActiveObject != maActiveObject)
+ {
+ if (maActiveObject != null)
+ maActiveObject.unhighlight();
+
+ maActiveObject = aNewActiveObject;
+ if (maActiveObject != null)
+ {
+ if (maTree != null)
+ {
+ maTree.scrollPathToVisible (maActiveObject.getPath());
+ maTree.setSelectionPath (maActiveObject.getPath());
+ maTree.repaint ();
+ }
+ maActiveObject.highlight ();
+ repaint ();
+ }
+ return true;
+ }
+ else
+ return false;
+ }
+
+ /** Called when the selection of the tree changes. Highlight the
+ corresponding graphical representation of the first selected object.
+ */
+ public void valueChanged (javax.swing.event.TreeSelectionEvent event)
+ {
+ TreePath aPath = event.getPath();
+ Object aObject = aPath.getLastPathComponent();
+ if (aObject instanceof AccTreeNode)
+ {
+ CanvasShape aCanvasShape = maObjects.get (aObject);
+ if (highlightObject (aCanvasShape))
+ repaint();
+ }
+ }
+
+ private double
+ mnHOffset,
+ mnVOffset,
+ mnScale;
+ private CanvasShape
+ maActiveObject;
+ private final java.util.HashMap<AccTreeNode, CanvasShape>
+ maObjects;
+ private final List<CanvasShape>
+ maObjectList;
+ private final List<AccTreeNode>
+ maNodes;
+ private Rectangle
+ maBoundingBox;
+ private JTree
+ maTree;
+}
diff --git a/toolkit/test/accessibility/CanvasShape.java b/toolkit/test/accessibility/CanvasShape.java
new file mode 100644
index 0000000000..71ae17d688
--- /dev/null
+++ b/toolkit/test/accessibility/CanvasShape.java
@@ -0,0 +1,286 @@
+/*
+ * 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 .
+ */
+
+import java.awt.*;
+import javax.swing.tree.*;
+import java.awt.geom.Rectangle2D;
+
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleComponent;
+import com.sun.star.accessibility.XAccessibleText;
+import com.sun.star.accessibility.AccessibleStateType;
+
+class CanvasShape
+{
+ private final Color maHighlightColor = Color.red;
+ private final Color maSelectionColor = Color.green;
+ private final Color maFocusColor = Color.blue;
+
+ public CanvasShape (AccTreeNode aNode)
+ {
+ maNode = aNode;
+ mxContext = aNode.getContext();
+ msName = "name unknown";
+ msDescription = "description unknown";
+ maShape = new Rectangle2D.Double (-10,-10,10,10);
+ maPosition = new Point (-10,-10);
+ maSize = new Dimension (10,10);
+ maFgColor = java.awt.Color.black;
+ maBgColor = Color.blue;
+ mbHighlighted = false;
+ mbSelected = false;
+ mbFocused = false;
+ mxComponent = aNode.getComponent();
+
+ update ();
+ }
+
+
+
+ /** Update the data obtained from the xAccessible.
+ */
+ public void update ()
+ {
+ if (mxContext != null)
+ {
+ msName = mxContext.getAccessibleName();
+ msDescription = mxContext.getAccessibleDescription();
+
+ // Extract the selected and focused flag.
+ long nStateSet = mxContext.getAccessibleStateSet ();
+ mbSelected = (nStateSet & AccessibleStateType.SELECTED) != 0;
+ mbFocused = (nStateSet & AccessibleStateType.FOCUSED) != 0;
+ }
+
+ updateGeometry ();
+ if (mxComponent != null)
+ {
+ // Note: alpha values in office 0..255 have to be mapped to
+ // 255..0 in Java
+ Color aCol = new Color (mxComponent.getForeground(), true);
+ maFgColor = new Color (aCol.getRed (),
+ aCol.getGreen (),
+ aCol.getBlue (),
+ 0xff - aCol.getAlpha ());
+ aCol = new Color (mxComponent.getBackground(), true);
+ maBgColor = new Color (aCol.getRed (),
+ aCol.getGreen (),
+ aCol.getBlue (),
+ 0xff - aCol.getAlpha ());
+ }
+ }
+
+ public void updateGeometry ()
+ {
+ if (mxComponent != null)
+ {
+ com.sun.star.awt.Point aLocationOnScreen = mxComponent.getLocationOnScreen();
+ com.sun.star.awt.Size aSizeOnScreen = mxComponent.getSize();
+ maPosition = new Point (
+ aLocationOnScreen.X,
+ aLocationOnScreen.Y);
+ maSize = new Dimension (
+ aSizeOnScreen.Width,
+ aSizeOnScreen.Height);
+ }
+ }
+
+
+ /** Paint the object into the specified canvas. It is transformed
+ according to the specified offset and scale.
+ */
+ public void paint (Graphics2D g,
+ double nXOffset, double nYOffset, double nScaleFactor,
+ boolean bShowDescription, boolean bShowName, boolean bShowText)
+ {
+ try{
+ // Transform the object's position and size according to the
+ // specified offset and scale.
+ maShape = new Rectangle2D.Double (
+ maPosition.x * nScaleFactor + nXOffset,
+ maPosition.y * nScaleFactor + nYOffset,
+ maSize.width * nScaleFactor,
+ maSize.height * nScaleFactor);
+
+ // Fill the object's bounding box with its background color if it
+ // has no children.
+ if (mxContext.getAccessibleChildCount() == 0)
+ {
+ g.setColor (maBgColor);
+ g.fill (maShape);
+ }
+
+ // Remove alpha channel from color before drawing the frame.
+ Color color = maFgColor;
+ if (maFgColor.getAlpha()<128)
+ color = new Color (maFgColor.getRed(), maFgColor.getGreen(), maFgColor.getBlue());
+ g.setColor (color);
+ g.draw (maShape);
+
+ if (mbFocused)
+ {
+ g.setColor (maFocusColor);
+ for (int x=0; x<=2; x++)
+ for (int y=0; y<=2; y++)
+ g.fill (
+ new Rectangle2D.Double (
+ maShape.x + x/2.0 * maShape.width-3,
+ maShape.y + y/2.0 * maShape.height-3,
+ 6,
+ 6));
+ }
+ if (mbSelected)
+ {
+ g.setColor (maSelectionColor);
+ for (int x=0; x<=2; x++)
+ for (int y=0; y<=2; y++)
+ g.draw (
+ new Rectangle2D.Double (
+ maShape.x + x/2.0 * maShape.width-2,
+ maShape.y + y/2.0 * maShape.height-2,
+ 4,
+ 4));
+ }
+
+ // Write the object's text OR name and description.
+ g.setColor (maFgColor);
+ if (bShowName)
+ paintName (g);
+ if (bShowDescription)
+ paintDescription (g);
+ if (bShowText)
+ paintText (g);
+ }
+ catch (Exception e)
+ { // don't care
+ }
+ }
+
+ public void paint_highlight (Graphics2D g)
+ {
+ if (mbHighlighted)
+ g.setColor (maHighlightColor);
+ else
+ g.setColor (maFgColor);
+ g.draw (maShape);
+ }
+
+
+
+
+ private void paintName (Graphics2D g)
+ {
+ g.drawString ("Name: " + msName,
+ (float)maShape.x+5,
+ (float)maShape.y+15);
+ }
+
+
+
+ private void paintDescription (Graphics2D g)
+ {
+ g.drawString ("Description: " + msDescription,
+ (float)maShape.x+5,
+ (float)maShape.y+35);
+ }
+
+
+
+
+ private void paintText (Graphics2D g)
+ {
+ XAccessibleText xText = null;
+ // get XAccessibleText
+ xText = maNode.getText();
+
+ // Draw every character in the text string.
+ if (xText != null)
+ {
+ String sText = xText.getText();
+ try
+ {
+ for(int i = 0; i < sText.length(); i++)
+ {
+ com.sun.star.awt.Rectangle aRect =
+ xText.getCharacterBounds(i);
+
+ double x = maShape.x + aRect.X;
+ double y = maShape.y + aRect.Y + aRect.Height;
+
+ g.drawString(sText.substring(i, i+1), (float)x, (float)y);
+ }
+ }
+ catch (com.sun.star.lang.IndexOutOfBoundsException e)
+ {}
+ }
+ }
+
+
+
+
+ /** Compute whether the specified point lies inside the object's
+ bounding box.
+ */
+ public boolean contains (int x, int y)
+ {
+ return maShape.contains (x,y);
+ }
+
+ public void highlight ()
+ {
+ mbHighlighted = true;
+ }
+
+ public void unhighlight ()
+ {
+ mbHighlighted = false;
+ }
+
+ public Rectangle getBBox ()
+ {
+ return new Rectangle (maPosition, maSize);
+ }
+
+ public TreePath getPath ()
+ {
+ return new TreePath (maNode.createPath());
+ }
+
+ @Override
+ public String toString ()
+ {
+ return ">"+msName+", "+msDescription+" +"+maPosition.x+"+"+maPosition.y
+ +"x"+maSize.width+"x"+maSize.height+"<";
+ }
+
+ private final AccTreeNode maNode;
+ private final XAccessibleContext mxContext;
+ private final XAccessibleComponent mxComponent;
+ private String msDescription, msName;
+ private Rectangle2D.Double maShape;
+ private Point maPosition;
+ private Dimension maSize;
+ private Color maFgColor, maBgColor;
+ private boolean
+ // Highlighting objects is an internal concept. Corresponds to selection in the tree view.
+ mbHighlighted,
+ // Set when the accessible object is selected.
+ mbSelected,
+ // Set when the accessible object is focused.
+ mbFocused;
+}
diff --git a/toolkit/test/accessibility/ChildEventHandler.java b/toolkit/test/accessibility/ChildEventHandler.java
new file mode 100644
index 0000000000..e36f3502ad
--- /dev/null
+++ b/toolkit/test/accessibility/ChildEventHandler.java
@@ -0,0 +1,66 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.AccessibleEventObject;
+import com.sun.star.uno.UnoRuntime;
+
+import java.io.PrintStream;
+
+class ChildEventHandler
+ extends EventHandler
+{
+ public ChildEventHandler (AccessibleEventObject aEvent, AccessibilityTreeModel aTreeModel)
+ {
+ super (aEvent, aTreeModel);
+ mxOldChild = UnoRuntime.queryInterface(
+ XAccessible.class, aEvent.OldValue);
+ mxNewChild = UnoRuntime.queryInterface(
+ XAccessible.class, aEvent.NewValue);
+ }
+
+ @Override
+ public void PrintOldAndNew (PrintStream out)
+ {
+ if (mxOldChild != null)
+ out.println (" removing child " + mxOldChild);
+ if (mxNewChild != null)
+ out.println (" adding child " + mxNewChild);
+ }
+
+ @Override
+ public void Process ()
+ {
+ // Insertion and removal of children should be mutually exclusive.
+ // But this is a test tool and should take everything into account.
+ if (mxOldChild != null)
+ {
+ maTreeModel.removeNode (mxOldChild.getAccessibleContext());
+ maTreeModel.updateNode (mxEventSource, AccessibleTreeHandler.class);
+ }
+
+ if (mxNewChild != null)
+ {
+ maTreeModel.addChild (mxEventSource, mxNewChild);
+ }
+ }
+
+
+ private final XAccessible mxOldChild;
+ private final XAccessible mxNewChild;
+}
diff --git a/toolkit/test/accessibility/ContextEventHandler.java b/toolkit/test/accessibility/ContextEventHandler.java
new file mode 100644
index 0000000000..12ffd0648c
--- /dev/null
+++ b/toolkit/test/accessibility/ContextEventHandler.java
@@ -0,0 +1,70 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.accessibility.AccessibleEventObject;
+import com.sun.star.accessibility.AccessibleEventId;
+import com.sun.star.uno.AnyConverter;
+
+import java.io.PrintStream;
+
+import tools.NameProvider;
+
+class ContextEventHandler
+ extends EventHandler
+{
+ public ContextEventHandler (AccessibleEventObject aEvent, AccessibilityTreeModel aTreeModel)
+ {
+ super (aEvent, aTreeModel);
+ }
+
+ @Override
+ public void PrintOldAndNew (PrintStream out)
+ {
+ switch (mnEventId)
+ {
+ case AccessibleEventId.STATE_CHANGED:
+ try
+ {
+ int nOldValue = AnyConverter.toInt (maEvent.OldValue);
+ out.println (" turning off state " + nOldValue + " ("
+ + NameProvider.getStateName (nOldValue) + ")");
+ }
+ catch (com.sun.star.lang.IllegalArgumentException e)
+ {}
+ try
+ {
+ int nNewValue = AnyConverter.toInt (maEvent.NewValue);
+ out.println (" turning on state " + nNewValue + " ("
+ + NameProvider.getStateName (nNewValue) + ")");
+ }
+ catch (com.sun.star.lang.IllegalArgumentException e)
+ {}
+ break;
+
+ default:
+ super.PrintOldAndNew (out);
+ }
+
+ }
+
+ @Override
+ public void Process ()
+ {
+ maTreeModel.updateNode (mxEventSource, AccessibleContextHandler.class);
+ }
+}
diff --git a/toolkit/test/accessibility/EventHandler.java b/toolkit/test/accessibility/EventHandler.java
new file mode 100644
index 0000000000..ed1a7adb4a
--- /dev/null
+++ b/toolkit/test/accessibility/EventHandler.java
@@ -0,0 +1,75 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.AccessibleEventObject;
+import com.sun.star.uno.UnoRuntime;
+
+import java.io.PrintStream;
+
+import tools.NameProvider;
+
+/** Base class for handling of accessibility events.
+*/
+class EventHandler
+{
+ public EventHandler (AccessibleEventObject aEvent, AccessibilityTreeModel aTreeModel)
+ {
+ maEvent = aEvent;
+ maTreeModel = aTreeModel;
+
+ mnEventId = aEvent.EventId;
+
+ mxEventSource = UnoRuntime.queryInterface(
+ XAccessibleContext.class, aEvent.Source);
+ if (mxEventSource == null)
+ {
+ XAccessible xAccessible = UnoRuntime.queryInterface(
+ XAccessible.class, aEvent.Source);
+ if (xAccessible != null)
+ mxEventSource = xAccessible.getAccessibleContext();
+ }
+ }
+
+ public void Print (PrintStream out)
+ {
+ out.println ("Event id is " + mnEventId
+ + " (" + NameProvider.getEventName(mnEventId)+")"
+ + " for " + mxEventSource.getAccessibleName() + " / "
+ + NameProvider.getRoleName (mxEventSource.getAccessibleRole()));
+ PrintOldAndNew (out);
+ }
+
+ public void PrintOldAndNew (PrintStream out)
+ {
+ out.println (" old value is " + maEvent.OldValue);
+ out.println (" new value is " + maEvent.NewValue);
+ }
+
+ public void Process ()
+ {
+ System.out.println ("processing of event " + maEvent + " not implemented");
+ }
+
+ protected AccessibleEventObject maEvent;
+ protected AccessibilityTreeModel maTreeModel;
+
+ protected int mnEventId;
+ protected XAccessibleContext mxEventSource;
+}
diff --git a/toolkit/test/accessibility/EventListener.java b/toolkit/test/accessibility/EventListener.java
new file mode 100644
index 0000000000..5d9141953d
--- /dev/null
+++ b/toolkit/test/accessibility/EventListener.java
@@ -0,0 +1,108 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.accessibility.*;
+
+/** Objects of this class (usually one, singleton?) listen to accessible
+ events of all objects in all trees.
+*/
+public class EventListener
+{
+ private boolean mbVerbose = false;
+
+ public EventListener (AccessibilityTreeModel aTreeModel)
+ {
+ maTreeModel = aTreeModel;
+ }
+
+
+ /** This method handles accessibility objects that are being disposed.
+ */
+ public void disposing (XAccessibleContext xContext)
+ {
+ if (mbVerbose)
+ System.out.println("disposing " + xContext);
+ maTreeModel.removeNode (xContext);
+ }
+
+ /** This method is called from accessible objects that broadcast
+ modifications of themselves or from their children. The event is
+ processed only, except printing some messages, if the tree is not
+ locked. It should be locked during changes to its internal
+ structure like expanding nodes.
+ */
+ public void notifyEvent (AccessibleEventObject aEvent)
+ {
+ EventHandler aHandler;
+
+ switch (aEvent.EventId)
+ {
+ case AccessibleEventId.CHILD:
+ aHandler = new ChildEventHandler (aEvent, maTreeModel);
+ break;
+
+ case AccessibleEventId.BOUNDRECT_CHANGED:
+ case AccessibleEventId.VISIBLE_DATA_CHANGED:
+ aHandler = new GeometryEventHandler (aEvent, maTreeModel);
+ break;
+
+
+ case AccessibleEventId.NAME_CHANGED:
+ case AccessibleEventId.DESCRIPTION_CHANGED:
+ case AccessibleEventId.STATE_CHANGED:
+ case AccessibleEventId.SELECTION_CHANGED:
+ aHandler = new ContextEventHandler (aEvent, maTreeModel);
+ break;
+
+ case AccessibleEventId.TABLE_MODEL_CHANGED:
+ case AccessibleEventId.TABLE_CAPTION_CHANGED:
+ case AccessibleEventId.TABLE_COLUMN_DESCRIPTION_CHANGED:
+ case AccessibleEventId.TABLE_COLUMN_HEADER_CHANGED:
+ case AccessibleEventId.TABLE_ROW_DESCRIPTION_CHANGED:
+ case AccessibleEventId.TABLE_ROW_HEADER_CHANGED:
+ case AccessibleEventId.TABLE_SUMMARY_CHANGED:
+ aHandler = new TableEventHandler (aEvent, maTreeModel);
+ break;
+
+ case AccessibleEventId.ACTION_CHANGED:
+ case AccessibleEventId.HYPERTEXT_CHANGED:
+ case AccessibleEventId.ACTIVE_DESCENDANT_CHANGED:
+ case AccessibleEventId.CARET_CHANGED:
+ case AccessibleEventId.TEXT_CHANGED:
+ case AccessibleEventId.VALUE_CHANGED:
+ aHandler = new EventHandler (aEvent, maTreeModel);
+ break;
+
+ default:
+ aHandler = null;
+ break;
+ }
+
+ if (aHandler == null)
+ System.out.println (" unhandled event");
+ else
+ {
+ if (mbVerbose)
+ aHandler.Print (System.out);
+ aHandler.Process ();
+ }
+ }
+
+
+ private final AccessibilityTreeModel maTreeModel;
+}
diff --git a/toolkit/test/accessibility/EventQueue.java b/toolkit/test/accessibility/EventQueue.java
new file mode 100644
index 0000000000..b6f6c6415e
--- /dev/null
+++ b/toolkit/test/accessibility/EventQueue.java
@@ -0,0 +1,140 @@
+/*
+ * 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 .
+ */
+
+import java.util.LinkedList;
+
+/** The event queue singleton dispatches events received from OpenOffice.org
+ applications in a thread separate from the AWB main thread.
+
+ The queue of event objects, LinkedList<Runnable> The queue object will
+ also serve as lock for the consumer/producer type synchronization.
+*/
+class EventQueue
+ implements Runnable
+{
+ private boolean mbVerbose = false;
+ private boolean mbHandleDisposingEventsSynchronous = true;
+
+ public synchronized static EventQueue Instance ()
+ {
+ if (maInstance == null)
+ maInstance = new EventQueue ();
+ return maInstance;
+ }
+
+ public void addEvent (Runnable aEvent)
+ {
+ synchronized (maMonitor)
+ {
+ if (mbVerbose)
+ System.out.println ("queueing regular event " + aEvent);
+ maRegularQueue.addLast (aEvent);
+ maMonitor.notify ();
+ }
+ }
+
+
+ public void addDisposingEvent (Runnable aEvent)
+ {
+ if (mbHandleDisposingEventsSynchronous)
+ aEvent.run ();
+ else
+ synchronized (maMonitor)
+ {
+ if (mbVerbose)
+ System.out.println ("queueing disposing event " + aEvent);
+ maDisposingQueue.addLast (aEvent);
+ maMonitor.notify ();
+ }
+ }
+
+
+ private EventQueue ()
+ {
+ maRegularQueue = new LinkedList<Runnable>();
+ maDisposingQueue = new LinkedList<Runnable>();
+ new Thread(this, "AWB.EventQueue").start();
+ }
+
+
+ /// This thread's main method: deliver all events
+ public void run()
+ {
+ // in an infinite loop, check for events to deliver, then
+ // wait on lock (which will be notified when new events arrive)
+ while( true )
+ {
+ Runnable aEvent = null;
+ do
+ {
+ synchronized (maMonitor)
+ {
+ if (maDisposingQueue.size() > 0)
+ {
+ aEvent = maDisposingQueue.removeFirst();
+ if (mbVerbose)
+ System.out.println ("delivering disposing event " + aEvent);
+ }
+ else if (maRegularQueue.size() > 0)
+ {
+ aEvent = maRegularQueue.removeFirst();
+ if (mbVerbose)
+ System.out.println ("delivering regular event " + aEvent);
+ }
+ else
+ aEvent = null;
+ }
+ if (aEvent != null)
+ {
+ try
+ {
+ aEvent.run();
+ }
+ catch( Throwable e )
+ {
+ System.out.println(
+ "caught exception during event delivery: " + e );
+ e.printStackTrace();
+ }
+ }
+ }
+ while( aEvent != null );
+
+ try
+ {
+ synchronized (maMonitor)
+ {
+ maMonitor.wait();
+ }
+ }
+ catch (Exception e)
+ {
+ // can't wait? odd!
+ System.err.println("Can't wait!");
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private static EventQueue maInstance = null;
+ private final Object maMonitor = new Object();
+ private final LinkedList<Runnable> maRegularQueue;
+ private final LinkedList<Runnable> maDisposingQueue;
+}
+
+
diff --git a/toolkit/test/accessibility/GeometryEventHandler.java b/toolkit/test/accessibility/GeometryEventHandler.java
new file mode 100644
index 0000000000..c55ee3acc4
--- /dev/null
+++ b/toolkit/test/accessibility/GeometryEventHandler.java
@@ -0,0 +1,71 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.accessibility.AccessibleEventObject;
+import java.io.PrintStream;
+import java.util.LinkedList;
+
+class GeometryEventHandler
+ extends EventHandler
+{
+ public GeometryEventHandler (AccessibleEventObject aEvent, AccessibilityTreeModel aTreeModel)
+ {
+ super (aEvent, aTreeModel);
+ }
+
+ @Override
+ public void PrintOldAndNew (PrintStream out)
+ {
+ out.println (" children not relevant");
+ }
+
+ @Override
+ public void Process ()
+ {
+ AccTreeNode aNode = maTreeModel.updateNode (mxEventSource,
+ AccessibleComponentHandler.class,
+ AccessibleExtendedComponentHandler.class);
+
+ // Update the graphical representation of aNode in the Canvas.
+ Canvas aCanvas = maTreeModel.getCanvas();
+ if (aCanvas != null)
+ {
+ // Iterate over all nodes in the sub-tree rooted in aNode.
+ LinkedList<Object> aShapeQueue = new LinkedList<Object>();
+ aShapeQueue.addLast (aNode);
+ while (aShapeQueue.size() > 0)
+ {
+ // Remove the first node from the queue and update its
+ // graphical representation.
+ AccTreeNode aShapeNode = (AccTreeNode) aShapeQueue.getFirst();
+ aShapeQueue.removeFirst();
+ aCanvas.updateNodeGeometry (aShapeNode);
+
+ // Add the node's children to the queue.
+ int nChildCount = maTreeModel.getChildCount (aShapeNode);
+ for (int i=0; i<nChildCount; i++)
+ {
+ Object aTreeNode = maTreeModel.getChildNoCreate (aShapeNode, i);
+ if (aTreeNode instanceof AccTreeNode)
+ aShapeQueue.addLast (aTreeNode);
+ }
+ }
+ aCanvas.repaint ();
+ }
+ }
+}
diff --git a/toolkit/test/accessibility/HelpWindow.java b/toolkit/test/accessibility/HelpWindow.java
new file mode 100644
index 0000000000..00c9340676
--- /dev/null
+++ b/toolkit/test/accessibility/HelpWindow.java
@@ -0,0 +1,189 @@
+/*
+ * 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 .
+ */
+
+import javax.swing.JFrame;
+import javax.swing.JScrollPane;
+import javax.swing.JEditorPane;
+import javax.swing.JButton;
+import java.net.URL;
+import javax.swing.event.HyperlinkListener;
+import javax.swing.event.HyperlinkEvent;
+import java.net.MalformedURLException;
+import java.io.File;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.GridBagLayout;
+import java.awt.GridBagConstraints;
+import java.awt.event.ActionListener;
+import java.util.LinkedList;
+
+class HelpWindow
+ implements ActionListener
+{
+ public static synchronized HelpWindow Instance ()
+ {
+ if (maInstance == null)
+ maInstance = new HelpWindow();
+ return maInstance;
+ }
+
+ public void loadFile (String sFilename)
+ {
+ File aFile = new File (sFilename);
+ try
+ {
+ loadURL (aFile.toURI().toURL());
+ }
+ catch (MalformedURLException e)
+ {
+ e.printStackTrace (System.err);
+ }
+ }
+
+ private void loadURL (URL aURL)
+ {
+ maHistory.addLast (aURL);
+ selectHistoryPage (maHistory.size()-1);
+ maFrame.toFront ();
+ }
+
+
+
+
+ private HelpWindow ()
+ {
+ try
+ {
+ maCurrentHistoryEntry = -1;
+ maHistory = new LinkedList<URL>();
+
+ maFrame = new JFrame ();
+ maFrame.addWindowListener (new WindowAdapter ()
+ {
+ @Override
+ public void windowClosing (WindowEvent e)
+ {
+ maInstance = null;
+ }
+ });
+ maContent = createContentWidget();
+
+ maFrame.getContentPane().setLayout (new GridBagLayout());
+ GridBagConstraints aConstraints = new GridBagConstraints ();
+ aConstraints.gridx = 0;
+ aConstraints.gridy = 0;
+ aConstraints.gridwidth = 3;
+ aConstraints.weightx = 1;
+ aConstraints.weighty = 1;
+ aConstraints.fill = GridBagConstraints.BOTH;
+ maFrame.getContentPane().add (new JScrollPane (maContent), aConstraints);
+
+ aConstraints = new GridBagConstraints();
+ aConstraints.gridx = 0;
+ aConstraints.gridy = 1;
+ maPrevButton = new JButton ("Prev");
+ maFrame.getContentPane().add (maPrevButton, aConstraints);
+ maPrevButton.addActionListener (this);
+
+ aConstraints = new GridBagConstraints();
+ aConstraints.gridx = 1;
+ aConstraints.gridy = 1;
+ maNextButton = new JButton ("Next");
+ maFrame.getContentPane().add (maNextButton, aConstraints);
+ maNextButton.addActionListener (this);
+
+ aConstraints = new GridBagConstraints();
+ aConstraints.gridx = 2;
+ aConstraints.gridy = 1;
+ aConstraints.anchor = GridBagConstraints.EAST;
+ JButton aButton = new JButton ("Close");
+ maFrame.getContentPane().add (aButton, aConstraints);
+ aButton.addActionListener (this);
+
+ maFrame.setSize (600,400);
+ maFrame.setVisible (true);
+ }
+ catch (Exception e)
+ {}
+ }
+
+ public void actionPerformed (java.awt.event.ActionEvent e)
+ {
+ if (e.getActionCommand().equals("Prev"))
+ {
+ selectHistoryPage (maCurrentHistoryEntry - 1);
+ }
+ else if (e.getActionCommand().equals("Next"))
+ {
+ selectHistoryPage (maCurrentHistoryEntry + 1);
+ }
+ else if (e.getActionCommand().equals("Close"))
+ {
+ maFrame.dispose ();
+ maInstance = null;
+ }
+ }
+
+ private JEditorPane createContentWidget ()
+ {
+ JEditorPane aContent = new JEditorPane ();
+ aContent.setEditable (false);
+ aContent.addHyperlinkListener (new HyperlinkListener()
+ {
+ public void hyperlinkUpdate (HyperlinkEvent e)
+ {
+ if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED)
+ HelpWindow.Instance().loadURL (e.getURL());
+ }
+ });
+ return aContent;
+ }
+
+ private void selectHistoryPage (int i)
+ {
+ if (i < 0)
+ i = 0;
+ else if (i >= maHistory.size()-1)
+ i = maHistory.size()-1;
+ if (i != maCurrentHistoryEntry)
+ {
+ URL aURL = maHistory.get (i);
+ try
+ {
+ maContent.setPage (aURL);
+ }
+ catch (java.io.IOException ex)
+ {
+ ex.printStackTrace(System.err);
+ }
+
+ maCurrentHistoryEntry = i;
+ }
+
+ maPrevButton.setEnabled (maCurrentHistoryEntry > 0);
+ maNextButton.setEnabled (maCurrentHistoryEntry < maHistory.size()-1);
+ }
+
+ private static HelpWindow maInstance = null;
+ private JFrame maFrame;
+ private JEditorPane maContent;
+ private LinkedList<URL> maHistory;
+ private int maCurrentHistoryEntry;
+ private JButton maPrevButton;
+ private JButton maNextButton;
+}
diff --git a/toolkit/test/accessibility/MessageArea.java b/toolkit/test/accessibility/MessageArea.java
new file mode 100644
index 0000000000..512cfaf733
--- /dev/null
+++ b/toolkit/test/accessibility/MessageArea.java
@@ -0,0 +1,131 @@
+/*
+ * 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 .
+ */
+
+import java.awt.Font;
+import java.awt.Color;
+import java.awt.Graphics;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JScrollBar;
+
+
+
+/** A message area displays text in a scrollable text widget. It is a
+ singleton. Other objects can access it directly to display messages.
+*/
+public class MessageArea
+ extends JScrollPane
+{
+ public static synchronized MessageArea Instance ()
+ {
+ if (saInstance == null)
+ saInstance = new MessageArea ();
+ return saInstance;
+ }
+
+
+
+
+ /** Create a new message area. This method is private because the class is
+ a singleton and may therefore not be instantiated from the outside.
+ */
+ private MessageArea ()
+ {
+ maText = new JTextArea();
+ maText.setBackground (new Color (255,250,240));
+ maText.setFont (new Font ("Helvetica", Font.PLAIN, 9));
+ setViewportView (maText);
+ setVerticalScrollBarPolicy (JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
+ setHorizontalScrollBarPolicy (JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
+
+ printMessage (
+ "class path is " + System.getProperty ("java.class.path") + "\n");
+ }
+
+
+
+
+ /** Show the given string at the end of the message area and scroll to make
+ it visible. Indent the string as requested.
+ */
+ private static synchronized void print (int nIndentation, String aMessage)
+ {
+ while (nIndentation-- > 0) {
+ aMessage = " " + aMessage;
+ }
+ Instance().printMessage(aMessage);
+ }
+
+
+
+
+ /** Show the given string at the end of the message area and scroll to make
+ it visible.
+ */
+ public static void println (String aMessage)
+ {
+ println (0, aMessage);
+ }
+
+
+
+
+ /** Show the given string at the end of the message area and scroll to make
+ it visible.
+ */
+ private static void println (int nIndentation, String aMessage)
+ {
+ print (nIndentation, aMessage+"\n");
+ }
+
+
+
+
+ @Override
+ public void paintComponent (Graphics g)
+ {
+ synchronized (g)
+ {
+ JScrollBar sb = getVerticalScrollBar();
+ if (sb != null)
+ {
+ int nScrollBarValue = sb.getMaximum() - sb.getVisibleAmount() - 1;
+ sb.setValue (nScrollBarValue);
+ }
+ super.paintComponent (g);
+ }
+ }
+
+
+
+
+ /** Append the given string to the end of the text and scroll so that it
+ becomes visible. This is an internal method. Use one of the static
+ and public ones.
+ */
+ private synchronized void printMessage (String aMessage)
+ {
+ maText.append (aMessage);
+ }
+
+
+
+
+ private static MessageArea saInstance = null;
+ private final JTextArea maText;
+}
diff --git a/toolkit/test/accessibility/NodeFactory.java b/toolkit/test/accessibility/NodeFactory.java
new file mode 100644
index 0000000000..7e1d9f585c
--- /dev/null
+++ b/toolkit/test/accessibility/NodeFactory.java
@@ -0,0 +1,142 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.accessibility.*;
+import tools.NameProvider;
+
+/** This singleton class creates nodes for given accessible objects.
+*/
+class NodeFactory
+{
+ public synchronized static NodeFactory Instance ()
+ {
+ if (maInstance == null)
+ {
+ maInstance = new NodeFactory();
+ }
+ return maInstance;
+ }
+
+ private NodeFactory ()
+ {
+ }
+
+
+ /** add default handlers based on the supported interfaces */
+ private void addDefaultHandlers (AccTreeNode aNode, XAccessibleContext xContext)
+ {
+ if (false)
+ {
+ // Slow but complete version: try each handler type separately.
+ aNode.addHandler (maContextHandler.createHandler (xContext));
+ aNode.addHandler (maTextHandler.createHandler (xContext));
+ aNode.addHandler (maEditableTextHandler.createHandler (xContext));
+ aNode.addHandler (maComponentHandler.createHandler (xContext));
+ aNode.addHandler (maExtendedComponentHandler.createHandler (xContext));
+ aNode.addHandler (maActionHandler.createHandler (xContext));
+ aNode.addHandler (maImageHandler.createHandler (xContext));
+ aNode.addHandler (maTableHandler.createHandler (xContext));
+ aNode.addHandler (maCellHandler.createHandler (xContext));
+ aNode.addHandler (maHypertextHandler.createHandler (xContext));
+ aNode.addHandler (maHyperlinkHandler.createHandler (xContext));
+ aNode.addHandler (maSelectionHandler.createHandler (xContext));
+ aNode.addHandler (maRelationHandler.createHandler (xContext));
+ aNode.addHandler (maUNOHandler.createHandler (xContext));
+ aNode.addHandler (maTreeHandler.createHandler (xContext));
+ }
+ else
+ {
+ // Exploit dependencies between interfaces.
+ NodeHandler aHandler;
+ aNode.addHandler (maContextHandler.createHandler (xContext));
+
+ aHandler = maTextHandler.createHandler (xContext);
+ if (aHandler != null)
+ {
+ aNode.addHandler (aHandler);
+ aNode.addHandler (maEditableTextHandler.createHandler (xContext));
+ aNode.addHandler (maHypertextHandler.createHandler (xContext));
+ aNode.addHandler (maHyperlinkHandler.createHandler (xContext));
+ }
+ aHandler = maComponentHandler.createHandler (xContext);
+ if (aHandler != null)
+ {
+ aNode.addHandler (aHandler);
+ aNode.addHandler (maExtendedComponentHandler.createHandler (xContext));
+ }
+ aNode.addHandler (maActionHandler.createHandler (xContext));
+ aNode.addHandler (maImageHandler.createHandler (xContext));
+ aNode.addHandler (maTableHandler.createHandler (xContext));
+ aNode.addHandler (maRelationHandler.createHandler (xContext));
+ aNode.addHandler (maCellHandler.createHandler (xContext));
+ aNode.addHandler (maSelectionHandler.createHandler (xContext));
+ aNode.addHandler (maUNOHandler.createHandler (xContext));
+ aNode.addHandler (maTreeHandler.createHandler (xContext));
+ }
+ }
+
+ /** create a node with the default handlers */
+ public AccTreeNode createDefaultNode (XAccessible xAccessible, AccessibleTreeNode aParent)
+ {
+ // default: aObject + aDisplay
+ String sDisplay;
+
+ // if we are accessible, we use the context + name instead
+ XAccessibleContext xContext = null;
+ if (xAccessible != null)
+ xContext = xAccessible.getAccessibleContext();
+ if (xContext != null)
+ {
+ sDisplay = xContext.getAccessibleName();
+ if (sDisplay.length()==0)
+ {
+ sDisplay = "<no name> Role: "
+ + NameProvider.getRoleName (
+ xContext.getAccessibleRole());
+ }
+ }
+ else
+ sDisplay = "not accessible";
+
+
+ // create node, and add default handlers
+ AccTreeNode aNode = new AccTreeNode (xContext, sDisplay, aParent);
+ addDefaultHandlers (aNode, xContext);
+
+ return aNode;
+ }
+
+ private static NodeFactory maInstance = null;
+
+ // default handlers
+ private final NodeHandler maContextHandler = new AccessibleContextHandler();
+ private final NodeHandler maTextHandler = new AccessibleTextHandler();
+ private final NodeHandler maEditableTextHandler = new AccessibleEditableTextHandler();
+ private final NodeHandler maComponentHandler = new AccessibleComponentHandler();
+ private final NodeHandler maExtendedComponentHandler = new AccessibleExtendedComponentHandler();
+ private final NodeHandler maActionHandler = new AccessibleActionHandler();
+ private final NodeHandler maImageHandler = new AccessibleImageHandler();
+ private final NodeHandler maTableHandler = new AccessibleTableHandler();
+ private final NodeHandler maCellHandler = new AccessibleCellHandler();
+ private final NodeHandler maHypertextHandler = new AccessibleHypertextHandler();
+ private final NodeHandler maHyperlinkHandler = new AccessibleHyperlinkHandler();
+ private final NodeHandler maSelectionHandler = new AccessibleSelectionHandler();
+ private final NodeHandler maRelationHandler = new AccessibleRelationHandler();
+ private final NodeHandler maTreeHandler = new AccessibleTreeHandler();
+ private final NodeHandler maUNOHandler = new AccessibleUNOHandler();
+}
diff --git a/toolkit/test/accessibility/NodeHandler.java b/toolkit/test/accessibility/NodeHandler.java
new file mode 100644
index 0000000000..69cff2c13e
--- /dev/null
+++ b/toolkit/test/accessibility/NodeHandler.java
@@ -0,0 +1,133 @@
+/*
+ * 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 .
+ */
+
+import java.util.Vector;
+
+
+/**
+ * Map an arbitrary object into parts of a tree node.
+ */
+abstract class NodeHandler
+{
+ /** This vector is used as cache for the child objects.
+ */
+ protected Vector<AccessibleTreeNode> maChildList;
+
+
+ public abstract NodeHandler createHandler (
+ com.sun.star.accessibility.XAccessibleContext xContext);
+
+ public NodeHandler ()
+ {
+ maChildList = new Vector<AccessibleTreeNode> ();
+ }
+
+ /** return the number of children this object has */
+ public int getChildCount()
+ {
+ synchronized (maChildList)
+ {
+ return maChildList.size();
+ }
+ }
+
+ /**
+ * return a child object. Complex
+ * children have to be AccTreeNode instances.
+ * @see AccTreeNode
+ */
+ public AccessibleTreeNode getChild (AccessibleTreeNode aParent, int nIndex)
+ {
+ synchronized (maChildList)
+ {
+ AccessibleTreeNode aChild = maChildList.get(nIndex);
+ if (aChild == null)
+ {
+ aChild = createChild (aParent, nIndex);
+ if (aChild == null)
+ aChild = new StringNode ("could not create child", aParent);
+ maChildList.set (nIndex, aChild);
+ }
+ return aChild;
+ }
+ }
+
+ public AccessibleTreeNode getChildNoCreate (int nIndex)
+ {
+ synchronized (maChildList)
+ {
+ return maChildList.get(nIndex);
+ }
+ }
+
+ /** Remove the specified child from the list of children.
+ */
+ public boolean removeChild (int nIndex)
+ {
+ try
+ {
+ synchronized (maChildList)
+ {
+ System.out.println (" removing child at position " + nIndex + ": "
+ + maChildList.get (nIndex));
+ maChildList.remove (nIndex);
+ }
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public int indexOf (AccessibleTreeNode aNode)
+ {
+ synchronized (maChildList)
+ {
+ return maChildList.indexOf (aNode);
+ }
+ }
+
+ /** Create a child object for the specified data. This method is called
+ usually from getChild and put there into the cache.
+ */
+ public abstract AccessibleTreeNode createChild (
+ AccessibleTreeNode aParent, int nIndex);
+
+
+ // The following methods support editing of children and actions.
+ // They have default implementations for no actions and read-only.
+
+
+ /** get names of supported actions */
+ public String[] getActions (AccessibleTreeNode aNode)
+ {
+ return new String[] {};
+ }
+
+ /** perform action */
+ public void performAction (AccessibleTreeNode aNode, int nIndex)
+ {
+ }
+
+ /** Update all children.
+ */
+ public void update (AccessibleTreeNode aNode)
+ {
+ }
+}
diff --git a/toolkit/test/accessibility/NodeMap.java b/toolkit/test/accessibility/NodeMap.java
new file mode 100644
index 0000000000..045c933713
--- /dev/null
+++ b/toolkit/test/accessibility/NodeMap.java
@@ -0,0 +1,117 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.accessibility.XAccessibleContext;
+
+import java.util.HashMap;
+
+abstract class NodeMapCallback
+{
+ public abstract void Apply (AccTreeNode aNode);
+}
+
+/** This map translates from XAccessible objects to our internal
+ representations.
+*/
+class NodeMap
+{
+ public NodeMap ()
+ {
+ maXAccessibleToNode = new HashMap<XAccessibleContext, AccessibleTreeNode> ();
+ }
+
+ /** Clear the whole map.
+ */
+ public void Clear ()
+ {
+ maXAccessibleToNode.clear();
+ }
+
+ /** @return
+ whether the new node was different from a previous one
+ respectively was the first one set.
+ */
+ public boolean InsertNode (XAccessibleContext xContext, AccessibleTreeNode aNode)
+ {
+ AccessibleTreeNode aPreviousNode = maXAccessibleToNode.put (
+ xContext,
+ aNode);
+ return aPreviousNode != aNode;
+ }
+
+ protected void RemoveNode (AccessibleTreeNode aNode)
+ {
+ try
+ {
+ if ((aNode != null) && (aNode instanceof AccTreeNode))
+ {
+ maXAccessibleToNode.remove (((AccTreeNode)aNode).getContext());
+ }
+ }
+ catch (Exception e)
+ {
+ System.out.println ("caught exception while removing node "
+ + aNode + " : " + e);
+ e.printStackTrace();
+ }
+ }
+
+
+ public void ForEach (NodeMapCallback aFunctor)
+ {
+ Object[] aNodes = maXAccessibleToNode.values().toArray();
+ for (int i=0; i<aNodes.length; i++)
+ {
+ if (aNodes[i] != null && (aNodes[i] instanceof AccTreeNode))
+ {
+ try
+ {
+ aFunctor.Apply ((AccTreeNode)aNodes[i]);
+ }
+ catch (Exception e)
+ {
+ System.out.println ("caught exception applying functor to "
+ + i + "th node " + aNodes[i] + " : " + e);
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ AccessibleTreeNode GetNode (XAccessibleContext xContext)
+ {
+ return maXAccessibleToNode.get (xContext);
+ }
+
+ AccessibleTreeNode GetNode (Object aObject)
+ {
+ if (aObject instanceof XAccessibleContext)
+ return GetNode ((XAccessibleContext)aObject);
+ else
+ return null;
+ }
+
+ boolean ValueIsMember (AccessibleTreeNode aNode)
+ {
+ return maXAccessibleToNode.containsValue(aNode);
+ }
+
+
+
+ private final HashMap<XAccessibleContext, AccessibleTreeNode> maXAccessibleToNode;
+}
diff --git a/toolkit/test/accessibility/OfficeConnection.java b/toolkit/test/accessibility/OfficeConnection.java
new file mode 100644
index 0000000000..357c7c6d18
--- /dev/null
+++ b/toolkit/test/accessibility/OfficeConnection.java
@@ -0,0 +1,98 @@
+/*
+ * 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 .
+ */
+
+// base classes
+import com.sun.star.uno.UnoRuntime;
+
+import com.sun.star.bridge.XUnoUrlResolver;
+import com.sun.star.lang.XMultiServiceFactory;
+
+
+/** @descr This class establishes a connection to a LibreOffice application.
+ */
+public class OfficeConnection
+{
+ public OfficeConnection (int nPortNumber)
+ {
+ mnDefaultPort = nPortNumber;
+ connect ();
+ }
+
+ /** @descr Return the service manager that represents the connected
+ LibreOffice application
+ */
+ public XMultiServiceFactory getServiceManager ()
+ {
+ if ( ! mbInitialized)
+ connect ();
+ return maServiceManager;
+ }
+
+ /** @descr Connect to an already running LibreOffice application.
+ */
+ private void connect ()
+ {
+ connect (msDefaultHost, mnDefaultPort);
+ }
+
+ /** @descr Connect to an already running LibreOffice application that has
+ been started with a command line argument like
+ "--accept=socket,host=localhost,port=5678;urp;"
+ */
+ private void connect (String hostname, int portnumber)
+ {
+ mbInitialized = true;
+ // Set up connection string.
+ String sConnectString = "uno:socket,host=" + hostname + ",port=" + portnumber
+ + ";urp;StarOffice.ServiceManager";
+
+
+ // connect to a running office and get the ServiceManager
+ try
+ {
+ // Create a URL Resolver.
+ XMultiServiceFactory aLocalServiceManager =
+ com.sun.star.comp.helper.Bootstrap.createSimpleServiceManager();
+ XUnoUrlResolver aURLResolver = UnoRuntime.queryInterface (
+ XUnoUrlResolver.class,
+ aLocalServiceManager.createInstance ("com.sun.star.bridge.UnoUrlResolver")
+ );
+
+ maServiceManager = UnoRuntime.queryInterface (
+ XMultiServiceFactory.class,
+ aURLResolver.resolve (sConnectString)
+ );
+ }
+
+ catch (Exception e)
+ {
+ MessageArea.println ("Could not connect with " + sConnectString + " : " + e);
+ MessageArea.println ("Please start LibreOffice with "
+ + "\"--accept=socket,host=localhost,port=5678;urp;\"");
+ }
+ }
+
+ private final int mnDefaultPort;
+ private static final String msDefaultHost = "localhost";
+ private XMultiServiceFactory maServiceManager = null;
+
+ /** A value of true just indicates that it has been tried to establish a connection,
+ not that has been successful.
+ */
+ private boolean mbInitialized = false;
+}
diff --git a/toolkit/test/accessibility/Options.java b/toolkit/test/accessibility/Options.java
new file mode 100644
index 0000000000..6cf6e48f2a
--- /dev/null
+++ b/toolkit/test/accessibility/Options.java
@@ -0,0 +1,122 @@
+/*
+ * 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 .
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+/** Load from and save options into a file.
+*/
+class Options
+ extends Properties
+{
+ public static Options Instance ()
+ {
+ if (saOptions == null)
+ saOptions = new Options ();
+ return saOptions;
+ }
+
+ public static void SetBoolean (String sName, boolean bValue)
+ {
+ Instance().setProperty (sName, Boolean.toString(bValue));
+ }
+
+ public static boolean GetBoolean (String sName)
+ {
+ return Boolean.getBoolean(Instance().getProperty (sName));
+ }
+
+ public static void SetInteger (String sName, int nValue)
+ {
+ Instance().setProperty (sName, Integer.toString(nValue));
+ }
+
+ public static int GetInteger (String sName, int nDefault)
+ {
+ String sValue = Instance().getProperty (sName);
+ if (sValue == null)
+ return nDefault;
+ else
+ return Integer.parseInt (sValue);
+ }
+
+ public void Load (String sBaseName)
+ {
+ FileInputStream fis = null;
+ try
+ {
+ fis = new FileInputStream (ProvideFile(sBaseName));
+ load (fis);
+ }
+ catch (IOException e)
+ {
+ // Ignore a non-existing options file.
+ }
+ finally
+ {
+ try
+ {
+ if (fis != null)
+ fis.close();
+ }
+ catch (IOException ex)
+ {
+ }
+ }
+ }
+
+ public void Save (String sBaseName)
+ {
+ FileOutputStream fos = null;
+ try
+ {
+ fos = new FileOutputStream (ProvideFile(sBaseName));
+ store (fos, null);
+ }
+ catch (IOException e)
+ {
+ }
+ finally
+ {
+ try
+ {
+ if (fos != null)
+ fos.close();
+ }
+ catch (IOException ex)
+ {
+ }
+ }
+ }
+
+ private Options ()
+ {
+ }
+
+ private File ProvideFile (String sBaseName)
+ {
+ return new File (
+ System.getProperty ("user.home"),
+ sBaseName);
+ }
+
+ private static Options saOptions = null;
+}
diff --git a/toolkit/test/accessibility/QueuedListener.java b/toolkit/test/accessibility/QueuedListener.java
new file mode 100644
index 0000000000..a34b335497
--- /dev/null
+++ b/toolkit/test/accessibility/QueuedListener.java
@@ -0,0 +1,70 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.accessibility.*;
+import com.sun.star.lang.EventObject;
+import com.sun.star.uno.*;
+
+class QueuedListener
+ implements XAccessibleEventListener
+{
+ public QueuedListener (EventListener aListener)
+ {
+ maListener = aListener;
+ }
+
+
+ public void disposing( final EventObject aEvent)
+ {
+ XAccessibleContext xContext = UnoRuntime.queryInterface(
+ XAccessibleContext.class, aEvent.Source);
+ if (xContext == null)
+ {
+ XAccessible xAccessible = UnoRuntime.queryInterface(
+ XAccessible.class, aEvent.Source);
+ if (xAccessible != null)
+ xContext = xAccessible.getAccessibleContext();
+ }
+ final XAccessibleContext xSource = xContext;
+ EventQueue.Instance().addDisposingEvent (new Runnable()
+ {
+ public void run()
+ {
+ if (QueuedListener.this.maListener != null)
+ QueuedListener.this.maListener.disposing (xSource);
+ }
+ }
+ );
+ }
+
+ public void notifyEvent( final AccessibleEventObject aEvent )
+ {
+ EventQueue.Instance().addEvent (new Runnable()
+ {
+ public void run()
+ {
+ QueuedListener.this.maListener.notifyEvent( aEvent );
+ }
+ }
+ );
+ }
+
+ private final EventListener maListener;
+}
+
+
diff --git a/toolkit/test/accessibility/QueuedTopWindowListener.java b/toolkit/test/accessibility/QueuedTopWindowListener.java
new file mode 100644
index 0000000000..2ac5c7849d
--- /dev/null
+++ b/toolkit/test/accessibility/QueuedTopWindowListener.java
@@ -0,0 +1,97 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.awt.XTopWindowListener;
+import com.sun.star.lang.EventObject;
+
+class QueuedTopWindowListener
+ implements XTopWindowListener
+{
+ public QueuedTopWindowListener (TopWindowListener aListener)
+ {
+ maListener = aListener;
+ }
+
+ public void windowOpened (final com.sun.star.lang.EventObject aEvent) throws RuntimeException
+ {
+ EventQueue.Instance().addEvent (new Runnable()
+ {
+ public void run()
+ {
+ QueuedTopWindowListener.this.maListener.windowOpened (aEvent);
+ }
+ }
+ );
+ }
+
+ public void windowClosing (final com.sun.star.lang.EventObject aEvent) throws RuntimeException
+ {
+ // Ignored.
+ }
+
+ public void windowClosed (final com.sun.star.lang.EventObject aEvent) throws RuntimeException
+ {
+ EventQueue.Instance().addEvent (new Runnable()
+ {
+ public void run()
+ {
+ QueuedTopWindowListener.this.maListener.windowClosed (aEvent);
+ }
+ }
+ );
+ }
+
+ public void windowMinimized (final com.sun.star.lang.EventObject aEvent)
+ throws RuntimeException
+ {
+ System.out.println ("QueuedTopWindowListener: Top window minimized: " + aEvent);
+ }
+
+ public void windowNormalized (final com.sun.star.lang.EventObject aEvent)
+ throws RuntimeException
+ {
+ System.out.println ("QueuedTopWindowListener: Top window normalized: " + aEvent);
+ }
+
+ public void windowActivated (final com.sun.star.lang.EventObject aEvent)
+ throws RuntimeException
+ {
+ System.out.println ("QueuedTopWindowListener: Top window activated: " + aEvent);
+ }
+
+ public void windowDeactivated (final com.sun.star.lang.EventObject aEvent)
+ throws RuntimeException
+ {
+ System.out.println ("QueuedTopWindowListener: Top window deactivated: " + aEvent);
+ }
+
+ public void disposing( final EventObject aEvent)
+ {
+ EventQueue.Instance().addDisposingEvent (new Runnable()
+ {
+ public void run()
+ {
+ if (QueuedTopWindowListener.this.maListener != null)
+ QueuedTopWindowListener.this.maListener.disposing (aEvent);
+ }
+ }
+ );
+ }
+
+ private final TopWindowListener maListener;
+}
diff --git a/toolkit/test/accessibility/SelectionDialog.java b/toolkit/test/accessibility/SelectionDialog.java
new file mode 100644
index 0000000000..2f0c6d5434
--- /dev/null
+++ b/toolkit/test/accessibility/SelectionDialog.java
@@ -0,0 +1,203 @@
+/*
+ * 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 .
+ */
+
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Vector;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.ListSelectionModel;
+
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleSelection;
+import com.sun.star.lang.IndexOutOfBoundsException;
+
+/**
+ * Display a dialog with a list-box of children and select/deselect buttons
+ */
+class SelectionDialog extends JDialog
+ implements ActionListener
+{
+ public SelectionDialog (AccTreeNode aNode)
+ {
+ super (AccessibilityWorkBench.Instance());
+
+ maNode = aNode;
+
+ Layout();
+ }
+
+ /** build dialog */
+ private void Layout ()
+ {
+ setTitle( "Select" );
+
+ // vertical stacking of the elements
+ Container aContent = getContentPane();
+
+ // label with explanation
+ aContent.add( new JLabel( "Select/Deselect child elements" ),
+ BorderLayout.NORTH );
+
+ // the JListBox
+ maChildrenSelector = new JList (GetChildrenList());
+ maChildrenSelector.setPreferredSize (new Dimension (500,300));
+ aContent.add (maChildrenSelector, BorderLayout.CENTER);
+ maChildrenSelector.setSelectionMode (ListSelectionModel.SINGLE_SELECTION);
+
+ JPanel aButtons = new JPanel();
+ aButtons.setLayout( new FlowLayout() );
+
+ JButton aButton;
+
+ aButton = new JButton( "Select" );
+ aButton.setActionCommand( "Select" );
+ aButton.addActionListener( this );
+ aButtons.add( aButton );
+
+ aButton = new JButton( "Deselect" );
+ aButton.setActionCommand( "Deselect" );
+ aButton.addActionListener( this );
+ aButtons.add( aButton );
+
+ aButton = new JButton( "Select all" );
+ aButton.setActionCommand( "Select all" );
+ aButton.addActionListener( this );
+ aButtons.add( aButton );
+
+ aButton = new JButton( "Clear Selection" );
+ aButton.setActionCommand( "Clear Selection" );
+ aButton.addActionListener( this );
+ aButtons.add( aButton );
+
+ aButton = new JButton( "Close" );
+ aButton.setActionCommand( "Close" );
+ aButton.addActionListener( this );
+ aButtons.add( aButton );
+
+ // add Panel with buttons
+ aContent.add( aButtons, BorderLayout.SOUTH );
+
+ setSize( getPreferredSize() );
+ }
+
+ /** Get a list of all children
+ */
+ private Vector<String> GetChildrenList ()
+ {
+ mxSelection = maNode.getSelection();
+
+ XAccessibleContext xContext = maNode.getContext();
+ int nCount = xContext.getAccessibleChildCount();
+ Vector<String> aChildVector = new Vector<String>();
+ for(int i = 0; i < nCount; i++)
+ {
+ try
+ {
+ XAccessible xChild = xContext.getAccessibleChild(i);
+ XAccessibleContext xChildContext = xChild.getAccessibleContext();
+ aChildVector.add( i + " " + xChildContext.getAccessibleName());
+ }
+ catch( IndexOutOfBoundsException e )
+ {
+ aChildVector.add( "ERROR: IndexOutOfBoundsException" );
+ }
+ }
+ return aChildVector;
+ }
+
+
+ private void close ()
+ {
+ setVisible(false);
+ dispose();
+ }
+
+ private void select()
+ {
+ try
+ {
+ mxSelection.selectAccessibleChild (maChildrenSelector.getSelectedIndex());
+ }
+ catch( IndexOutOfBoundsException e )
+ {
+ JOptionPane.showMessageDialog( AccessibilityWorkBench.Instance(),
+ "Can't select: IndexOutofBounds",
+ "Error in selectAccessibleChild",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+ private void deselect()
+ {
+ try
+ {
+ mxSelection.deselectAccessibleChild(
+ maChildrenSelector.getSelectedIndex());
+ }
+ catch( IndexOutOfBoundsException e )
+ {
+ JOptionPane.showMessageDialog( AccessibilityWorkBench.Instance(),
+ "Can't deselect: IndexOutofBounds",
+ "Error in deselectAccessibleChild",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+ private void selectAll()
+ {
+ mxSelection.selectAllAccessibleChildren();
+ }
+
+ private void clearSelection()
+ {
+ mxSelection.clearAccessibleSelection();
+ }
+
+
+
+ public void actionPerformed(ActionEvent e)
+ {
+ String sCommand = e.getActionCommand();
+
+ if( "Close".equals( sCommand ) )
+ close();
+ else if ( "Select".equals( sCommand ) )
+ select();
+ else if ( "Deselect".equals( sCommand ) )
+ deselect();
+ else if ( "Clear Selection".equals( sCommand ) )
+ clearSelection();
+ else if ( "Select all".equals( sCommand ) )
+ selectAll();
+ }
+
+ private JList maChildrenSelector;
+ private XAccessibleSelection mxSelection;
+ private final AccTreeNode maNode;
+}
diff --git a/toolkit/test/accessibility/SimpleOffice.java b/toolkit/test/accessibility/SimpleOffice.java
new file mode 100644
index 0000000000..ecb16a6e38
--- /dev/null
+++ b/toolkit/test/accessibility/SimpleOffice.java
@@ -0,0 +1,139 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.frame.XDesktop;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XInterface;
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.awt.XExtendedToolkit;
+
+
+/** This class tries to simplify some tasks like loading a document or
+ getting various objects.
+*/
+public class SimpleOffice
+{
+ private XDesktop mxDesktop = null;
+ private OfficeConnection aConnection;
+ private int mnPortNumber;
+
+ public SimpleOffice (int nPortNumber)
+ {
+ mnPortNumber = nPortNumber;
+ connect ();
+ getDesktop ();
+ }
+
+ public void connect ()
+ {
+ aConnection = new OfficeConnection (mnPortNumber);
+ mxDesktop = null;
+ getDesktop ();
+ }
+
+
+
+
+
+
+
+
+
+
+
+ public XDesktop getDesktop ()
+ {
+ if (mxDesktop != null)
+ return mxDesktop;
+ try
+ {
+ // Get the factory of the connected office.
+ XMultiServiceFactory xMSF = aConnection.getServiceManager ();
+ if (xMSF == null)
+ {
+ MessageArea.println ("can't connect to office");
+ return null;
+ }
+ else
+ MessageArea.println ("Connected successfully.");
+
+ // Create a new desktop.
+ mxDesktop = UnoRuntime.queryInterface(
+ XDesktop.class,
+ xMSF.createInstance ("com.sun.star.frame.Desktop")
+ );
+ }
+ catch (Exception e)
+ {
+ MessageArea.println ("caught exception while creating desktop: "
+ + e);
+ }
+
+ return mxDesktop;
+ }
+
+
+ /** Return a reference to the extended toolkit which is a broadcaster of
+ top window, key, and focus events.
+ */
+ public XExtendedToolkit getExtendedToolkit ()
+ {
+ XExtendedToolkit xToolkit = null;
+ try
+ {
+ // Get the factory of the connected office.
+ XMultiServiceFactory xMSF = aConnection.getServiceManager ();
+ if (xMSF != null)
+ {
+ xToolkit = UnoRuntime.queryInterface(
+ XExtendedToolkit.class,
+ xMSF.createInstance ("stardiv.Toolkit.VCLXToolkit")
+ );
+ }
+ }
+ catch (Exception e)
+ {
+ MessageArea.println ("caught exception while creating extended toolkit: " + e);
+ }
+
+ return xToolkit;
+ }
+
+
+
+ public XAccessible getAccessibleObject (XInterface xObject)
+ {
+ XAccessible xAccessible = null;
+ try
+ {
+ xAccessible = UnoRuntime.queryInterface(
+ XAccessible.class, xObject);
+ }
+ catch (Exception e)
+ {
+ MessageArea.println (
+ "caught exception while getting accessible object" + e);
+ e.printStackTrace();
+ }
+ return xAccessible;
+ }
+
+
+
+}
diff --git a/toolkit/test/accessibility/StringNode.java b/toolkit/test/accessibility/StringNode.java
new file mode 100644
index 0000000000..f6660e44a9
--- /dev/null
+++ b/toolkit/test/accessibility/StringNode.java
@@ -0,0 +1,36 @@
+/*
+ * 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 .
+ */
+
+
+
+/**
+ Base class for all tree nodes.
+ */
+class StringNode
+ extends AccessibleTreeNode
+{
+ public StringNode (String aDisplayObject, AccessibleTreeNode aParent)
+ {
+ super (aDisplayObject, aParent);
+ }
+
+ @Override
+ public int indexOf(AccessibleTreeNode aNode) {
+ return -1;
+ }
+}
diff --git a/toolkit/test/accessibility/TableEventHandler.java b/toolkit/test/accessibility/TableEventHandler.java
new file mode 100644
index 0000000000..09a3adbbc3
--- /dev/null
+++ b/toolkit/test/accessibility/TableEventHandler.java
@@ -0,0 +1,58 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.accessibility.AccessibleEventObject;
+import com.sun.star.accessibility.AccessibleEventId;
+import com.sun.star.accessibility.AccessibleTableModelChange;
+import java.io.PrintStream;
+
+class TableEventHandler
+ extends EventHandler
+{
+ public TableEventHandler (AccessibleEventObject aEvent, AccessibilityTreeModel aTreeModel)
+ {
+ super (aEvent, aTreeModel);
+ }
+
+ @Override
+ public void PrintOldAndNew (PrintStream out)
+ {
+ switch (mnEventId)
+ {
+ case AccessibleEventId.TABLE_MODEL_CHANGED:
+ AccessibleTableModelChange aModelChange =
+ (AccessibleTableModelChange)maEvent.NewValue;
+ out.println( "Range: StartRow " + aModelChange.FirstRow +
+ " StartColumn " + aModelChange.FirstColumn +
+ " EndRow " + aModelChange.LastRow +
+ " EndColumn " + aModelChange.LastColumn +
+ " Id " + aModelChange.Type);
+ break;
+ default:
+ super.PrintOldAndNew (out);
+ }
+ }
+
+ @Override
+ public void Process ()
+ {
+ maTreeModel.updateNode (mxEventSource, AccessibleTableHandler.class);
+ }
+
+
+}
diff --git a/toolkit/test/accessibility/TopWindowListener.java b/toolkit/test/accessibility/TopWindowListener.java
new file mode 100644
index 0000000000..a35b51a5ff
--- /dev/null
+++ b/toolkit/test/accessibility/TopWindowListener.java
@@ -0,0 +1,175 @@
+/*
+ * 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 .
+ */
+
+import com.sun.star.awt.XWindow;
+import com.sun.star.awt.XExtendedToolkit;
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.uno.UnoRuntime;
+
+/** Listen for top window events and create or delete children of the tree
+ model accordingly.
+*/
+class TopWindowListener
+{
+ TopWindowListener (AccessibilityTreeModel aModel, SimpleOffice aOffice)
+ {
+ maModel = aModel;
+ maOffice = aOffice;
+ }
+
+
+
+
+ /** Use this function to initially fill the accessibility object tree
+ view with nodes for top level windows.
+ */
+ public void Initialize ()
+ {
+ XExtendedToolkit xToolkit = maOffice.getExtendedToolkit();
+ if (xToolkit != null)
+ {
+ maModel.lock ();
+ int nTopWindowCount = xToolkit.getTopWindowCount();
+ MessageArea.println ("There are " + nTopWindowCount + " top windows.");
+ for (int i=0; i<nTopWindowCount; i++)
+ {
+ try
+ {
+ XAccessible xAccessible = maOffice.getAccessibleObject(
+ xToolkit.getTopWindow (i));
+ // Uncomment the following line to get the real root of
+ // the accessible tree that xAccessible belongs to.
+ // xAccessible = maOffice.getAccessibleRoot(xAccessible);
+ AddTopLevelNode (xAccessible);
+ }
+ catch (Exception e)
+ {
+ System.out.println ("caught exception: " + e);
+ e.printStackTrace();
+ }
+ }
+ maModel.unlock ((AccessibleTreeNode)maModel.getRoot());
+ }
+ }
+
+
+
+ /** Add a new top level node which, to be exact, will be placed on the
+ second layer of the tree.
+ @param xNewTopLevelObject
+ The accessible object of the new top level window.
+ */
+ private void AddTopLevelNode (XAccessible xNewTopLevelObject)
+ {
+ System.out.println ("adding top level window");
+ if (xNewTopLevelObject != null)
+ {
+ XAccessibleContext xContext = xNewTopLevelObject.getAccessibleContext();
+ if (xContext == null)
+ System.out.println ("top level window not accessible");
+ else
+ {
+ Object aRootObject = maModel.getRoot();
+ if (aRootObject instanceof VectorNode)
+ {
+ VectorNode aRoot = (VectorNode) aRootObject;
+ AccessibleTreeNode aNode =
+ NodeFactory.Instance().createDefaultNode (xNewTopLevelObject, aRoot);
+ aRoot.addChild (aNode);
+ maModel.fireTreeNodesInserted (maModel.createEvent (aRoot, aNode));
+ }
+ }
+ }
+ }
+
+ /** Remove an existing top level node from the tree.
+ @param xNewTopLevelObject
+ The accessible object to remove.
+ */
+ private void RemoveTopLevelNode (XAccessible xTopLevelObject)
+ {
+ Object aObject = maModel.getRoot();
+ if (aObject instanceof VectorNode && xTopLevelObject != null)
+ {
+ System.out.println ("removing node " + xTopLevelObject);
+ maModel.removeNode (xTopLevelObject.getAccessibleContext());
+ }
+ }
+
+
+
+
+
+ // XTopWindowListener
+ public void windowOpened (final com.sun.star.lang.EventObject aEvent)
+ throws RuntimeException
+ {
+ if (maModel != null)
+ {
+ XWindow xWindow = UnoRuntime.queryInterface(
+ XWindow.class, aEvent.Source);
+ if (xWindow == null)
+ System.out.println ("event source is no XWindow");
+ else
+ {
+ XAccessible xAccessible = maOffice.getAccessibleObject(xWindow);
+ if (xAccessible == null)
+ System.out.println ("event source is no XAccessible");
+ else
+ AddTopLevelNode (xAccessible);
+ }
+ }
+ }
+
+
+
+
+ public void windowClosed (final com.sun.star.lang.EventObject aEvent)
+ throws RuntimeException
+ {
+ if (maModel != null)
+ {
+ XWindow xWindow = UnoRuntime.queryInterface(
+ XWindow.class, aEvent.Source);
+ if (xWindow == null)
+ System.out.println ("event source is no XWindow");
+ else
+ {
+ XAccessible xAccessible = maOffice.getAccessibleObject(xWindow);
+ if (xAccessible == null)
+ System.out.println ("event source is no XAccessible");
+ else
+ RemoveTopLevelNode (xAccessible);
+ }
+ }
+ }
+
+ public void disposing (final com.sun.star.lang.EventObject aEvent)
+ {
+ System.out.println ("Top window disposed: " + aEvent);
+ }
+
+
+
+
+ private final AccessibilityTreeModel
+ maModel;
+ private final SimpleOffice
+ maOffice;
+}
diff --git a/toolkit/test/accessibility/VectorNode.java b/toolkit/test/accessibility/VectorNode.java
new file mode 100644
index 0000000000..c1ffcd6504
--- /dev/null
+++ b/toolkit/test/accessibility/VectorNode.java
@@ -0,0 +1,74 @@
+/*
+ * 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 .
+ */
+
+import java.util.ArrayList;
+
+import com.sun.star.lang.IndexOutOfBoundsException;
+
+/** The VectorNode class is a simple container whose list of children is
+ managed entirely by its owner.
+*/
+class VectorNode
+ extends StringNode
+{
+ private final ArrayList<AccessibleTreeNode> maChildren;
+
+ public VectorNode (String sDisplayObject, AccessibleTreeNode aParent)
+ {
+ super (sDisplayObject, aParent);
+
+ maChildren = new ArrayList<AccessibleTreeNode> ();
+ }
+
+ public void addChild (AccessibleTreeNode aChild)
+ {
+ maChildren.add (aChild);
+ }
+
+ @Override
+ public int getChildCount ()
+ {
+ return maChildren.size();
+ }
+
+ @Override
+ public AccessibleTreeNode getChild (int nIndex)
+ throws IndexOutOfBoundsException
+ {
+ return maChildren.get(nIndex);
+ }
+
+ @Override
+ public boolean removeChild (int nIndex)
+ throws IndexOutOfBoundsException
+ {
+ return maChildren.remove (nIndex) != null;
+ }
+
+ @Override
+ public int indexOf (AccessibleTreeNode aNode)
+ {
+ return maChildren.indexOf (aNode);
+ }
+
+ @Override
+ public boolean isLeaf()
+ {
+ return maChildren.isEmpty();
+ }
+}
diff --git a/toolkit/test/accessibility/about.html b/toolkit/test/accessibility/about.html
new file mode 100644
index 0000000000..ff24ed0586
--- /dev/null
+++ b/toolkit/test/accessibility/about.html
@@ -0,0 +1,8 @@
+<html>
+<body>
+<center><h1>About AWB</h1>
+<p>AWB, the <em>A</em>ccessibility <em>W</em>ork <em>B</em>ench.</p>
+<p>Version 1.7</p>
+</center>
+</body>
+</html> \ No newline at end of file
diff --git a/toolkit/test/accessibility/help.html b/toolkit/test/accessibility/help.html
new file mode 100644
index 0000000000..681fcead46
--- /dev/null
+++ b/toolkit/test/accessibility/help.html
@@ -0,0 +1,91 @@
+<html><body bgcolor="#fffaf0">
+<h1>Help for the AWB v1.7</h1>
+
+<p>The AWB, or <em>A</em>ccessibility <em>W</em>ork <em>B</em>ench, is a tool
+for testing the implementation UNO Accessibility API.</p>
+
+<p>The main window is roughly divided into three areas:
+<ul>
+<li>The <a href="#treeview">tree view</a> on the left shows a part of the
+accessibility tree of one or more StarOffice/OpenOffice applications.</li>
+<li>The <a href="#graphicalview">graphical view</a> on the right side shows
+a graphical representation of the accessibility objects in the tree. To
+make objects missing in the graphical view visible expand the corresponding
+nodes in the tree view.</li>
+
+<li>The text window at the bottom logs important messages.</li>
+</ul>
+</p>
+
+<h2><a name="treeview">Tree View</a></h2>
+<p>The tree view has a top-level node for every open
+ document window of StarOffice/OpenOffice. Expand those nodes to make them
+ visible in the <a href="#graphicalview">graphical view</a>.</p>
+
+<h3>Nodes</h3>
+<p>The nodes in the tree view belong to different classes, some of which
+ have children others do not:
+<ul>
+<li><b>Accessible Object</b><br>
+ The node represents an accessible object and has corresponding shape in
+ the graphical view. Only this kind of node gets highlighted by clicking
+ on those shapes.</li>
+<li><b>Simple Property</b><br>
+ These leaves represent simple properties of their parent nodes. Examples
+ are the position, size, and color of an accessible object.</li>
+<li><b>Complex Properties</b><br>
+ These nodes have children that are not accessible objects. Examples are
+ the lists of interfaces or services supported by an accessible object.</li>
+</ul>
+</p>
+
+<h3>Actions</h3>
+<p>The tree view supports the following actions:
+<ul><li>Left double click expands the node under the mouse pointer.</li>
+<li>Right click shows a context menu. Entries, when supported, are:
+<ul>
+<li><b>Expand Shapes</b><br>
+Expands all nodes in the sub-tree that lie on a path from the root to a shape.</li>
+<li><b>Expand Subtree</b><br>
+Expands all nodes in the sub-tree.</li>
+<li><b>Select...</b><br>
+Show a dialog that gives access to the XAccessibleSelection interface.</li>
+<li><b>select...</b>, <b>copy...</b>, <b>cut...</b>, <b>paste...</b>,
+ <b>edit...</b>, <b>format...</b><br>
+Show dialogs that give access to the XAccessibleText and
+XAccessibleEditableText interfaces.
+</ul></li>
+</ul>
+</p>
+
+
+
+<h2><a name="graphicalview">Graphical View</a></h2>
+<p>The graphical view shows several properties of accessibility objects:
+<ul>
+<li>The bounding box is represented as a rectangle.</li>
+<li>The background color of the accessible object is taken to draw the
+ bounding box rectangle.</li>
+<li>The foreground color is used to fill the bounding box.</li>
+<li>The accessible name is shown when the menu checkbox Options->Show Name
+ is check.</li>
+<li>The accessible description is shown when the menu checkbox Options->Show
+ Descriptions is checked.</li>
+<li>If the XAccessibleText interface is supported and the menu checkbox
+ Options->Show Text is checked then the text of the accessible object is
+ shown.</li>
+</ul>
+</p>
+
+<h3>Actions</h3>
+<p>The graphical view supports three the following actions:
+<ul>
+<li>Left click (no modifiers) highlights the object under the mouse as well
+ as the corresponding node in the tree view.</li>
+<li>Left click with Control modifier expands the object under the
+ mouse.</li>
+<li>Mouse motion with Shift modifier highlights the object under the mouse
+ as well as the corresponding node in the tree view.</li>
+</ul>
+
+</body></html>
diff --git a/toolkit/test/accessibility/jawb.mf b/toolkit/test/accessibility/jawb.mf
new file mode 100644
index 0000000000..88aa2cc765
--- /dev/null
+++ b/toolkit/test/accessibility/jawb.mf
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Main-Class: AccessibilityWorkBench
+Class-Path: classes.jar libreoffice.jar java_uno.jar xt.jar xml-apis.jar
diff --git a/toolkit/test/accessibility/news.html b/toolkit/test/accessibility/news.html
new file mode 100644
index 0000000000..7b5336ea45
--- /dev/null
+++ b/toolkit/test/accessibility/news.html
@@ -0,0 +1,36 @@
+<html><body bgcolor="#fffaf0">
+<h1>News for AWB v1.7.2</h1>
+<p>Adaptation to recent UAA changes:
+<ul>
+<li>Introduction of
+com.sun.star.accessibility.TextSegment structure that is returned by some
+functions of the XAccessibleText interface.</li>
+<li>Removal of the COLLAPSED state.</li>
+<li>Renaming of XAccessibleSelectioni::selectAllAccessible to
+selectAllAccessibleChildren.</li>
+</ul>
+
+<h1>News for AWB v1.7</h1>
+
+<ul>
+
+<li>This help window.</li>
+
+<li>Integrated relocation of UAA files from drafts to final.</li>
+<li>Control left click in the graphical view expands the object that has
+ been clicked at.</li>
+
+<li>Introduction of split panes for easily changing the size of the three
+main widgets.</li>
+
+<li>The graphical view visualizes the screen size.</li>
+
+<li>Removed the "Load" button.</li>
+<li>Removed the status line.</li>
+<li>The tree view shows top level nodes only for document windows.</li>
+<li>New "views" menu that allows you to select the zoom scale of the
+ graphical view.</li>
+
+</ul>
+
+</body></html> \ No newline at end of file
diff --git a/toolkit/test/accessibility/ov/ContextView.java b/toolkit/test/accessibility/ov/ContextView.java
new file mode 100644
index 0000000000..0dc97a67a7
--- /dev/null
+++ b/toolkit/test/accessibility/ov/ContextView.java
@@ -0,0 +1,140 @@
+/*
+ * 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 .
+ */
+
+package ov;
+
+import java.awt.Color;
+import java.awt.GridBagLayout;
+import java.awt.GridBagConstraints;
+
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+
+import javax.swing.JLabel;
+import com.sun.star.accessibility.AccessibleEventId;
+import com.sun.star.accessibility.AccessibleEventObject;
+import com.sun.star.accessibility.XAccessibleContext;
+
+import tools.NameProvider;
+
+public class ContextView
+ extends ListeningObjectView
+ implements ActionListener
+{
+ public static ObjectView Create (
+ ObjectViewContainer aContainer,
+ XAccessibleContext xContext)
+ {
+ System.out.println ("ContextView.CreateView");
+ if (xContext != null)
+ return new ContextView (aContainer);
+ else
+ return null;
+ }
+
+ private ContextView (ObjectViewContainer aContainer)
+ {
+ super (aContainer);
+ JLabel aNameLabel = new JLabel ("Name: ");
+ maName = new JLabel ("");
+ JLabel aDescriptionLabel = new JLabel ("Description: ");
+ maDescription = new JLabel ("");
+ JLabel maRoleLabel = new JLabel ("Role: ");
+ maRole = new JLabel ("");
+
+ // Make the background of name and description white and opaque so
+ // that leading and trailing spaces become visible.
+ maName.setOpaque (true);
+ maName.setBackground (Color.WHITE);
+ maDescription.setOpaque (true);
+ maDescription.setBackground (Color.WHITE);
+ maRole.setOpaque (true);
+ maRole.setBackground (Color.WHITE);
+
+ GridBagLayout aLayout = new GridBagLayout();
+ setLayout (aLayout);
+ GridBagConstraints constraints = new GridBagConstraints ();
+ constraints.gridx = 0;
+ constraints.gridy = 0;
+ constraints.gridwidth = 1;
+ constraints.gridheight = 1;
+ constraints.weightx = 0;
+ constraints.weighty = 1;
+ constraints.anchor = GridBagConstraints.WEST;
+ constraints.fill = GridBagConstraints.NONE;
+ add (aNameLabel, constraints);
+ constraints.gridy = 1;
+ add (aDescriptionLabel, constraints);
+ constraints.gridy = 2;
+ add (maRoleLabel, constraints);
+ constraints.gridy = 0;
+ constraints.gridx = 1;
+ constraints.weightx = 2;
+ add (maName, constraints);
+ constraints.gridy = 1;
+ add (maDescription, constraints);
+ constraints.gridy = 2;
+ add (maRole, constraints);
+ }
+
+ @Override
+ public void Update ()
+ {
+ if (mxContext == null)
+ {
+ maName.setText ("<null object>");
+ maDescription.setText ("<null object>");
+ maRole.setText ("<null object>");
+ }
+ else
+ {
+ maName.setText (mxContext.getAccessibleName());
+ maDescription.setText (mxContext.getAccessibleDescription());
+ maRole.setText (NameProvider.getRoleName (mxContext.getAccessibleRole()));
+ }
+ }
+
+ @Override
+ public String GetTitle ()
+ {
+ return "Context";
+ }
+
+ /** Listen for changes regarding displayed values.
+ */
+ @Override
+ public void notifyEvent (AccessibleEventObject aEvent)
+ {
+ switch (aEvent.EventId)
+ {
+ case AccessibleEventId.NAME_CHANGED :
+ case AccessibleEventId.DESCRIPTION_CHANGED :
+ Update ();
+ }
+ }
+
+ public void actionPerformed (ActionEvent aEvent)
+ {
+ }
+
+
+ private final JLabel
+ maName,
+ maDescription,
+ maRole;
+}
diff --git a/toolkit/test/accessibility/ov/FocusView.java b/toolkit/test/accessibility/ov/FocusView.java
new file mode 100644
index 0000000000..0428403f80
--- /dev/null
+++ b/toolkit/test/accessibility/ov/FocusView.java
@@ -0,0 +1,140 @@
+/*
+ * 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 .
+ */
+
+package ov;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+
+import com.sun.star.accessibility.AccessibleEventId;
+import com.sun.star.accessibility.AccessibleEventObject;
+import com.sun.star.accessibility.AccessibleStateType;
+import com.sun.star.accessibility.XAccessibleComponent;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.uno.UnoRuntime;
+
+public class FocusView
+ extends ListeningObjectView
+ implements ActionListener
+{
+ /** Create a FocusView when the given object supports the
+ XAccessibleComponent interface.
+ */
+ public static ObjectView Create (
+ ObjectViewContainer aContainer,
+ XAccessibleContext xContext)
+ {
+ XAccessibleComponent xComponent = UnoRuntime.queryInterface(
+ XAccessibleComponent.class, xContext);
+ if (xComponent != null)
+ return new FocusView (aContainer);
+ else
+ return null;
+ }
+
+ private FocusView (ObjectViewContainer aContainer)
+ {
+ super (aContainer);
+
+ setLayout (new GridBagLayout());
+ GridBagConstraints aConstraints = new GridBagConstraints ();
+
+ maFocused = new JLabel ();
+ aConstraints.gridy = 0;
+ aConstraints.weightx = 1;
+ aConstraints.fill = GridBagConstraints.HORIZONTAL;
+ add (maFocused, aConstraints);
+
+ maGrabFocus = new JButton ("grabFocus");
+ aConstraints.gridy = 1;
+ aConstraints.fill = GridBagConstraints.NONE;
+ aConstraints.anchor = GridBagConstraints.WEST;
+ add (maGrabFocus, aConstraints);
+
+ maGrabFocus.addActionListener (this);
+ }
+
+ /** Additionally to the context store a reference to the
+ XAccessibleComponent interface.
+ */
+ @Override
+ public void SetObject (XAccessibleContext xObject)
+ {
+ mxComponent = UnoRuntime.queryInterface(
+ XAccessibleComponent.class, xObject);
+ super.SetObject (xObject);
+ }
+
+ @Override
+ synchronized public void Destroy ()
+ {
+ super.Destroy();
+ maGrabFocus.removeActionListener (this);
+ }
+
+ @Override
+ synchronized public void Update ()
+ {
+ if (mxContext == null)
+ {
+ maFocused.setText ("<null object>");
+ maGrabFocus.setEnabled (false);
+ }
+ else
+ {
+ long aStateSet = mxContext.getAccessibleStateSet();
+ if (aStateSet & AccessibleStateType.FOCUSED)
+ maFocused.setText ("focused");
+ else
+ maFocused.setText ("not focused");
+ if (maGrabFocus != null)
+ maGrabFocus.setEnabled (true);
+ }
+ }
+
+ @Override
+ public String GetTitle ()
+ {
+ return "Focus";
+ }
+
+ synchronized public void actionPerformed (ActionEvent aEvent)
+ {
+ if (aEvent.getActionCommand().equals("grabFocus"))
+ {
+ mxComponent.grabFocus();
+ }
+ }
+
+ @Override
+ public void notifyEvent (AccessibleEventObject aEvent)
+ {
+ System.out.println (aEvent);
+ if (aEvent.EventId == AccessibleEventId.STATE_CHANGED)
+ Update ();
+ }
+
+ private final JLabel maFocused;
+ private final JButton maGrabFocus;
+ private XAccessibleComponent mxComponent;
+}
diff --git a/toolkit/test/accessibility/ov/ListeningObjectView.java b/toolkit/test/accessibility/ov/ListeningObjectView.java
new file mode 100644
index 0000000000..63b5f8ff7a
--- /dev/null
+++ b/toolkit/test/accessibility/ov/ListeningObjectView.java
@@ -0,0 +1,80 @@
+/*
+ * 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 .
+ */
+
+package ov;
+
+import com.sun.star.accessibility.AccessibleEventObject;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.accessibility.XAccessibleEventBroadcaster;
+import com.sun.star.accessibility.XAccessibleEventListener;
+import com.sun.star.lang.EventObject;
+import com.sun.star.uno.UnoRuntime;
+
+/** Base class for object views that registers as accessibility event
+ listener.
+*/
+abstract class ListeningObjectView
+ extends ObjectView
+ implements XAccessibleEventListener
+{
+ public ListeningObjectView (ObjectViewContainer aContainer)
+ {
+ super (aContainer);
+ }
+
+ /** Add this object as event listener at the broadcasting
+ accessible object.
+ */
+ @Override
+ public void SetObject (XAccessibleContext xContext)
+ {
+ super.SetObject (xContext);
+ XAccessibleEventBroadcaster xBroadcaster =
+ UnoRuntime.queryInterface(
+ XAccessibleEventBroadcaster.class, xContext);
+ if (xBroadcaster != null)
+ xBroadcaster.addAccessibleEventListener (this);
+ }
+
+
+ /** Remove this object as event listener from the broadcasting
+ accessible object.
+ */
+ @Override
+ public void Destroy ()
+ {
+ super.Destroy ();
+ XAccessibleEventBroadcaster xBroadcaster =
+ UnoRuntime.queryInterface(
+ XAccessibleEventBroadcaster.class, mxContext);
+ if (xBroadcaster != null)
+ xBroadcaster.removeAccessibleEventListener (this);
+ }
+
+ /** Derived classes have to implement this method to handle incoming
+ events.
+ */
+ abstract public void notifyEvent (AccessibleEventObject aEvent);
+
+ /** The disposing event is ignored per default. If a derived class is
+ interested it can overwrite this method.
+ */
+ public void disposing (EventObject aEvent)
+ {
+ }
+}
diff --git a/toolkit/test/accessibility/ov/ObjectView.java b/toolkit/test/accessibility/ov/ObjectView.java
new file mode 100644
index 0000000000..7e1570b62b
--- /dev/null
+++ b/toolkit/test/accessibility/ov/ObjectView.java
@@ -0,0 +1,80 @@
+/*
+ * 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 .
+ */
+
+package ov;
+
+import javax.swing.JPanel;
+
+import com.sun.star.accessibility.XAccessibleContext;
+
+/** This is the base class for all object views that can be placed inside an
+ object view container.
+
+ <p>When provided with a new accessible object the container will call
+ the Create method to create a new instance when certain conditions are
+ met. It then calls SetObject to pass the object to the instance.
+ Finally it calls Update.</p>
+
+ <p>The SetObject and Update methods may be called for a new object
+ without calling Create first. In this way an existing instance is
+ recycled.</p>
+*/
+abstract public class ObjectView
+ extends JPanel
+{
+ public ObjectView (ObjectViewContainer aContainer)
+ {
+ mxContext = null;
+ }
+
+ /** Call this when you want the object to be destroyed. Release all
+ resources when called.
+ */
+ public void Destroy ()
+ {
+ }
+
+ /** Tell the view to display information for a new accessible object.
+ @param xContext
+ The given object may be null. A typical behaviour in this case
+ would be to display a blank area. But is also possible to show
+ information about the last object.
+ */
+ public void SetObject (XAccessibleContext xContext)
+ {
+ mxContext = xContext;
+ Update ();
+ }
+
+
+ /** This is a request of a repaint with the current state of the current
+ object. The current object may or may not be the same as the one
+ when Update() was called the last time.
+ */
+ public void Update ()
+ {
+ }
+
+
+ /** Return a string that is used as a title of an enclosing frame.
+ */
+ abstract public String GetTitle ();
+
+ /// Reference to the current object to display information about.
+ protected XAccessibleContext mxContext;
+}
diff --git a/toolkit/test/accessibility/ov/ObjectViewContainer.java b/toolkit/test/accessibility/ov/ObjectViewContainer.java
new file mode 100644
index 0000000000..c7e647d673
--- /dev/null
+++ b/toolkit/test/accessibility/ov/ObjectViewContainer.java
@@ -0,0 +1,152 @@
+/*
+ * 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 .
+ */
+
+package ov;
+
+import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.util.ArrayList;
+
+import javax.swing.BorderFactory;
+import javax.swing.JPanel;
+import javax.swing.border.BevelBorder;
+import javax.swing.border.Border;
+
+import com.sun.star.accessibility.XAccessibleContext;
+
+
+public class ObjectViewContainer
+ extends JPanel
+{
+ private static interface IViewFactory {
+ ObjectView Create (
+ ObjectViewContainer aContainer,
+ XAccessibleContext xContext);
+ }
+
+ public ObjectViewContainer ()
+ {
+ maViewTemplates = new ArrayList<IViewFactory>();
+ maViewBorder = BorderFactory.createBevelBorder (BevelBorder.RAISED);
+ setLayout (new GridBagLayout ());
+
+ maViewTemplates.add(new IViewFactory() {
+ public ObjectView Create(ObjectViewContainer aContainer,
+ XAccessibleContext xContext) {
+ return ContextView.Create(aContainer, xContext);
+ }
+ });
+ maViewTemplates.add(new IViewFactory() {
+ public ObjectView Create(ObjectViewContainer aContainer,
+ XAccessibleContext xContext) {
+ return FocusView.Create(aContainer, xContext);
+ }
+ });
+ maViewTemplates.add(new IViewFactory() {
+ public ObjectView Create(ObjectViewContainer aContainer,
+ XAccessibleContext xContext) {
+ return TextView.Create(aContainer, xContext);
+ }
+ });
+ }
+
+ /** Remove all existing views and create new ones according to the
+ interfaces supported by the given object.
+ */
+ public void SetObject (XAccessibleContext xContext)
+ {
+ // Call Destroy at all views to give them a chance to release their
+ // resources.
+ int n = getComponentCount();
+ for (int i=0; i<n; i++)
+ ((ObjectView)getComponent(i)).Destroy();
+ // Remove existing views.
+ removeAll ();
+
+ // Add new views.
+ for (int i=0; i<maViewTemplates.size(); i++)
+ {
+ IViewFactory aViewFactory = maViewTemplates.get(i);
+ ObjectView aView = aViewFactory.Create(this, xContext);
+ Add (aView);
+ }
+
+ UpdateLayoutManager ();
+
+ // Now set the object at all views.
+ n = getComponentCount();
+ for (int i=0; i<n; i++)
+ ((ObjectView)getComponent(i)).SetObject (xContext);
+
+ setPreferredSize (getLayout().preferredLayoutSize (this));
+ }
+
+
+ /** Add an object view and place it below all previously added views.
+ @param aView
+ This argument may be null. In this case nothing happens.
+ */
+ private void Add (ObjectView aView)
+ {
+ if (aView != null)
+ {
+ GridBagConstraints constraints = new GridBagConstraints ();
+ constraints.gridx = 0;
+ constraints.gridy = getComponentCount();
+ constraints.gridwidth = 1;
+ constraints.gridheight = 1;
+ constraints.weightx = 1;
+ constraints.weighty = 0;
+ constraints.ipadx = 2;
+ constraints.ipady = 5;
+ constraints.insets = new Insets (5,5,5,5);
+ constraints.anchor = GridBagConstraints.NORTH;
+ constraints.fill = GridBagConstraints.HORIZONTAL;
+
+ aView.setBorder (
+ BorderFactory.createTitledBorder (
+ maViewBorder, aView.GetTitle()));
+
+ add (aView, constraints);
+ }
+ }
+
+ /** Update the layout manager by setting the vertical weight of the
+ bottom entry to 1 and so make it stretch to over the available
+ space.
+
+ */
+ private void UpdateLayoutManager ()
+ {
+ // Adapt the layout manager.
+ if (getComponentCount() > 0)
+ {
+ Component aComponent = getComponent (getComponentCount()-1);
+ GridBagLayout aLayout = (GridBagLayout)getLayout();
+ GridBagConstraints aConstraints = aLayout.getConstraints (aComponent);
+ aConstraints.weighty = 1;
+ aLayout.setConstraints (aComponent, aConstraints);
+ }
+ }
+
+ private final Border maViewBorder;
+ /// List of view templates which are instantiated when new object is set.
+ private final ArrayList<IViewFactory> maViewTemplates;
+}
diff --git a/toolkit/test/accessibility/ov/TextView.java b/toolkit/test/accessibility/ov/TextView.java
new file mode 100644
index 0000000000..518d5ff507
--- /dev/null
+++ b/toolkit/test/accessibility/ov/TextView.java
@@ -0,0 +1,133 @@
+/*
+ * 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 .
+ */
+
+package ov;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import javax.swing.JLabel;
+
+import com.sun.star.accessibility.AccessibleEventId;
+import com.sun.star.accessibility.AccessibleEventObject;
+import com.sun.star.accessibility.XAccessibleText;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.uno.UnoRuntime;
+
+public class TextView
+ extends ListeningObjectView
+{
+ /** Create a TextView when the given object supports the
+ XAccessibleText interface.
+ */
+ public static ObjectView Create (
+ ObjectViewContainer aContainer,
+ XAccessibleContext xContext)
+ {
+ XAccessibleText xText = UnoRuntime.queryInterface(
+ XAccessibleText.class, xContext);
+ if (xText != null)
+ return new TextView (aContainer);
+ else
+ return null;
+ }
+
+
+ private TextView (ObjectViewContainer aContainer)
+ {
+ super (aContainer);
+
+ setLayout (new GridBagLayout());
+ GridBagConstraints aConstraints = new GridBagConstraints ();
+
+ JLabel aLabel = new JLabel ("Text:");
+ aConstraints.gridy = 0;
+ aConstraints.weightx = 1;
+ aConstraints.fill = GridBagConstraints.HORIZONTAL;
+ add (aLabel, aConstraints);
+
+ maTextLabel = new JLabel ("");
+ aConstraints.gridx = 1;
+ aConstraints.fill = GridBagConstraints.NONE;
+ aConstraints.anchor = GridBagConstraints.WEST;
+ add (maTextLabel, aConstraints);
+
+ aLabel = new JLabel ("Caret position:");
+ aConstraints.gridx = 0;
+ aConstraints.gridy = 1;
+ aConstraints.weightx = 1;
+ aConstraints.fill = GridBagConstraints.HORIZONTAL;
+ add (aLabel, aConstraints);
+
+ maCaretPositionLabel = new JLabel ("");
+ aConstraints.gridx = 1;
+ aConstraints.fill = GridBagConstraints.NONE;
+ aConstraints.anchor = GridBagConstraints.WEST;
+ add (maCaretPositionLabel, aConstraints);
+ }
+
+
+ /** Additionally to the context store a reference to the
+ XAccessibleText interface.
+ */
+ @Override
+ public void SetObject (XAccessibleContext xObject)
+ {
+ mxText = UnoRuntime.queryInterface(
+ XAccessibleText.class, xObject);
+ super.SetObject (xObject);
+ }
+
+ @Override
+ synchronized public void Update ()
+ {
+ if (mxText == null)
+ {
+ maTextLabel.setText ("<null object>");
+ maCaretPositionLabel.setText ("<null object>");
+ }
+ else
+ {
+ maTextLabel.setText (mxText.getText());
+ maCaretPositionLabel.setText (Integer.toString(mxText.getCaretPosition()));
+ }
+ }
+
+ @Override
+ public String GetTitle ()
+ {
+ return "Text";
+ }
+
+ @Override
+ public void notifyEvent (AccessibleEventObject aEvent)
+ {
+ System.out.println (aEvent);
+ switch (aEvent.EventId)
+ {
+ case AccessibleEventId.TEXT_CHANGED :
+ case AccessibleEventId.CARET_CHANGED :
+ Update ();
+ break;
+ }
+ }
+
+ private final JLabel
+ maTextLabel,
+ maCaretPositionLabel;
+ private XAccessibleText mxText;
+}
diff --git a/toolkit/test/accessibility/tools/NameProvider.java b/toolkit/test/accessibility/tools/NameProvider.java
new file mode 100644
index 0000000000..7a859fcea6
--- /dev/null
+++ b/toolkit/test/accessibility/tools/NameProvider.java
@@ -0,0 +1,277 @@
+/*
+ * 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 .
+ */
+
+package tools;
+
+import java.util.HashMap;
+import com.sun.star.accessibility.AccessibleStateType;
+import com.sun.star.accessibility.AccessibleEventId;
+import com.sun.star.accessibility.AccessibleRole;
+import com.sun.star.accessibility.AccessibleRelationType;
+
+
+/** Provide names for several accessibility constants groups.
+*/
+public class NameProvider
+{
+ /** Return the name of the specified state.
+ @param nStateId
+ Id of the state for which to return its name. This is one of
+ the ids listed in the <type>AccessibleStateType</const>
+ constants group.
+ @return
+ Returns the name of the specified state or an empty string if an
+ invalid / unknown state id was given.
+ */
+ public static String getStateName (int nStateId)
+ {
+ return maStateMap.get (Integer.valueOf(nStateId));
+ }
+
+
+ /** Return the name of the specified event.
+ @param nEventId
+ Id of the event type for which to return its name. This is one
+ of the ids listed in the <type>AccessibleEventId</const>
+ constants group.
+ @return
+ Returns the name of the specified event type or an empty string
+ if an invalid / unknown event id was given.
+ */
+ public static String getEventName (int nEventId)
+ {
+ return maEventMap.get (Integer.valueOf(nEventId));
+ }
+
+
+ /** Return the name of the specified role.
+ @param nRole
+ Id of the role for which to return its name. This is one of
+ the ids listed in the <type>AccessibleRole</const>
+ constants group.
+ @return
+ Returns the name of the specified role or an empty string if an
+ invalid / unknown role id was given.
+ */
+ public static String getRoleName (int nRole)
+ {
+ return maRoleMap.get (Integer.valueOf(nRole));
+ }
+
+
+ /** Return the name of the specified relation.
+ @param nRelation
+ Id of the relation for which to return its name. This is one of
+ the ids listed in the <type>AccessibleRelationType</const>
+ constants group.
+ @return
+ Returns the name of the specified relation type or an empty
+ string if an invalid / unknown role id was given.
+ */
+ public static String getRelationName (int nRelation)
+ {
+ return maRelationMap.get (Integer.valueOf(nRelation));
+ }
+
+
+ private static HashMap<Integer, String> maStateMap = new HashMap<Integer, String>();
+ private static HashMap<Integer, String> maEventMap = new HashMap<Integer, String>();
+ private static HashMap<Integer, String> maRoleMap = new HashMap<Integer, String>();
+ private static HashMap<Integer, String> maRelationMap = new HashMap<Integer, String>();
+
+ static {
+ maStateMap.put (Integer.valueOf(AccessibleStateType.INVALID), "INVALID");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.ACTIVE), "ACTIVE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.ARMED), "ARMED");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.BUSY), "BUSY");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.CHECKABLE), "CHECKABLE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.CHECKED), "CHECKED");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.DEFUNC), "DEFUNC");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.EDITABLE), "EDITABLE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.ENABLED), "ENABLED");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.EXPANDABLE), "EXPANDABLE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.EXPANDED), "EXPANDED");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.FOCUSABLE), "FOCUSABLE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.FOCUSED), "FOCUSED");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.HORIZONTAL), "HORIZONTAL");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.ICONIFIED), "ICONIFIED");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.MODAL), "MODAL");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.MULTI_LINE), "MULTI_LINE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.MULTI_SELECTABLE), "MULTI_SELECTABLE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.OPAQUE), "OPAQUE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.PRESSED), "PRESSED");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.RESIZABLE), "RESIZABLE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.SELECTABLE), "SELECTABLE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.SELECTED), "SELECTED");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.SENSITIVE), "SENSITIVE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.SHOWING), "SHOWING");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.SINGLE_LINE), "SINGLE_LINE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.STALE), "STALE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.TRANSIENT), "TRANSIENT");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.VERTICAL), "VERTICAL");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.VISIBLE), "VISIBLE");
+ maStateMap.put (Integer.valueOf(AccessibleStateType.MANAGES_DESCENDANTS),
+ "MANAGES_DESCENDANTS");
+
+
+ maEventMap.put (Integer.valueOf(0),
+ "[UNKNOWN]");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.NAME_CHANGED),
+ "NAME_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.DESCRIPTION_CHANGED),
+ "DESCRIPTION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.ACTION_CHANGED),
+ "ACTION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.STATE_CHANGED),
+ "STATE_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.ACTIVE_DESCENDANT_CHANGED),
+ "ACTIVE_DESCENDANT_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.BOUNDRECT_CHANGED),
+ "BOUNDRECT_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.CHILD),
+ "CHILD");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.INVALIDATE_ALL_CHILDREN),
+ "INVALIDATE_ALL_CHILDREN");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.SELECTION_CHANGED),
+ "SELECTION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.VISIBLE_DATA_CHANGED),
+ "VISIBLE_DATA_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.VALUE_CHANGED),
+ "VALUE_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.CONTENT_FLOWS_FROM_RELATION_CHANGED),
+ "CONTENT_FLOWS_FROM_RELATION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.CONTENT_FLOWS_TO_RELATION_CHANGED),
+ "CONTENT_FLOWS_TO_RELATION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.CONTROLLED_BY_RELATION_CHANGED),
+ "CONTROLLED_BY_RELATION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.CONTROLLER_FOR_RELATION_CHANGED),
+ "CONTROLLER_FOR_RELATION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.LABEL_FOR_RELATION_CHANGED),
+ "LABEL_FOR_RELATION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.LABELED_BY_RELATION_CHANGED),
+ "LABELED_BY_RELATION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.MEMBER_OF_RELATION_CHANGED),
+ "MEMBER_OF_RELATION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.SUB_WINDOW_OF_RELATION_CHANGED),
+ "SUB_WINDOW_OF_RELATION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.CARET_CHANGED),
+ "CARET_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.TEXT_SELECTION_CHANGED),
+ "TEXT_SELECTION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.TEXT_CHANGED),
+ "TEXT_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.TEXT_ATTRIBUTE_CHANGED),
+ "TEXT_ATTRIBUTE_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.HYPERTEXT_CHANGED),
+ "HYPERTEXT_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.TABLE_CAPTION_CHANGED),
+ "TABLE_CAPTION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.TABLE_COLUMN_DESCRIPTION_CHANGED),
+ "TABLE_COLUMN_DESCRIPTION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.TABLE_COLUMN_HEADER_CHANGED),
+ "TABLE_COLUMN_HEADER_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.TABLE_MODEL_CHANGED),
+ "TABLE_MODEL_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.TABLE_ROW_DESCRIPTION_CHANGED),
+ "TABLE_ROW_DESCRIPTION_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.TABLE_ROW_HEADER_CHANGED),
+ "TABLE_ROW_HEADER_CHANGED");
+ maEventMap.put (Integer.valueOf(AccessibleEventId.TABLE_SUMMARY_CHANGED),
+ "TABLE_SUMMARY_CHANGED");
+
+ maRoleMap.put (Integer.valueOf(AccessibleRole.UNKNOWN), "UNKNOWN");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.UNKNOWN), "UNKNOWN");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.ALERT), "ALERT");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.COLUMN_HEADER), "COLUMN_HEADER");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.CANVAS), "CANVAS");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.CHECK_BOX), "CHECK_BOX");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.CHECK_MENU_ITEM), "CHECK_MENU_ITEM");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.COLOR_CHOOSER), "COLOR_CHOOSER");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.COMBO_BOX), "COMBO_BOX");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.DESKTOP_ICON), "DESKTOP_ICON");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.DESKTOP_PANE), "DESKTOP_PANE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.DIRECTORY_PANE), "DIRECTORY_PANE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.DIALOG), "DIALOG");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.DOCUMENT), "DOCUMENT");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.EMBEDDED_OBJECT), "EMBEDDED_OBJECT");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.END_NOTE), "END_NOTE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.FILE_CHOOSER), "FILE_CHOOSER");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.FILLER), "FILLER");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.FONT_CHOOSER), "FONT_CHOOSER");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.FOOTER), "FOOTER");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.FOOTNOTE), "FOOTNOTE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.FRAME), "FRAME");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.GLASS_PANE), "GLASS_PANE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.GRAPHIC), "GRAPHIC");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.GROUP_BOX), "GROUP_BOX");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.HEADER), "HEADER");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.HEADING), "HEADING");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.HYPER_LINK), "HYPER_LINK");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.ICON), "ICON");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.INTERNAL_FRAME), "INTERNAL_FRAME");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.LABEL), "LABEL");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.LAYERED_PANE), "LAYERED_PANE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.LIST), "LIST");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.LIST_ITEM), "LIST_ITEM");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.MENU), "MENU");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.MENU_BAR), "MENU_BAR");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.MENU_ITEM), "MENU_ITEM");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.OPTION_PANE), "OPTION_PANE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.PAGE_TAB), "PAGE_TAB");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.PAGE_TAB_LIST), "PAGE_TAB_LIST");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.PANEL), "PANEL");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.PARAGRAPH), "PARAGRAPH");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.PASSWORD_TEXT), "PASSWORD_TEXT");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.POPUP_MENU), "POPUP_MENU");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.PUSH_BUTTON), "PUSH_BUTTON");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.PROGRESS_BAR), "PROGRESS_BAR");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.RADIO_BUTTON), "RADIO_BUTTON");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.RADIO_MENU_ITEM), "RADIO_MENU_ITEM");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.ROW_HEADER), "ROW_HEADER");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.ROOT_PANE), "ROOT_PANE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.SCROLL_BAR), "SCROLL_BAR");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.SCROLL_PANE), "SCROLL_PANE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.SHAPE), "SHAPE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.SEPARATOR), "SEPARATOR");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.SLIDER), "SLIDER");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.SPIN_BOX), "SPIN_BOX");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.SPLIT_PANE), "SPLIT_PANE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.STATIC), "STATIC");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.STATUS_BAR), "STATUS_BAR");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.TABLE), "TABLE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.TABLE_CELL), "TABLE_CELL");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.TEXT), "TEXT");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.TEXT_FRAME), "TEXT_FRAME");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.TOGGLE_BUTTON), "TOGGLE_BUTTON");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.TOOL_BAR), "TOOL_BAR");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.TOOL_TIP), "TOOL_TIP");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.TREE), "TREE");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.VIEW_PORT), "VIEW_PORT");
+ maRoleMap.put (Integer.valueOf(AccessibleRole.WINDOW), "WINDOW");
+
+ maRelationMap.put (Integer.valueOf(AccessibleRelationType.INVALID), "INVALID");
+ maRelationMap.put (Integer.valueOf(AccessibleRelationType.CONTENT_FLOWS_FROM), "CONTENT_FLOWS_FROM");
+ maRelationMap.put (Integer.valueOf(AccessibleRelationType.CONTENT_FLOWS_TO), "CONTENT_FLOWS_TO");
+ maRelationMap.put (Integer.valueOf(AccessibleRelationType.CONTROLLED_BY), "CONTROLLED_BY");
+ maRelationMap.put (Integer.valueOf(AccessibleRelationType.CONTROLLER_FOR), "CONTROLLER_FOR");
+ maRelationMap.put (Integer.valueOf(AccessibleRelationType.LABEL_FOR), "LABEL_FOR");
+ maRelationMap.put (Integer.valueOf(AccessibleRelationType.LABELED_BY), "LABELED_BY");
+ maRelationMap.put (Integer.valueOf(AccessibleRelationType.MEMBER_OF), "MEMBER_OF");
+ maRelationMap.put (Integer.valueOf(AccessibleRelationType.SUB_WINDOW_OF), "SUB_WINDOW_OF");
+ }
+}
diff --git a/toolkit/util/tk.component b/toolkit/util/tk.component
new file mode 100644
index 0000000000..f93d1550a0
--- /dev/null
+++ b/toolkit/util/tk.component
@@ -0,0 +1,394 @@
+<?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 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.awt.comp.AsyncCallback"
+ constructor="com_sun_star_awt_comp_AsyncCallback_get_implementation">
+ <service name="com.sun.star.awt.AsyncCallback"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.embed.HatchWindowFactory"
+ constructor="com_sun_star_comp_embed_HatchWindowFactory_get_implementation">
+ <service name="com.sun.star.comp.embed.HatchWindowFactory"/>
+ <service name="com.sun.star.embed.HatchWindowFactory"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlTabPage"
+ constructor="stardiv_Toolkit_UnoControlTabPage_get_implementation">
+ <service name="com.sun.star.awt.tab.UnoControlTabPage"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlTabPageModel"
+ constructor="stardiv_Toolkit_UnoControlTabPageModel_get_implementation">
+ <service name="com.sun.star.awt.tab.UnoControlTabPageModel"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlTabPageContainerModel"
+ constructor="stardiv_Toolkit_UnoControlTabPageContainerModel_get_implementation">
+ <service name="com.sun.star.awt.tab.UnoControlTabPageContainerModel"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlTabPageContainer"
+ constructor="stardiv_Toolkit_UnoControlTabPageContainer_get_implementation">
+ <service name="com.sun.star.awt.tab.UnoControlTabPageContainer"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.DefaultGridColumnModel"
+ constructor="stardiv_Toolkit_DefaultGridColumnModel_get_implementation">
+ <service name="com.sun.star.awt.grid.DefaultGridColumnModel"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.DefaultGridDataModel"
+ constructor="stardiv_Toolkit_DefaultGridDataModel_get_implementation">
+ <service name="com.sun.star.awt.grid.DefaultGridDataModel"/>
+ </implementation>
+ <implementation name="org.openoffice.comp.toolkit.GridColumn"
+ constructor="org_openoffice_comp_toolkit_GridColumn_get_implementation">
+ <service name="com.sun.star.awt.grid.GridColumn"/>
+ </implementation>
+ <implementation name="org.openoffice.comp.toolkit.SortableGridDataModel"
+ constructor="org_openoffice_comp_toolkit_SortableGridDataModel_get_implementation">
+ <service name="com.sun.star.awt.grid.SortableGridDataModel"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.GridControl"
+ constructor="stardiv_Toolkit_GridControl_get_implementation">
+ <service name="com.sun.star.awt.grid.UnoControlGrid"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.GridControlModel"
+ constructor="stardiv_Toolkit_GridControlModel_get_implementation">
+ <service name="com.sun.star.awt.grid.UnoControlGridModel"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.MutableTreeDataModel"
+ constructor="stardiv_Toolkit_MutableTreeDataModel_get_implementation">
+ <service name="com.sun.star.awt.tree.MutableTreeDataModel"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.StdTabController"
+ constructor="stardiv_Toolkit_StdTabController_get_implementation">
+ <service name="com.sun.star.awt.TabController"/>
+ <service name="stardiv.vcl.control.TabController"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.StdTabControllerModel"
+ constructor="stardiv_Toolkit_StdTabControllerModel_get_implementation">
+ <service name="com.sun.star.awt.TabControllerModel"/>
+ <service name="stardiv.vcl.controlmodel.TabController"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.TreeControl"
+ constructor="stardiv_Toolkit_TreeControl_get_implementation">
+ <service name="com.sun.star.awt.tree.TreeControl"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.TreeControlModel"
+ constructor="stardiv_Toolkit_TreeControlModel_get_implementation">
+ <service name="com.sun.star.awt.tree.TreeControlModel"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoButtonControl"
+ constructor="stardiv_Toolkit_UnoButtonControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlButton"/>
+ <service name="stardiv.vcl.control.Button"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoCheckBoxControl"
+ constructor="stardiv_Toolkit_UnoCheckBoxControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlCheckBox"/>
+ <service name="stardiv.vcl.control.CheckBox"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoComboBoxControl"
+ constructor="stardiv_Toolkit_UnoComboBoxControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlComboBox"/>
+ <service name="stardiv.vcl.control.ComboBox"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlButtonModel"
+ constructor="stardiv_Toolkit_UnoControlButtonModel_get_implementation">
+ <service name="com.sun.star.awt.UnoControlButtonModel"/>
+ <service name="stardiv.vcl.controlmodel.Button"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlCheckBoxModel"
+ constructor="stardiv_Toolkit_UnoControlCheckBoxModel_get_implementation">
+ <service name="com.sun.star.awt.UnoControlCheckBoxModel"/>
+ <service name="stardiv.vcl.controlmodel.CheckBox"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlComboBoxModel"
+ constructor="stardiv_Toolkit_UnoControlComboBoxModel_get_implementation">
+ <service name="com.sun.star.awt.UnoControlComboBoxModel"/>
+ <service name="stardiv.vcl.controlmodel.ComboBox"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlContainer"
+ constructor="stardiv_Toolkit_UnoControlContainer_get_implementation">
+ <service name="com.sun.star.awt.UnoControlContainer"/>
+ <service name="stardiv.vcl.control.ControlContainer"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlContainerModel"
+ constructor="stardiv_Toolkit_UnoControlContainerModel_get_implementation">
+ <service name="com.sun.star.awt.UnoControlContainerModel"/>
+ <service name="stardiv.vcl.controlmodel.ControlContainer"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlCurrencyFieldModel"
+ constructor="stardiv_Toolkit_UnoControlCurrencyFieldModel_get_implementation">
+ <service name="com.sun.star.awt.UnoControlCurrencyFieldModel"/>
+ <service name="stardiv.vcl.controlmodel.CurrencyField"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlDateFieldModel"
+ constructor="stardiv_Toolkit_UnoControlDateFieldModel_get_implementation">
+ <service name="com.sun.star.awt.UnoControlDateFieldModel"/>
+ <service name="stardiv.vcl.controlmodel.DateField"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlDialogModel"
+ constructor="stardiv_Toolkit_UnoControlDialogModel_get_implementation">
+ <service name="com.sun.star.awt.UnoControlDialogModel"/>
+ <service name="stardiv.vcl.controlmodel.Dialog"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlEditModel"
+ constructor="stardiv_Toolkit_UnoControlEditModel_get_implementation">
+ <service name="com.sun.star.awt.UnoControlEditModel"/>
+ <service name="stardiv.vcl.controlmodel.Edit"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlFileControlModel"
+ constructor="stardiv_Toolkit_UnoControlFileControlModel_get_implementation">
+ <service name="com.sun.star.awt.UnoControlFileControlModel"/>
+ <service name="stardiv.vcl.controlmodel.FileControl"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlFixedHyperlinkModel"
+ constructor="stardiv_Toolkit_UnoControlFixedHyperlinkModel_get_implementation">
+ <service name="com.sun.star.awt.UnoControlFixedHyperlinkModel"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlFixedLineModel"
+ constructor="stardiv_Toolkit_UnoControlFixedLineModel_get_implementation">
+ <service name="com.sun.star.awt.UnoControlFixedLineModel"/>
+ <service name="stardiv.vcl.controlmodel.FixedLine"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlFixedTextModel"
+ constructor="stardiv_Toolkit_UnoControlFixedTextModel_get_implementation">
+ <service name="com.sun.star.awt.UnoControlFixedTextModel"/>
+ <service name="stardiv.vcl.controlmodel.FixedText"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlFormattedFieldModel"
+ constructor="stardiv_Toolkit_UnoControlFormattedFieldModel_get_implementation">
+ <service name="com.sun.star.awt.UnoControlFormattedFieldModel"/>
+ <service name="stardiv.vcl.controlmodel.FormattedField"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlGroupBoxModel"
+ constructor="stardiv_Toolkit_UnoControlGroupBoxModel_get_implementation">
+ <service name="com.sun.star.awt.UnoControlGroupBoxModel"/>
+ <service name="stardiv.vcl.controlmodel.GroupBox"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlImageControlModel"
+ constructor="stardiv_Toolkit_UnoControlImageControlModel_get_implementation">
+ <service name="com.sun.star.awt.UnoControlImageButtonModel"/>
+ <service name="com.sun.star.awt.UnoControlImageControlModel"/>
+ <service name="stardiv.vcl.controlmodel.ImageButton"/>
+ <service name="stardiv.vcl.controlmodel.ImageControl"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlListBoxModel"
+ constructor="stardiv_Toolkit_UnoControlListBoxModel_get_implementation">
+ <service name="com.sun.star.awt.UnoControlListBoxModel"/>
+ <service name="stardiv.vcl.controlmodel.ListBox"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlNumericFieldModel"
+ constructor="stardiv_Toolkit_UnoControlNumericFieldModel_get_implementation">
+ <service name="com.sun.star.awt.UnoControlNumericFieldModel"/>
+ <service name="stardiv.vcl.controlmodel.NumericField"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlPatternFieldModel"
+ constructor="stardiv_Toolkit_UnoControlPatternFieldModel_get_implementation">
+ <service name="com.sun.star.awt.UnoControlPatternFieldModel"/>
+ <service name="stardiv.vcl.controlmodel.PatternField"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlProgressBarModel"
+ constructor="stardiv_Toolkit_UnoControlProgressBarModel_get_implementation">
+ <service name="com.sun.star.awt.UnoControlProgressBarModel"/>
+ <service name="stardiv.vcl.controlmodel.ProgressBar"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlRadioButtonModel"
+ constructor="stardiv_Toolkit_UnoControlRadioButtonModel_get_implementation">
+ <service name="com.sun.star.awt.UnoControlRadioButtonModel"/>
+ <service name="stardiv.vcl.controlmodel.RadioButton"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlRoadmapModel"
+ constructor="stardiv_Toolkit_UnoControlRoadmapModel_get_implementation">
+ <service name="com.sun.star.awt.UnoControlRoadmapModel"/>
+ <service name="stardiv.vcl.controlmodel.Roadmap"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlScrollBarModel"
+ constructor="stardiv_Toolkit_UnoControlScrollBarModel_get_implementation">
+ <service name="com.sun.star.awt.UnoControlScrollBarModel"/>
+ <service name="stardiv.vcl.controlmodel.ScrollBar"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoControlTimeFieldModel"
+ constructor="stardiv_Toolkit_UnoControlTimeFieldModel_get_implementation">
+ <service name="com.sun.star.awt.UnoControlTimeFieldModel"/>
+ <service name="stardiv.vcl.controlmodel.TimeField"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoCurrencyFieldControl"
+ constructor="stardiv_Toolkit_UnoCurrencyFieldControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlCurrencyField"/>
+ <service name="stardiv.vcl.control.CurrencyField"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoDateFieldControl"
+ constructor="stardiv_Toolkit_UnoDateFieldControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlDateField"/>
+ <service name="stardiv.vcl.control.DateField"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoDialogControl"
+ constructor="stardiv_Toolkit_UnoDialogControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlDialog"/>
+ <service name="stardiv.vcl.control.Dialog"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoEditControl"
+ constructor="stardiv_Toolkit_UnoEditControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlEdit"/>
+ <service name="stardiv.vcl.control.Edit"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoFileControl"
+ constructor="stardiv_Toolkit_UnoFileControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlFileControl"/>
+ <service name="stardiv.vcl.control.FileControl"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoFixedHyperlinkControl"
+ constructor="stardiv_Toolkit_UnoFixedHyperlinkControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlFixedHyperlink"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoFixedLineControl"
+ constructor="stardiv_Toolkit_UnoFixedLineControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlFixedLine"/>
+ <service name="stardiv.vcl.control.FixedLine"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoFixedTextControl"
+ constructor="stardiv_Toolkit_UnoFixedTextControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlFixedText"/>
+ <service name="stardiv.vcl.control.FixedText"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoFormattedFieldControl"
+ constructor="stardiv_Toolkit_UnoFormattedFieldControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlFormattedField"/>
+ <service name="stardiv.vcl.control.FormattedField"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoGroupBoxControl"
+ constructor="stardiv_Toolkit_UnoGroupBoxControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlGroupBox"/>
+ <service name="stardiv.vcl.control.GroupBox"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoImageControlControl"
+ constructor="stardiv_Toolkit_UnoImageControlControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlImageButton"/>
+ <service name="com.sun.star.awt.UnoControlImageControl"/>
+ <service name="stardiv.vcl.control.ImageButton"/>
+ <service name="stardiv.vcl.control.ImageControl"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoListBoxControl"
+ constructor="stardiv_Toolkit_UnoListBoxControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlListBox"/>
+ <service name="stardiv.vcl.control.ListBox"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoNumericFieldControl"
+ constructor="stardiv_Toolkit_UnoNumericFieldControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlNumericField"/>
+ <service name="stardiv.vcl.control.NumericField"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoPatternFieldControl"
+ constructor="stardiv_Toolkit_UnoPatternFieldControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlPatternField"/>
+ <service name="stardiv.vcl.control.PatternField"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoProgressBarControl"
+ constructor="stardiv_Toolkit_UnoProgressBarControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlProgressBar"/>
+ <service name="stardiv.vcl.control.ProgressBar"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoRadioButtonControl"
+ constructor="stardiv_Toolkit_UnoRadioButtonControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlRadioButton"/>
+ <service name="stardiv.vcl.control.RadioButton"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoRoadmapControl"
+ constructor="stardiv_Toolkit_UnoRoadmapControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlRoadmap"/>
+ <service name="stardiv.vcl.control.Roadmap"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoScrollBarControl"
+ constructor="stardiv_Toolkit_UnoScrollBarControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlScrollBar"/>
+ <service name="stardiv.vcl.control.ScrollBar"/>
+ </implementation>
+ <implementation name="org.openoffice.comp.toolkit.SpinningProgressControlModel"
+ constructor="org_openoffice_comp_toolkit_SpinningProgressControlModel_get_implementation">
+ <service name="com.sun.star.awt.SpinningProgressControlModel"/>
+ </implementation>
+ <implementation name="org.openoffice.comp.toolkit.AnimatedImagesControlModel"
+ constructor="org_openoffice_comp_toolkit_AnimatedImagesControlModel_get_implementation">
+ <service name="com.sun.star.awt.AnimatedImagesControlModel"/>
+ </implementation>
+ <implementation name="org.openoffice.comp.toolkit.AnimatedImagesControl"
+ constructor="org_openoffice_comp_toolkit_AnimatedImagesControl_get_implementation">
+ <service name="com.sun.star.awt.AnimatedImagesControl"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoSpinButtonControl"
+ constructor="stardiv_Toolkit_UnoSpinButtonControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlSpinButton"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoSpinButtonModel"
+ constructor="stardiv_Toolkit_UnoSpinButtonModel_get_implementation">
+ <service name="com.sun.star.awt.UnoControlSpinButtonModel"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoTimeFieldControl"
+ constructor="stardiv_Toolkit_UnoTimeFieldControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlTimeField"/>
+ <service name="stardiv.vcl.control.TimeField"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.VCLXMenuBar"
+ constructor="stardiv_Toolkit_VCLXMenuBar_get_implementation">
+ <service name="com.sun.star.awt.MenuBar"/>
+ <service name="stardiv.vcl.MenuBar"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.VCLXPointer"
+ constructor="stardiv_Toolkit_VCLXPointer_get_implementation">
+ <service name="com.sun.star.awt.Pointer"/>
+ <service name="stardiv.vcl.Pointer"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.VCLXPopupMenu"
+ constructor="stardiv_Toolkit_VCLXPopupMenu_get_implementation">
+ <service name="com.sun.star.awt.PopupMenu"/>
+ <service name="stardiv.vcl.PopupMenu"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.VCLXPrinterServer"
+ constructor="stardiv_Toolkit_VCLXPrinterServer_get_implementation">
+ <service name="com.sun.star.awt.PrinterServer"/>
+ <service name="stardiv.vcl.PrinterServer"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.VCLXToolkit"
+ constructor="stardiv_Toolkit_VCLXToolkit_get_implementation">
+ <service name="com.sun.star.awt.Toolkit"/>
+ <service name="stardiv.vcl.VclToolkit"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoMultiPageModel"
+ constructor="stardiv_Toolkit_UnoMultiPageModel_get_implementation">
+ <service name="com.sun.star.awt.UnoMultiPageModel"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoMultiPageControl"
+ constructor="stardiv_Toolkit_UnoMultiPageControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlMultiPage"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoPageModel"
+ constructor="stardiv_Toolkit_UnoPageModel_get_implementation">
+ <service name="com.sun.star.awt.UnoPageModel"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoPageControl"
+ constructor="stardiv_Toolkit_UnoPageControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlPage"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoFrameModel"
+ constructor="stardiv_Toolkit_UnoFrameModel_get_implementation">
+ <service name="com.sun.star.awt.UnoFrameModel"/>
+ </implementation>
+ <implementation name="stardiv.Toolkit.UnoFrameControl"
+ constructor="stardiv_Toolkit_UnoFrameControl_get_implementation">
+ <service name="com.sun.star.awt.UnoControlFrame"/>
+ </implementation>
+</component>