Bug Summary

File:home/maarten/src/libreoffice/core/framework/source/layoutmanager/toolbarlayoutmanager.cxx
Warning:line 3069, column 25
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name toolbarlayoutmanager.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D FWK_DLLIMPLEMENTATION -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/framework/source/inc -I /home/maarten/src/libreoffice/core/framework/inc -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/framework/source/layoutmanager/toolbarlayoutmanager.cxx

/home/maarten/src/libreoffice/core/framework/source/layoutmanager/toolbarlayoutmanager.cxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include "toolbarlayoutmanager.hxx"
21#include <uiconfiguration/windowstateproperties.hxx>
22#include <uielement/addonstoolbarwrapper.hxx>
23#include "helpers.hxx"
24#include <services/layoutmanager.hxx>
25#include <strings.hrc>
26#include <classes/fwkresid.hxx>
27
28#include <com/sun/star/awt/PosSize.hpp>
29#include <com/sun/star/beans/XPropertySet.hpp>
30#include <com/sun/star/ui/UIElementType.hpp>
31#include <com/sun/star/container/XNameReplace.hpp>
32#include <com/sun/star/container/XNameContainer.hpp>
33#include <com/sun/star/ui/XUIElementSettings.hpp>
34#include <com/sun/star/ui/XUIFunctionListener.hpp>
35
36#include <cppuhelper/queryinterface.hxx>
37#include <unotools/cmdoptions.hxx>
38#include <toolkit/helper/vclunohelper.hxx>
39#include <toolkit/helper/convert.hxx>
40#include <vcl/i18nhelp.hxx>
41#include <vcl/dockingarea.hxx>
42#include <vcl/settings.hxx>
43#include <vcl/svapp.hxx>
44#include <sal/log.hxx>
45#include <tools/gen.hxx>
46
47
48using namespace ::com::sun::star;
49
50namespace framework
51{
52
53ToolbarLayoutManager::ToolbarLayoutManager(
54 const uno::Reference< uno::XComponentContext >& rxContext,
55 const uno::Reference< ui::XUIElementFactory >& xUIElementFactory,
56 LayoutManager* pParentLayouter ):
57 m_xContext( rxContext),
58 m_xUIElementFactoryManager( xUIElementFactory ),
59 m_pParentLayouter( pParentLayouter ),
60 m_eDockOperation( DOCKOP_ON_COLROW ),
61 m_ePreviewDetection( PREVIEWFRAME_UNKNOWN ),
62 m_bComponentAttached( false ),
63 m_bLayoutDirty( false ),
64 m_bGlobalSettings( false ),
65 m_bDockingInProgress( false ),
66 m_bLayoutInProgress( false ),
67 m_bToolbarCreation( false )
68{
69 // initialize rectangles to zero values
70 setZeroRectangle( m_aDockingAreaOffsets );
71 setZeroRectangle( m_aDockingArea );
72}
73
74ToolbarLayoutManager::~ToolbarLayoutManager()
75{
76 m_pGlobalSettings.reset();
77 m_pAddonOptions.reset();
78}
79
80// XInterface
81
82void SAL_CALL ToolbarLayoutManager::acquire() throw()
83{
84 OWeakObject::acquire();
85}
86
87void SAL_CALL ToolbarLayoutManager::release() throw()
88{
89 OWeakObject::release();
90}
91
92uno::Any SAL_CALL ToolbarLayoutManager::queryInterface( const uno::Type & rType )
93{
94 uno::Any a = ::cppu::queryInterface( rType,
95 static_cast< awt::XDockableWindowListener* >(this),
96 static_cast< ui::XUIConfigurationListener* >(this),
97 static_cast< awt::XWindowListener* >(this));
98
99 if ( a.hasValue() )
100 return a;
101
102 return OWeakObject::queryInterface( rType );
103}
104
105void SAL_CALL ToolbarLayoutManager::disposing( const lang::EventObject& aEvent )
106{
107 if ( aEvent.Source == m_xFrame )
108 {
109 // Reset all internal references
110 reset();
111 implts_destroyDockingAreaWindows();
112 }
113}
114
115awt::Rectangle ToolbarLayoutManager::getDockingArea()
116{
117 SolarMutexResettableGuard aWriteLock;
118 tools::Rectangle aNewDockingArea( m_aDockingArea );
119 aWriteLock.clear();
120
121 if ( isLayoutDirty() )
122 aNewDockingArea = implts_calcDockingArea();
123
124 aWriteLock.reset();
125 m_aDockingArea = aNewDockingArea;
126 aWriteLock.clear();
127
128 return putRectangleValueToAWT(aNewDockingArea);
129}
130
131void ToolbarLayoutManager::setDockingArea( const awt::Rectangle& rDockingArea )
132{
133 SolarMutexGuard g;
134 m_aDockingArea = putAWTToRectangle( rDockingArea );
135 m_bLayoutDirty = true;
136}
137
138void ToolbarLayoutManager::implts_setDockingAreaWindowSizes( const awt::Rectangle& rBorderSpace )
139{
140 SolarMutexClearableGuard aReadLock;
141 tools::Rectangle aDockOffsets = m_aDockingAreaOffsets;
142 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
143 uno::Reference< awt::XWindow > xTopDockAreaWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] );
144 uno::Reference< awt::XWindow > xBottomDockAreaWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)] );
145 uno::Reference< awt::XWindow > xLeftDockAreaWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] );
146 uno::Reference< awt::XWindow > xRightDockAreaWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)] );
147 aReadLock.clear();
148
149 uno::Reference< awt::XDevice > xDevice( xContainerWindow, uno::UNO_QUERY );
150
151 // Convert relative size to output size.
152 awt::Rectangle aRectangle = xContainerWindow->getPosSize();
153 awt::DeviceInfo aInfo = xDevice->getInfo();
154 awt::Size aContainerClientSize( aRectangle.Width - aInfo.LeftInset - aInfo.RightInset ,
155 aRectangle.Height - aInfo.TopInset - aInfo.BottomInset );
156 long aStatusBarHeight = aDockOffsets.GetHeight();
157
158 sal_Int32 nLeftRightDockingAreaHeight( aContainerClientSize.Height );
159 if ( rBorderSpace.Y >= 0 )
160 {
161 // Top docking area window
162 xTopDockAreaWindow->setPosSize( 0, 0, aContainerClientSize.Width, rBorderSpace.Y, awt::PosSize::POSSIZE );
163 xTopDockAreaWindow->setVisible( true );
164 nLeftRightDockingAreaHeight -= rBorderSpace.Y;
165 }
166
167 if ( rBorderSpace.Height >= 0 )
168 {
169 // Bottom docking area window
170 sal_Int32 nBottomPos = std::max( sal_Int32( aContainerClientSize.Height - rBorderSpace.Height - aStatusBarHeight + 1 ), sal_Int32( 0 ));
171 sal_Int32 nHeight = ( nBottomPos == 0 ) ? 0 : rBorderSpace.Height;
172
173 xBottomDockAreaWindow->setPosSize( 0, nBottomPos, aContainerClientSize.Width, nHeight, awt::PosSize::POSSIZE );
174 xBottomDockAreaWindow->setVisible( true );
175 nLeftRightDockingAreaHeight -= nHeight - 1;
176 }
177
178 nLeftRightDockingAreaHeight -= aStatusBarHeight;
179 if ( rBorderSpace.X >= 0 || nLeftRightDockingAreaHeight > 0 )
180 {
181 // Left docking area window
182 // We also have to change our right docking area window if the top or bottom area has changed. They have a higher priority!
183 sal_Int32 nHeight = std::max<sal_Int32>( 0, nLeftRightDockingAreaHeight );
184
185 xLeftDockAreaWindow->setPosSize( 0, rBorderSpace.Y, rBorderSpace.X, nHeight, awt::PosSize::POSSIZE );
186 xLeftDockAreaWindow->setVisible( true );
187 }
188 if ( rBorderSpace.Width >= 0 || nLeftRightDockingAreaHeight > 0 )
189 {
190 // Right docking area window
191 // We also have to change our right docking area window if the top or bottom area has changed. They have a higher priority!
192 sal_Int32 nLeftPos = std::max<sal_Int32>( 0, aContainerClientSize.Width - rBorderSpace.Width );
193 sal_Int32 nHeight = std::max<sal_Int32>( 0, nLeftRightDockingAreaHeight );
194 sal_Int32 nWidth = ( nLeftPos == 0 ) ? 0 : rBorderSpace.Width;
195
196 xRightDockAreaWindow->setPosSize( nLeftPos, rBorderSpace.Y, nWidth, nHeight, awt::PosSize::POSSIZE );
197 xRightDockAreaWindow->setVisible( true );
198 }
199}
200
201
202void ToolbarLayoutManager::doLayout(const ::Size& aContainerSize)
203{
204 SolarMutexResettableGuard aWriteLock;
205 bool bLayoutInProgress( m_bLayoutInProgress );
206 m_bLayoutInProgress = true;
207 awt::Rectangle aDockingArea = putRectangleValueToAWT( m_aDockingArea );
208 aWriteLock.clear();
209
210 if ( bLayoutInProgress )
211 return;
212
213 // Retrieve row/column dependent data from all docked user-interface elements
214 for ( sal_Int32 i = 0; i < DOCKINGAREAS_COUNT; i++ )
215 {
216 bool bReverse( isReverseOrderDockingArea( i ));
217 std::vector< SingleRowColumnWindowData > aRowColumnsWindowData;
218
219 implts_getDockingAreaElementInfos( static_cast<ui::DockingArea>(i), aRowColumnsWindowData );
220
221 sal_Int32 nOffset( 0 );
222 const sal_uInt32 nCount = aRowColumnsWindowData.size();
223 for ( sal_uInt32 j = 0; j < nCount; ++j )
224 {
225 sal_uInt32 nIndex = bReverse ? nCount-j-1 : j;
226 implts_calcWindowPosSizeOnSingleRowColumn( i, nOffset, aRowColumnsWindowData[nIndex], aContainerSize );
227 nOffset += aRowColumnsWindowData[j].nStaticSize;
228 }
229 }
230
231 implts_setDockingAreaWindowSizes( aDockingArea );
232
233 aWriteLock.reset();
234 m_bLayoutDirty = false;
235 m_bLayoutInProgress = false;
236 aWriteLock.clear();
237}
238
239bool ToolbarLayoutManager::implts_isParentWindowVisible() const
240{
241 SolarMutexGuard g;
242 bool bVisible( false );
243 if ( m_xContainerWindow.is() )
244 bVisible = m_xContainerWindow->isVisible();
245
246 return bVisible;
247}
248
249tools::Rectangle ToolbarLayoutManager::implts_calcDockingArea()
250{
251 SolarMutexClearableGuard aReadLock;
252 UIElementVector aWindowVector( m_aUIElements );
253 aReadLock.clear();
254
255 tools::Rectangle aBorderSpace;
256 sal_Int32 nCurrRowColumn( 0 );
257 sal_Int32 nCurrPos( 0 );
258 ui::DockingArea nCurrDockingArea( ui::DockingArea_DOCKINGAREA_TOP );
259 std::vector< sal_Int32 > aRowColumnSizes[DOCKINGAREAS_COUNT];
260
261 // initialize rectangle with zero values!
262 aBorderSpace.setWidth(0);
263 aBorderSpace.setHeight(0);
264
265 aRowColumnSizes[static_cast<int>(nCurrDockingArea)].clear();
266 aRowColumnSizes[static_cast<int>(nCurrDockingArea)].push_back( 0 );
267
268 for (auto const& window : aWindowVector)
269 {
270 if ( window.m_xUIElement.is() )
271 {
272 uno::Reference< awt::XWindow > xWindow( window.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
273 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
274 if ( xWindow.is() && xDockWindow.is() )
275 {
276 SolarMutexGuard aGuard;
277
278 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
279 if ( pWindow && !xDockWindow->isFloating() && window.m_bVisible && !window.m_bMasterHide )
280 {
281 awt::Rectangle aPosSize = xWindow->getPosSize();
282 if ( window.m_aDockedData.m_nDockedArea != nCurrDockingArea )
283 {
284 nCurrDockingArea = window.m_aDockedData.m_nDockedArea;
285 nCurrRowColumn = 0;
286 nCurrPos = 0;
287 aRowColumnSizes[static_cast<int>(nCurrDockingArea)].clear();
288 aRowColumnSizes[static_cast<int>(nCurrDockingArea)].push_back( 0 );
289 }
290
291 if ( window.m_aDockedData.m_nDockedArea == nCurrDockingArea )
292 {
293 if ( isHorizontalDockingArea( window.m_aDockedData.m_nDockedArea ))
294 {
295 if ( window.m_aDockedData.m_aPos.Y > nCurrPos )
296 {
297 ++nCurrRowColumn;
298 nCurrPos = window.m_aDockedData.m_aPos.Y;
299 aRowColumnSizes[static_cast<int>(nCurrDockingArea)].push_back( 0 );
300 }
301
302 if ( aPosSize.Height > aRowColumnSizes[static_cast<int>(nCurrDockingArea)][nCurrRowColumn] )
303 aRowColumnSizes[static_cast<int>(nCurrDockingArea)][nCurrRowColumn] = aPosSize.Height;
304 }
305 else
306 {
307 if ( window.m_aDockedData.m_aPos.X > nCurrPos )
308 {
309 ++nCurrRowColumn;
310 nCurrPos = window.m_aDockedData.m_aPos.X;
311 aRowColumnSizes[static_cast<int>(nCurrDockingArea)].push_back( 0 );
312 }
313
314 if ( aPosSize.Width > aRowColumnSizes[static_cast<int>(nCurrDockingArea)][nCurrRowColumn] )
315 aRowColumnSizes[static_cast<int>(nCurrDockingArea)][nCurrRowColumn] = aPosSize.Width;
316 }
317 }
318 }
319 }
320 }
321 }
322
323 // Sum up max heights from every row/column
324 if ( !aWindowVector.empty() )
325 {
326 for ( sal_Int32 i = 0; i <= sal_Int32(ui::DockingArea_DOCKINGAREA_RIGHT); i++ )
327 {
328 sal_Int32 nSize( 0 );
329 const sal_uInt32 nCount = aRowColumnSizes[i].size();
330 for ( sal_uInt32 j = 0; j < nCount; j++ )
331 nSize += aRowColumnSizes[i][j];
332
333 if ( i == sal_Int32(ui::DockingArea_DOCKINGAREA_TOP) )
334 aBorderSpace.SetTop( nSize );
335 else if ( i == sal_Int32(ui::DockingArea_DOCKINGAREA_BOTTOM) )
336 aBorderSpace.SetBottom( nSize );
337 else if ( i == sal_Int32(ui::DockingArea_DOCKINGAREA_LEFT) )
338 aBorderSpace.SetLeft( nSize );
339 else
340 aBorderSpace.SetRight( nSize );
341 }
342 }
343
344 return aBorderSpace;
345}
346
347void ToolbarLayoutManager::reset()
348{
349 {
350 SolarMutexGuard aWriteLock;
351 m_xModuleCfgMgr.clear();
352 m_xDocCfgMgr.clear();
353 m_ePreviewDetection = PREVIEWFRAME_UNKNOWN;
354 m_bComponentAttached = false;
355 }
356
357 destroyToolbars();
358 resetDockingArea();
359}
360
361void ToolbarLayoutManager::attach(
362 const uno::Reference< frame::XFrame >& xFrame,
363 const uno::Reference< ui::XUIConfigurationManager >& xModuleCfgMgr,
364 const uno::Reference< ui::XUIConfigurationManager >& xDocCfgMgr,
365 const uno::Reference< container::XNameAccess >& xPersistentWindowState )
366{
367 // reset toolbar manager if we lose our current frame
368 if ( m_xFrame.is() && m_xFrame != xFrame )
369 reset();
370
371 SolarMutexGuard g;
372 m_xFrame = xFrame;
373 m_xModuleCfgMgr = xModuleCfgMgr;
374 m_xDocCfgMgr = xDocCfgMgr;
375 m_xPersistentWindowState = xPersistentWindowState;
376 m_bComponentAttached = true;
377}
378
379bool ToolbarLayoutManager::isPreviewFrame()
380{
381 SolarMutexGuard g;
382 if (m_ePreviewDetection == PREVIEWFRAME_UNKNOWN)
383 {
384 uno::Reference< frame::XFrame > xFrame( m_xFrame );
385
386 uno::Reference< frame::XModel > xModel( impl_getModelFromFrame( xFrame ));
387
388 m_ePreviewDetection = (implts_isPreviewModel( xModel ) ? PREVIEWFRAME_YES : PREVIEWFRAME_NO);
389 }
390 return m_ePreviewDetection == PREVIEWFRAME_YES;
391}
392
393void ToolbarLayoutManager::createStaticToolbars()
394{
395 resetDockingArea();
396 implts_createCustomToolBars();
397 implts_createAddonsToolBars();
398 implts_createNonContextSensitiveToolBars();
399 implts_sortUIElements();
400}
401
402bool ToolbarLayoutManager::requestToolbar( const OUString& rResourceURL )
403{
404 if (isPreviewFrame())
405 return false; // no toolbars for preview frame!
406
407 bool bNotify( false );
408 bool bMustCallCreate( false );
409 uno::Reference< ui::XUIElement > xUIElement;
410
411 UIElement aRequestedToolbar = impl_findToolbar( rResourceURL );
412 if ( aRequestedToolbar.m_aName != rResourceURL )
413 {
414 bMustCallCreate = true;
415 aRequestedToolbar.m_aName = rResourceURL;
416 aRequestedToolbar.m_aType = UIRESOURCETYPE_TOOLBAR"toolbar";
417 aRequestedToolbar.m_xUIElement = xUIElement;
418 implts_readWindowStateData( rResourceURL, aRequestedToolbar );
419 }
420
421 xUIElement = aRequestedToolbar.m_xUIElement;
422 if ( !xUIElement.is() )
423 bMustCallCreate = true;
424
425 bool bCreateOrShowToolbar( aRequestedToolbar.m_bVisible && !aRequestedToolbar.m_bMasterHide );
426
427 if ( bCreateOrShowToolbar )
428 bNotify = bMustCallCreate ? createToolbar( rResourceURL ) : showToolbar( rResourceURL );
429
430 return bNotify;
431}
432
433bool ToolbarLayoutManager::createToolbar( const OUString& rResourceURL )
434{
435 bool bNotify( false );
436
437 uno::Reference<frame::XFrame> xFrame;
438 uno::Reference<awt::XWindow2> xContainerWindow;
439 {
440 SolarMutexGuard aReadLock;
441 xFrame.set(m_xFrame);
442 xContainerWindow.set(m_xContainerWindow);
443 }
444
445 if ( !xFrame.is() || !xContainerWindow.is() )
446 return false;
447
448 UIElement aToolbarElement = implts_findToolbar( rResourceURL );
449 if ( !aToolbarElement.m_xUIElement.is() )
450 {
451 uno::Reference< ui::XUIElement > xUIElement;
452
453 uno::Sequence< beans::PropertyValue > aPropSeq( 2 );
454 aPropSeq[0].Name = "Frame";
455 aPropSeq[0].Value <<= xFrame;
456 aPropSeq[1].Name = "Persistent";
457 aPropSeq[1].Value <<= true;
458 uno::Reference<ui::XUIElementFactory> xUIElementFactory;
459 {
460 SolarMutexGuard aReadLock;
461 xUIElementFactory.set(m_xUIElementFactoryManager);
462 }
463
464 implts_setToolbarCreation();
465 try
466 {
467 if ( xUIElementFactory.is() )
468 xUIElement = xUIElementFactory->createUIElement( rResourceURL, aPropSeq );
469 }
470 catch (const container::NoSuchElementException&)
471 {
472 }
473 catch (const lang::IllegalArgumentException&)
474 {
475 }
476 implts_setToolbarCreation( false );
477
478 if ( xUIElement.is() )
479 {
480 uno::Reference< awt::XWindow > xWindow( xUIElement->getRealInterface(), uno::UNO_QUERY );
481 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
482 if ( xDockWindow.is() && xWindow.is() )
483 {
484 try
485 {
486 xDockWindow->addDockableWindowListener( uno::Reference< awt::XDockableWindowListener >(
487 static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
488 xWindow->addWindowListener( uno::Reference< awt::XWindowListener >(
489 static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
490 xDockWindow->enableDocking( true );
491 }
492 catch (const uno::Exception&)
493 {
494 }
495 }
496
497 bool bVisible = false;
498 bool bFloating = false;
499
500 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
501 {
502 SolarMutexClearableGuard aWriteLock;
503
504 UIElement& rElement = impl_findToolbar(rResourceURL);
505 if (rElement.m_xUIElement.is())
506 {
507 // somebody else must have created it while we released
508 // the SolarMutex - just dispose our new instance and
509 // do nothing. (We have to dispose either the new or the
510 // existing m_xUIElement.)
511 aWriteLock.clear();
512 uno::Reference<lang::XComponent> const xC(xUIElement, uno::UNO_QUERY);
513 xC->dispose();
514 return false;
515 }
516 if (!rElement.m_aName.isEmpty())
517 {
518 // Reuse a local entry so we are able to use the latest
519 // UI changes for this document.
520 implts_setElementData(rElement, xDockWindow);
521 rElement.m_xUIElement = xUIElement;
522 bVisible = rElement.m_bVisible;
523 bFloating = rElement.m_bFloating;
524 }
525 else
526 {
527 // Create new UI element and try to read its state data
528 UIElement aNewToolbar(rResourceURL, UIRESOURCETYPE_TOOLBAR"toolbar", xUIElement);
529 implts_readWindowStateData(rResourceURL, aNewToolbar);
530 implts_setElementData(aNewToolbar, xDockWindow);
531 implts_insertToolbar(aNewToolbar);
532 bVisible = aNewToolbar.m_bVisible;
533 bFloating = rElement.m_bFloating;
534 }
535 }
536 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
537
538 // set toolbar menu style according to customize command state
539 SvtCommandOptions aCmdOptions;
540
541 SolarMutexGuard aGuard;
542 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
543 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
544 {
545 ToolBox* pToolbar = static_cast<ToolBox *>(pWindow.get());
546 ToolBoxMenuType nMenuType = pToolbar->GetMenuType();
547 if ( aCmdOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED, "ConfigureDialog" ))
548 pToolbar->SetMenuType( nMenuType & ~ToolBoxMenuType::Customize );
549 else
550 pToolbar->SetMenuType( nMenuType | ToolBoxMenuType::Customize );
551 }
552 bNotify = true;
553
554 implts_sortUIElements();
555
556 if ( bVisible && !bFloating )
557 implts_setLayoutDirty();
558 }
559 }
560
561 return bNotify;
562}
563
564bool ToolbarLayoutManager::destroyToolbar( const OUString& rResourceURL )
565{
566 uno::Reference< lang::XComponent > xComponent;
567
568 bool bNotify( false );
569 bool bMustBeSorted( false );
570 bool bMustLayouted( false );
571 bool bMustBeDestroyed( !rResourceURL.startsWith("private:resource/toolbar/addon_") );
572
573 {
574 SolarMutexGuard aWriteLock;
575 for (auto & elem : m_aUIElements)
576 {
577 if (elem.m_aName == rResourceURL)
578 {
579 xComponent.set(elem.m_xUIElement, uno::UNO_QUERY);
580 if (bMustBeDestroyed)
581 elem.m_xUIElement.clear();
582 else
583 elem.m_bVisible = false;
584 break;
585 }
586 }
587 }
588
589 uno::Reference< ui::XUIElement > xUIElement( xComponent, uno::UNO_QUERY );
590 if ( xUIElement.is() )
591 {
592 uno::Reference< awt::XWindow > xWindow( xUIElement->getRealInterface(), uno::UNO_QUERY );
593 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
594
595 if ( bMustBeDestroyed )
596 {
597 try
598 {
599 if ( xWindow.is() )
600 xWindow->removeWindowListener( uno::Reference< awt::XWindowListener >(
601 static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
602 }
603 catch (const uno::Exception&)
604 {
605 }
606
607 try
608 {
609 if ( xDockWindow.is() )
610 xDockWindow->removeDockableWindowListener( uno::Reference< awt::XDockableWindowListener >(
611 static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
612 }
613 catch (const uno::Exception&)
614 {
615 }
616 }
617 else
618 {
619 if ( xWindow.is() )
620 xWindow->setVisible( false );
621 bNotify = true;
622 }
623
624 if ( !xDockWindow->isFloating() )
625 bMustLayouted = true;
626 bMustBeSorted = true;
627 }
628
629 if ( bMustBeDestroyed )
630 {
631 if ( xComponent.is() )
632 xComponent->dispose();
633 bNotify = true;
634 }
635
636 if ( bMustLayouted )
637 implts_setLayoutDirty();
638
639 if ( bMustBeSorted )
640 implts_sortUIElements();
641
642 return bNotify;
643}
644
645void ToolbarLayoutManager::destroyToolbars()
646{
647 UIElementVector aUIElementVector;
648 implts_getUIElementVectorCopy( aUIElementVector );
649
650 {
651 SolarMutexGuard aWriteLock;
652 m_aUIElements.clear();
653 m_bLayoutDirty = true;
654 }
655
656 for (auto const& elem : aUIElementVector)
657 {
658 uno::Reference< lang::XComponent > xComponent( elem.m_xUIElement, uno::UNO_QUERY );
659 if ( xComponent.is() )
660 xComponent->dispose();
661 }
662}
663
664bool ToolbarLayoutManager::showToolbar( const OUString& rResourceURL )
665{
666 UIElement aUIElement = implts_findToolbar( rResourceURL );
667
668 SolarMutexGuard aGuard;
669 vcl::Window* pWindow = getWindowFromXUIElement( aUIElement.m_xUIElement );
670
671 // Addons appear to need to be populated at start, but we don't
672 // want to populate them with (scaled) images until later.
673 AddonsToolBarWrapper *pAddOns;
674 pAddOns = dynamic_cast<AddonsToolBarWrapper *>( aUIElement.m_xUIElement.get());
675 if (pAddOns)
676 pAddOns->populateImages();
677
678 if ( pWindow )
679 {
680 if ( !aUIElement.m_bFloating )
681 implts_setLayoutDirty();
682 else
683 pWindow->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
684
685 aUIElement.m_bVisible = true;
686 implts_writeWindowStateData( aUIElement );
687 implts_setToolbar( aUIElement );
688 implts_sortUIElements();
689 return true;
690 }
691
692 return false;
693}
694
695bool ToolbarLayoutManager::hideToolbar( const OUString& rResourceURL )
696{
697 UIElement aUIElement = implts_findToolbar( rResourceURL );
698
699 SolarMutexGuard aGuard;
700 vcl::Window* pWindow = getWindowFromXUIElement( aUIElement.m_xUIElement );
701 if ( pWindow )
702 {
703 pWindow->Show( false );
704 if ( !aUIElement.m_bFloating )
705 implts_setLayoutDirty();
706
707 aUIElement.m_bVisible = false;
708 implts_writeWindowStateData( aUIElement );
709 implts_setToolbar( aUIElement );
710 return true;
711 }
712
713 return false;
714}
715
716void ToolbarLayoutManager::refreshToolbarsVisibility( bool bAutomaticToolbars )
717{
718 UIElementVector aUIElementVector;
719
720 if ( !bAutomaticToolbars )
721 return;
722
723 implts_getUIElementVectorCopy( aUIElementVector );
724
725 UIElement aUIElement;
726 SolarMutexGuard aGuard;
727 for (auto const& elem : aUIElementVector)
728 {
729 if ( implts_readWindowStateData( elem.m_aName, aUIElement ) &&
730 ( elem.m_bVisible != aUIElement.m_bVisible ) && !elem.m_bMasterHide )
731 {
732 SolarMutexGuard g;
733 UIElement& rUIElement = impl_findToolbar( elem.m_aName );
734 if ( rUIElement.m_aName == elem.m_aName )
735 {
736 rUIElement.m_bVisible = aUIElement.m_bVisible;
737 implts_setLayoutDirty();
738 }
739 }
740 }
741}
742
743void ToolbarLayoutManager::setFloatingToolbarsVisibility( bool bVisible )
744{
745 UIElementVector aUIElementVector;
746 implts_getUIElementVectorCopy( aUIElementVector );
747
748 SolarMutexGuard aGuard;
749 for (auto const& elem : aUIElementVector)
750 {
751 vcl::Window* pWindow = getWindowFromXUIElement( elem.m_xUIElement );
752 if ( pWindow && elem.m_bFloating )
753 {
754 if ( bVisible )
755 {
756 if ( elem.m_bVisible && !elem.m_bMasterHide )
757 pWindow->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
758 }
759 else
760 pWindow->Show( false );
761 }
762 }
763}
764
765void ToolbarLayoutManager::setVisible( bool bVisible )
766{
767 UIElementVector aUIElementVector;
768 implts_getUIElementVectorCopy( aUIElementVector );
769
770 SolarMutexGuard aGuard;
771 for (auto & elem : aUIElementVector)
772 {
773 if (!elem.m_bFloating)
774 {
775 elem.m_bMasterHide = !bVisible;
776 implts_setToolbar(elem);
777 implts_setLayoutDirty();
778 }
779
780 vcl::Window* pWindow = getWindowFromXUIElement( elem.m_xUIElement );
781 if ( pWindow )
782 {
783 bool bSetVisible( elem.m_bVisible && bVisible );
784 if ( !bSetVisible )
785 pWindow->Hide();
786 else
787 {
788 if ( elem.m_bFloating )
789 pWindow->Show(true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
790 }
791 }
792 }
793
794 if ( !bVisible )
795 resetDockingArea();
796}
797
798bool ToolbarLayoutManager::dockToolbar( const OUString& rResourceURL, ui::DockingArea eDockingArea, const awt::Point& aPos )
799{
800 UIElement aUIElement = implts_findToolbar( rResourceURL );
801
802 if ( aUIElement.m_xUIElement.is() )
803 {
804 try
805 {
806 uno::Reference< awt::XWindow > xWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
807 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
808 if ( xDockWindow.is() )
809 {
810 if ( eDockingArea != ui::DockingArea_DOCKINGAREA_DEFAULT )
811 aUIElement.m_aDockedData.m_nDockedArea = eDockingArea;
812
813 if ( !isDefaultPos( aPos ))
814 aUIElement.m_aDockedData.m_aPos = aPos;
815
816 if ( !xDockWindow->isFloating() )
817 {
818 vcl::Window* pWindow( nullptr );
819 ToolBox* pToolBox( nullptr );
820
821 {
822 SolarMutexGuard aGuard;
823 pWindow = VCLUnoHelper::GetWindow( xWindow ).get();
824 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
825 {
826 pToolBox = static_cast<ToolBox *>(pWindow);
827
828 // We have to set the alignment of the toolbox. It's possible that the toolbox is moved from a
829 // horizontal to a vertical docking area!
830 pToolBox->SetAlign( ImplConvertAlignment( aUIElement.m_aDockedData.m_nDockedArea ));
831 }
832 }
833
834 if ( hasDefaultPosValue( aUIElement.m_aDockedData.m_aPos ))
835 {
836 // Docking on its default position without a preset position -
837 // we have to find a good place for it.
838 ::Size aSize;
839
840 SolarMutexGuard aGuard;
841 {
842 if (pToolBox)
843 aSize = pToolBox->CalcWindowSizePixel( 1, ImplConvertAlignment( aUIElement.m_aDockedData.m_nDockedArea ) );
844 else if (pWindow)
845 aSize = pWindow->GetSizePixel();
846 }
847
848 ::Point aPixelPos;
849 awt::Point aDockPos;
850 implts_findNextDockingPos(aUIElement.m_aDockedData.m_nDockedArea, aSize, aDockPos, aPixelPos );
851 aUIElement.m_aDockedData.m_aPos = aDockPos;
852 }
853 }
854
855 implts_setToolbar( aUIElement );
856
857 if ( xDockWindow->isFloating() )
858 {
859 // ATTENTION: This will call toggleFloatingMode() via notifications which
860 // sets the floating member of the UIElement correctly!
861 xDockWindow->setFloatingMode( false );
862 }
863 else
864 {
865 implts_writeWindowStateData( aUIElement );
866 implts_sortUIElements();
867
868 if ( aUIElement.m_bVisible )
869 implts_setLayoutDirty();
870 }
871 return true;
872 }
873 }
874 catch (const lang::DisposedException&)
875 {
876 }
877 }
878
879 return false;
880}
881
882bool ToolbarLayoutManager::dockAllToolbars()
883{
884 std::vector< OUString > aToolBarNameVector;
885
886 {
887 SolarMutexGuard aReadLock;
888 for (auto const& elem : m_aUIElements)
889 {
890 if (elem.m_aType == "toolbar" && elem.m_xUIElement.is() && elem.m_bFloating
891 && elem.m_bVisible)
892 aToolBarNameVector.push_back(elem.m_aName);
893 }
894 }
895
896 bool bResult(true);
897 const sal_uInt32 nCount = aToolBarNameVector.size();
898 for ( sal_uInt32 i = 0; i < nCount; ++i )
899 {
900 awt::Point aPoint;
901 aPoint.X = aPoint.Y = SAL_MAX_INT32((sal_Int32) 0x7FFFFFFF);
902 bResult &= dockToolbar( aToolBarNameVector[i], ui::DockingArea_DOCKINGAREA_DEFAULT, aPoint );
903 }
904
905 return bResult;
906}
907
908void ToolbarLayoutManager::childWindowEvent( VclSimpleEvent const * pEvent )
909{
910 // To enable toolbar controllers to change their image when a sub-toolbar function
911 // is activated, we need this mechanism. We have NO connection between these toolbars
912 // anymore!
913 auto pWindowEvent = dynamic_cast< const VclWindowEvent* >(pEvent);
914 if (!pWindowEvent)
915 return;
916
917 if ( pEvent->GetId() == VclEventId::ToolboxSelect )
918 {
919 OUString aToolbarName;
920 OUString aCommand;
921 ToolBox* pToolBox = getToolboxPtr( pWindowEvent->GetWindow() );
922
923 if ( pToolBox )
924 {
925 aToolbarName = retrieveToolbarNameFromHelpURL( pToolBox );
926 sal_uInt16 nId = pToolBox->GetCurItemId();
927 if ( nId > 0 )
928 aCommand = pToolBox->GetItemCommand( nId );
929 }
930
931 if ( !aToolbarName.isEmpty() && !aCommand.isEmpty() )
932 {
933 SolarMutexClearableGuard aReadLock;
934 ::std::vector< uno::Reference< ui::XUIFunctionListener > > aListenerArray;
935
936 for (auto const& elem : m_aUIElements)
937 {
938 if ( elem.m_xUIElement.is() )
939 {
940 uno::Reference< ui::XUIFunctionListener > xListener( elem.m_xUIElement, uno::UNO_QUERY );
941 if ( xListener.is() )
942 aListenerArray.push_back( xListener );
943 }
944 }
945 aReadLock.clear();
946
947 const sal_uInt32 nCount = aListenerArray.size();
948 for ( sal_uInt32 i = 0; i < nCount; ++i )
949 {
950 try
951 {
952 aListenerArray[i]->functionExecute( aToolbarName, aCommand );
953 }
954 catch (const uno::RuntimeException&)
955 {
956 throw;
957 }
958 catch (const uno::Exception&)
959 {
960 }
961 }
962 }
963 }
964 else if ( pEvent->GetId() == VclEventId::ToolboxFormatChanged )
965 {
966 if ( !implts_isToolbarCreationActive() )
967 {
968 ToolBox* pToolBox = getToolboxPtr( static_cast<VclWindowEvent const *>(pEvent)->GetWindow() );
969 if ( pToolBox )
970 {
971 OUString aToolbarName = retrieveToolbarNameFromHelpURL( pToolBox );
972 if ( !aToolbarName.isEmpty() )
973 {
974 OUString aToolbarUrl = "private:resource/toolbar/" + aToolbarName;
975
976 UIElement aToolbar = implts_findToolbar( aToolbarUrl );
977 if ( aToolbar.m_xUIElement.is() && !aToolbar.m_bFloating )
978 {
979 implts_setLayoutDirty();
980 m_pParentLayouter->requestLayout();
981 }
982 }
983 }
984 }
985 }
986}
987
988void ToolbarLayoutManager::resetDockingArea()
989{
990 SolarMutexClearableGuard aReadLock;
991 uno::Reference< awt::XWindow > xTopDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] );
992 uno::Reference< awt::XWindow > xLeftDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] );
993 uno::Reference< awt::XWindow > xRightDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)] );
994 uno::Reference< awt::XWindow > xBottomDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)] );
995 aReadLock.clear();
996
997 if ( xTopDockingWindow.is() )
998 xTopDockingWindow->setPosSize( 0, 0, 0, 0, awt::PosSize::POSSIZE );
999 if ( xLeftDockingWindow.is() )
1000 xLeftDockingWindow->setPosSize( 0, 0, 0, 0, awt::PosSize::POSSIZE );
1001 if ( xRightDockingWindow.is() )
1002 xRightDockingWindow->setPosSize( 0, 0, 0, 0, awt::PosSize::POSSIZE );
1003 if ( xBottomDockingWindow.is() )
1004 xBottomDockingWindow->setPosSize( 0, 0, 0, 0, awt::PosSize::POSSIZE );
1005}
1006
1007void ToolbarLayoutManager::setParentWindow(
1008 const uno::Reference< awt::XWindowPeer >& xParentWindow )
1009{
1010 static const char DOCKINGAREASTRING[] = "dockingarea";
1011
1012 uno::Reference< awt::XWindow > xTopDockWindow( createToolkitWindow( m_xContext, xParentWindow, DOCKINGAREASTRING ), uno::UNO_QUERY );
1013 uno::Reference< awt::XWindow > xLeftDockWindow( createToolkitWindow( m_xContext, xParentWindow, DOCKINGAREASTRING ), uno::UNO_QUERY );
1014 uno::Reference< awt::XWindow > xRightDockWindow( createToolkitWindow( m_xContext, xParentWindow, DOCKINGAREASTRING ), uno::UNO_QUERY );
1015 uno::Reference< awt::XWindow > xBottomDockWindow( createToolkitWindow( m_xContext, xParentWindow, DOCKINGAREASTRING ), uno::UNO_QUERY );
1016
1017 {
1018 SolarMutexGuard aWriteLock;
1019 m_xContainerWindow.set(xParentWindow, uno::UNO_QUERY);
1020 m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] = xTopDockWindow;
1021 m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] = xLeftDockWindow;
1022 m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)] = xRightDockWindow;
1023 m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)] = xBottomDockWindow;
1024 }
1025
1026 if ( xParentWindow.is() )
1027 {
1028 SolarMutexGuard aGuard;
1029 VclPtr< ::DockingAreaWindow > pWindow = dynamic_cast< ::DockingAreaWindow* >(VCLUnoHelper::GetWindow( xTopDockWindow ).get() );
1030 if( pWindow )
1031 pWindow->SetAlign( WindowAlign::Top );
1032 pWindow = dynamic_cast< ::DockingAreaWindow* >(VCLUnoHelper::GetWindow( xBottomDockWindow ).get() );
1033 if( pWindow )
1034 pWindow->SetAlign( WindowAlign::Bottom );
1035 pWindow = dynamic_cast< ::DockingAreaWindow* >(VCLUnoHelper::GetWindow( xLeftDockWindow ).get() );
1036 if( pWindow )
1037 pWindow->SetAlign( WindowAlign::Left );
1038 pWindow = dynamic_cast< ::DockingAreaWindow* >(VCLUnoHelper::GetWindow( xRightDockWindow ).get() );
1039 if( pWindow )
1040 pWindow->SetAlign( WindowAlign::Right );
1041 implts_reparentToolbars();
1042 }
1043 else
1044 {
1045 destroyToolbars();
1046 resetDockingArea();
1047 }
1048}
1049
1050void ToolbarLayoutManager::setDockingAreaOffsets( const ::tools::Rectangle& rOffsets )
1051{
1052 SolarMutexGuard g;
1053 m_aDockingAreaOffsets = rOffsets;
1054 m_bLayoutDirty = true;
1055}
1056
1057OUString ToolbarLayoutManager::implts_generateGenericAddonToolbarTitle( sal_Int32 nNumber ) const
1058{
1059 OUString aAddonGenericTitle(FwkResId(STR_TOOLBAR_TITLE_ADDONreinterpret_cast<char const *>("STR_TOOLBAR_TITLE_ADDON"
"\004" u8"Add-On %num%")
));
1060 const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
1061
1062 OUString aNumStr = rI18nHelper.GetNum( nNumber, 0, false, false );
1063 aAddonGenericTitle = aAddonGenericTitle.replaceFirst( "%num%", aNumStr );
1064
1065 return aAddonGenericTitle;
1066}
1067
1068void ToolbarLayoutManager::implts_createAddonsToolBars()
1069{
1070 SolarMutexClearableGuard aWriteLock;
1071 if ( !m_pAddonOptions )
1072 m_pAddonOptions.reset( new AddonsOptions );
1073
1074 uno::Reference< ui::XUIElementFactory > xUIElementFactory( m_xUIElementFactoryManager );
1075 uno::Reference< frame::XFrame > xFrame( m_xFrame );
1076 aWriteLock.clear();
1077
1078 if (isPreviewFrame())
1079 return; // no addon toolbars for preview frame!
1080
1081 uno::Sequence< uno::Sequence< beans::PropertyValue > > aAddonToolBarData;
1082 uno::Reference< ui::XUIElement > xUIElement;
1083
1084 sal_uInt32 nCount = m_pAddonOptions->GetAddonsToolBarCount();
1085
1086 uno::Sequence< beans::PropertyValue > aPropSeq( 2 );
1087 aPropSeq[0].Name = "Frame";
1088 aPropSeq[0].Value <<= xFrame;
1089 aPropSeq[1].Name = "ConfigurationData";
1090 for ( sal_uInt32 i = 0; i < nCount; i++ )
1091 {
1092 OUString aAddonToolBarName( "private:resource/toolbar/addon_" +
1093 m_pAddonOptions->GetAddonsToolbarResourceName(i) );
1094 aAddonToolBarData = m_pAddonOptions->GetAddonsToolBarPart( i );
1095 aPropSeq[1].Value <<= aAddonToolBarData;
1096
1097 UIElement aElement = implts_findToolbar( aAddonToolBarName );
1098
1099 // #i79828
1100 // It's now possible that we are called more than once. Be sure to not create
1101 // add-on toolbars more than once!
1102 if ( aElement.m_xUIElement.is() )
1103 continue;
1104
1105 try
1106 {
1107 xUIElement = xUIElementFactory->createUIElement( aAddonToolBarName, aPropSeq );
1108 if ( xUIElement.is() )
1109 {
1110 uno::Reference< awt::XDockableWindow > xDockWindow( xUIElement->getRealInterface(), uno::UNO_QUERY );
1111 if ( xDockWindow.is() )
1112 {
1113 try
1114 {
1115 xDockWindow->addDockableWindowListener( uno::Reference< awt::XDockableWindowListener >( static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
1116 xDockWindow->enableDocking( true );
1117 uno::Reference< awt::XWindow > xWindow( xDockWindow, uno::UNO_QUERY );
1118 if ( xWindow.is() )
1119 xWindow->addWindowListener( uno::Reference< awt::XWindowListener >( static_cast< OWeakObject * >( this ), uno::UNO_QUERY ));
1120 }
1121 catch (const uno::Exception&)
1122 {
1123 }
1124 }
1125
1126 OUString aGenericAddonTitle = implts_generateGenericAddonToolbarTitle( i+1 );
1127
1128 if ( !aElement.m_aName.isEmpty() )
1129 {
1130 // Reuse a local entry so we are able to use the latest
1131 // UI changes for this document.
1132 implts_setElementData( aElement, xDockWindow );
1133 aElement.m_xUIElement = xUIElement;
1134 if ( aElement.m_aUIName.isEmpty() )
1135 {
1136 aElement.m_aUIName = aGenericAddonTitle;
1137 implts_writeWindowStateData( aElement );
1138 }
1139 }
1140 else
1141 {
1142 // Create new UI element and try to read its state data
1143 UIElement aNewToolbar( aAddonToolBarName, "toolbar", xUIElement );
1144 aNewToolbar.m_bFloating = true;
1145 implts_readWindowStateData( aAddonToolBarName, aNewToolbar );
1146 implts_setElementData( aNewToolbar, xDockWindow );
1147 if ( aNewToolbar.m_aUIName.isEmpty() )
1148 {
1149 aNewToolbar.m_aUIName = aGenericAddonTitle;
1150 implts_writeWindowStateData( aNewToolbar );
1151 }
1152 implts_insertToolbar( aNewToolbar );
1153 }
1154
1155 uno::Reference< awt::XWindow > xWindow( xDockWindow, uno::UNO_QUERY );
1156 if ( xWindow.is() )
1157 {
1158 // Set generic title for add-on toolbar
1159 SolarMutexGuard aGuard;
1160 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
1161 if ( pWindow->GetText().isEmpty() )
1162 pWindow->SetText( aGenericAddonTitle );
1163 if ( pWindow->GetType() == WindowType::TOOLBOX )
1164 {
1165 ToolBox* pToolbar = static_cast<ToolBox *>(pWindow.get());
1166 pToolbar->SetMenuType();
1167 }
1168 }
1169 }
1170 }
1171 catch (const container::NoSuchElementException&)
1172 {
1173 }
1174 catch (const lang::IllegalArgumentException&)
1175 {
1176 }
1177 }
1178}
1179
1180void ToolbarLayoutManager::implts_createCustomToolBars()
1181{
1182 SolarMutexClearableGuard aReadLock;
1183 if ( !m_bComponentAttached )
1184 return;
1185
1186 uno::Reference< frame::XFrame > xFrame( m_xFrame );
1187 uno::Reference< ui::XUIConfigurationManager > xModuleCfgMgr = m_xModuleCfgMgr;
1188 uno::Reference< ui::XUIConfigurationManager > xDocCfgMgr = m_xDocCfgMgr;
1189 aReadLock.clear();
1190
1191 if ( !xFrame.is() )
1192 return;
1193
1194 if (isPreviewFrame())
1195 return; // no custom toolbars for preview frame!
1196
1197 uno::Sequence< uno::Sequence< beans::PropertyValue > > aTbxSeq;
1198 if ( xDocCfgMgr.is() )
1199 {
1200 aTbxSeq = xDocCfgMgr->getUIElementsInfo( ui::UIElementType::TOOLBAR );
1201 implts_createCustomToolBars( aTbxSeq ); // first create all document based toolbars
1202 }
1203 if ( xModuleCfgMgr.is() )
1204 {
1205 aTbxSeq = xModuleCfgMgr->getUIElementsInfo( ui::UIElementType::TOOLBAR );
1206 implts_createCustomToolBars( aTbxSeq ); // second create module based toolbars
1207 }
1208}
1209
1210void ToolbarLayoutManager::implts_createNonContextSensitiveToolBars()
1211{
1212 SolarMutexClearableGuard aReadLock;
1213
1214 if ( !m_xPersistentWindowState.is() || !m_xFrame.is() || !m_bComponentAttached )
1215 return;
1216
1217 uno::Reference< container::XNameAccess > xPersistentWindowState( m_xPersistentWindowState );
1218 aReadLock.clear();
1219
1220 if (isPreviewFrame())
1221 return;
1222
1223 std::vector< OUString > aMakeVisibleToolbars;
1224
1225 try
1226 {
1227 const uno::Sequence< OUString > aToolbarNames = xPersistentWindowState->getElementNames();
1228
1229 if ( aToolbarNames.hasElements() )
1230 {
1231 OUString aElementType;
1232 OUString aElementName;
1233
1234 aMakeVisibleToolbars.reserve(aToolbarNames.getLength());
1235
1236 SolarMutexGuard g;
1237
1238 for ( OUString const & aName : aToolbarNames )
1239 {
1240 parseResourceURL( aName, aElementType, aElementName );
1241
1242 // Check that we only create:
1243 // - Toolbars (the statusbar is also member of the persistent window state)
1244 // - Not custom toolbars, there are created with their own method (implts_createCustomToolbars)
1245 if ( aElementType.equalsIgnoreAsciiCase("toolbar") &&
1246 aElementName.indexOf( "custom_" ) == -1 )
1247 {
1248 UIElement aNewToolbar = implts_findToolbar( aName );
1249 bool bFound = ( aNewToolbar.m_aName == aName );
1250 if ( !bFound )
1251 implts_readWindowStateData( aName, aNewToolbar );
1252
1253 if ( aNewToolbar.m_bVisible && !aNewToolbar.m_bContextSensitive )
1254 {
1255 if ( !bFound )
1256 implts_insertToolbar( aNewToolbar );
1257 aMakeVisibleToolbars.push_back( aName );
1258 }
1259 }
1260 }
1261 }
1262 }
1263 catch (const uno::RuntimeException&)
1264 {
1265 throw;
1266 }
1267 catch (const uno::Exception&)
1268 {
1269 }
1270
1271 for (auto const& rURL : aMakeVisibleToolbars)
1272 {
1273 requestToolbar(rURL);
1274 }
1275}
1276
1277void ToolbarLayoutManager::implts_createCustomToolBars( const uno::Sequence< uno::Sequence< beans::PropertyValue > >& aTbxSeqSeq )
1278{
1279 for ( const uno::Sequence< beans::PropertyValue >& rTbxSeq : aTbxSeqSeq )
1280 {
1281 OUString aTbxResName;
1282 OUString aTbxTitle;
1283 for ( const beans::PropertyValue& rProp : rTbxSeq )
1284 {
1285 if ( rProp.Name == "ResourceURL" )
1286 rProp.Value >>= aTbxResName;
1287 else if ( rProp.Name == "UIName" )
1288 rProp.Value >>= aTbxTitle;
1289 }
1290
1291 // Only create custom toolbars. Their name have to start with "custom_"!
1292 if ( !aTbxResName.isEmpty() && ( aTbxResName.indexOf( "custom_" ) != -1 ) )
1293 implts_createCustomToolBar( aTbxResName, aTbxTitle );
1294 }
1295}
1296
1297void ToolbarLayoutManager::implts_createCustomToolBar( const OUString& aTbxResName, const OUString& aTitle )
1298{
1299 if ( aTbxResName.isEmpty() )
1300 return;
1301
1302 if ( !createToolbar( aTbxResName ) )
1303 SAL_WARN("fwk.uielement", "ToolbarLayoutManager cannot create custom toolbar")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "fwk.uielement")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "ToolbarLayoutManager cannot create custom toolbar"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("fwk.uielement"
), ("/home/maarten/src/libreoffice/core/framework/source/layoutmanager/toolbarlayoutmanager.cxx"
":" "1303" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "ToolbarLayoutManager cannot create custom toolbar"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "ToolbarLayoutManager cannot create custom toolbar"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("fwk.uielement"
), ("/home/maarten/src/libreoffice/core/framework/source/layoutmanager/toolbarlayoutmanager.cxx"
":" "1303" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "ToolbarLayoutManager cannot create custom toolbar"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("fwk.uielement"
), ("/home/maarten/src/libreoffice/core/framework/source/layoutmanager/toolbarlayoutmanager.cxx"
":" "1303" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "ToolbarLayoutManager cannot create custom toolbar"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "ToolbarLayoutManager cannot create custom toolbar"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("fwk.uielement"
), ("/home/maarten/src/libreoffice/core/framework/source/layoutmanager/toolbarlayoutmanager.cxx"
":" "1303" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1304
1305 uno::Reference< ui::XUIElement > xUIElement = getToolbar( aTbxResName );
1306
1307 if ( !aTitle.isEmpty() && xUIElement.is() )
1308 {
1309 SolarMutexGuard aGuard;
1310
1311 vcl::Window* pWindow = getWindowFromXUIElement( xUIElement );
1312 if ( pWindow )
1313 pWindow->SetText( aTitle );
1314 }
1315}
1316
1317void ToolbarLayoutManager::implts_reparentToolbars()
1318{
1319 SolarMutexClearableGuard aWriteLock;
1320 UIElementVector aUIElementVector = m_aUIElements;
1321 VclPtr<vcl::Window> pContainerWindow = VCLUnoHelper::GetWindow( m_xContainerWindow );
1322 VclPtr<vcl::Window> pTopDockWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] );
1323 VclPtr<vcl::Window> pBottomDockWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)] );
1324 VclPtr<vcl::Window> pLeftDockWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] );
1325 VclPtr<vcl::Window> pRightDockWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)] );
1326 aWriteLock.clear();
1327
1328 SolarMutexGuard aGuard;
1329 if ( !pContainerWindow )
1330 return;
1331
1332 for (auto const& elem : aUIElementVector)
1333 {
1334 uno::Reference< ui::XUIElement > xUIElement( elem.m_xUIElement );
1335 if ( xUIElement.is() )
1336 {
1337 uno::Reference< awt::XWindow > xWindow;
1338 try
1339 {
1340 // We have to retrieve the window reference with try/catch as it is
1341 // possible that all elements have been disposed!
1342 xWindow.set( xUIElement->getRealInterface(), uno::UNO_QUERY );
1343 }
1344 catch (const uno::RuntimeException&)
1345 {
1346 throw;
1347 }
1348 catch (const uno::Exception&)
1349 {
1350 }
1351
1352 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
1353 if ( pWindow )
1354 {
1355 // Reparent our child windows according to their current state.
1356 if ( elem.m_bFloating )
1357 pWindow->SetParent( pContainerWindow );
1358 else
1359 {
1360 if ( elem.m_aDockedData.m_nDockedArea == ui::DockingArea_DOCKINGAREA_TOP )
1361 pWindow->SetParent( pTopDockWindow );
1362 else if ( elem.m_aDockedData.m_nDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
1363 pWindow->SetParent( pBottomDockWindow );
1364 else if ( elem.m_aDockedData.m_nDockedArea == ui::DockingArea_DOCKINGAREA_LEFT )
1365 pWindow->SetParent( pLeftDockWindow );
1366 else
1367 pWindow->SetParent( pRightDockWindow );
1368 }
1369 }
1370 }
1371 }
1372}
1373
1374void ToolbarLayoutManager::implts_setToolbarCreation( bool bStart )
1375{
1376 SolarMutexGuard g;
1377 m_bToolbarCreation = bStart;
1378}
1379
1380bool ToolbarLayoutManager::implts_isToolbarCreationActive()
1381{
1382 SolarMutexGuard g;
1383 return m_bToolbarCreation;
1384}
1385
1386void ToolbarLayoutManager::implts_setElementData( UIElement& rElement, const uno::Reference< awt::XDockableWindow >& rDockWindow )
1387{
1388 SolarMutexClearableGuard aReadLock;
1389 bool bShowElement( rElement.m_bVisible && !rElement.m_bMasterHide && implts_isParentWindowVisible() );
1390 aReadLock.clear();
1391
1392 uno::Reference< awt::XWindow2 > xWindow( rDockWindow, uno::UNO_QUERY );
1393
1394 vcl::Window* pWindow( nullptr );
1395 ToolBox* pToolBox( nullptr );
1396
1397 if ( !(rDockWindow.is() && xWindow.is()) )
1398 return;
1399
1400 {
1401 SolarMutexGuard aGuard;
1402 pWindow = VCLUnoHelper::GetWindow( xWindow ).get();
1403 if ( pWindow )
1404 {
1405 OUString aText = pWindow->GetText();
1406 if ( aText.isEmpty() )
1407 pWindow->SetText( rElement.m_aUIName );
1408 if ( rElement.m_bNoClose )
1409 pWindow->SetStyle( pWindow->GetStyle() & ~WB_CLOSEABLE );
1410 if ( pWindow->GetType() == WindowType::TOOLBOX )
1411 pToolBox = static_cast<ToolBox *>(pWindow);
1412 }
1413 if ( pToolBox )
1414 {
1415 pToolBox->SetButtonType( rElement.m_nStyle );
1416 if ( rElement.m_bNoClose )
1417 pToolBox->SetFloatStyle( pToolBox->GetFloatStyle() & ~WB_CLOSEABLE );
1418 }
1419 }
1420
1421 if ( rElement.m_bFloating )
1422 {
1423 if ( pWindow )
1424 {
1425 SolarMutexGuard aGuard;
1426 OUString aText = pWindow->GetText();
1427 if ( aText.isEmpty() )
1428 pWindow->SetText( rElement.m_aUIName );
1429 }
1430
1431 awt::Point aPos(rElement.m_aFloatingData.m_aPos);
1432 bool bWriteData( false );
1433 bool bUndefPos = hasDefaultPosValue( rElement.m_aFloatingData.m_aPos );
1434 bool bSetSize = ( rElement.m_aFloatingData.m_aSize.Width != 0 &&
1435 rElement.m_aFloatingData.m_aSize.Height != 0 );
1436 rDockWindow->setFloatingMode( true );
1437 if ( bUndefPos )
1438 {
1439 aPos = implts_findNextCascadeFloatingPos();
1440 rElement.m_aFloatingData.m_aPos = aPos; // set new cascaded position
1441 bWriteData = true;
1442 }
1443
1444 if( bSetSize )
1445 xWindow->setOutputSize(rElement.m_aFloatingData.m_aSize);
1446 else
1447 {
1448 if( pToolBox )
1449 {
1450 // set an optimal initial floating size
1451 SolarMutexGuard aGuard;
1452 ::Size aSize( pToolBox->CalcFloatingWindowSizePixel() );
1453 pToolBox->SetOutputSizePixel( aSize );
1454 }
1455 }
1456
1457 // #i60882# IMPORTANT: Set position after size as it is
1458 // possible that we position some part of the toolbar
1459 // outside of the desktop. A default constructed toolbar
1460 // always has one line. Now VCL automatically
1461 // position the toolbar back into the desktop. Therefore
1462 // we resize the toolbar with the new (wrong) position.
1463 // To fix this problem we have to set the size BEFORE the
1464 // position.
1465 xWindow->setPosSize( aPos.X, aPos.Y, 0, 0, awt::PosSize::POS );
1466
1467 if ( bWriteData )
1468 implts_writeWindowStateData( rElement );
1469 if ( bShowElement && pWindow )
1470 {
1471 SolarMutexGuard aGuard;
1472 pWindow->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
1473 }
1474 }
1475 else
1476 {
1477 bool bSetSize( false );
1478 ::Point aPixelPos;
1479 ::Size aSize;
1480
1481 if ( pToolBox )
1482 {
1483 SolarMutexGuard aGuard;
1484 pToolBox->SetAlign( ImplConvertAlignment(rElement.m_aDockedData.m_nDockedArea ) );
1485 pToolBox->SetLineCount( 1 );
1486 rDockWindow->setFloatingMode( false );
1487 if ( rElement.m_aDockedData.m_bLocked )
1488 rDockWindow->lock();
1489 aSize = pToolBox->CalcWindowSizePixel();
1490 bSetSize = true;
1491
1492 if ( isDefaultPos( rElement.m_aDockedData.m_aPos ))
1493 {
1494 awt::Point aDockPos;
1495 implts_findNextDockingPos( rElement.m_aDockedData.m_nDockedArea, aSize, aDockPos, aPixelPos );
1496 rElement.m_aDockedData.m_aPos = aDockPos;
1497 }
1498 }
1499
1500 xWindow->setPosSize( aPixelPos.X(), aPixelPos.Y(), 0, 0, awt::PosSize::POS );
1501 if( bSetSize )
1502 xWindow->setOutputSize( AWTSize( aSize) );
1503
1504 if ( pWindow )
1505 {
1506 SolarMutexGuard aGuard;
1507 if ( !bShowElement )
1508 pWindow->Hide();
1509 }
1510 }
1511}
1512
1513void ToolbarLayoutManager::implts_destroyDockingAreaWindows()
1514{
1515 SolarMutexClearableGuard aWriteLock;
1516 uno::Reference< awt::XWindow > xTopDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] );
1517 uno::Reference< awt::XWindow > xLeftDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] );
1518 uno::Reference< awt::XWindow > xRightDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)] );
1519 uno::Reference< awt::XWindow > xBottomDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)] );
1520 m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)].clear();
1521 m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)].clear();
1522 m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)].clear();
1523 m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)].clear();
1524 aWriteLock.clear();
1525
1526 // destroy windows
1527 xTopDockingWindow->dispose();
1528 xLeftDockingWindow->dispose();
1529 xRightDockingWindow->dispose();
1530 xBottomDockingWindow->dispose();
1531}
1532
1533// persistence methods
1534
1535bool ToolbarLayoutManager::implts_readWindowStateData( const OUString& aName, UIElement& rElementData )
1536{
1537 return LayoutManager::readWindowStateData( aName, rElementData, m_xPersistentWindowState,
1538 m_pGlobalSettings, m_bGlobalSettings, m_xContext );
1539}
1540
1541void ToolbarLayoutManager::implts_writeWindowStateData( const UIElement& rElementData )
1542{
1543 SolarMutexClearableGuard aWriteLock;
1544 uno::Reference< container::XNameAccess > xPersistentWindowState( m_xPersistentWindowState );
1545 aWriteLock.clear();
1546
1547 bool bPersistent( false );
1548 uno::Reference< beans::XPropertySet > xPropSet( rElementData.m_xUIElement, uno::UNO_QUERY );
1549 if ( xPropSet.is() )
1550 {
1551 try
1552 {
1553 // Check persistent flag of the user interface element
1554 xPropSet->getPropertyValue("Persistent") >>= bPersistent;
1555 }
1556 catch (const beans::UnknownPropertyException&)
1557 {
1558 bPersistent = true; // Non-configurable elements should at least store their dimension/position
1559 }
1560 catch (const lang::WrappedTargetException&)
1561 {
1562 }
1563 }
1564
1565 if ( !(bPersistent && xPersistentWindowState.is()) )
1566 return;
1567
1568 try
1569 {
1570 uno::Sequence< beans::PropertyValue > aWindowState( 9 );
1571
1572 aWindowState[0].Name = WINDOWSTATE_PROPERTY_DOCKED"Docked";
1573 aWindowState[0].Value <<= !rElementData.m_bFloating;
1574 aWindowState[1].Name = WINDOWSTATE_PROPERTY_VISIBLE"Visible";
1575 aWindowState[1].Value <<= rElementData.m_bVisible;
1576 aWindowState[2].Name = WINDOWSTATE_PROPERTY_DOCKINGAREA"DockingArea";
1577 aWindowState[2].Value <<= rElementData.m_aDockedData.m_nDockedArea;
1578
1579 awt::Point aPos = rElementData.m_aDockedData.m_aPos;
1580 aWindowState[3].Name = WINDOWSTATE_PROPERTY_DOCKPOS"DockPos";
1581 aWindowState[3].Value <<= aPos;
1582
1583 aPos = rElementData.m_aFloatingData.m_aPos;
1584 aWindowState[4].Name = WINDOWSTATE_PROPERTY_POS"Pos";
1585 aWindowState[4].Value <<= aPos;
1586
1587 aWindowState[5].Name = WINDOWSTATE_PROPERTY_SIZE"Size";
1588 aWindowState[5].Value <<= rElementData.m_aFloatingData.m_aSize;
1589 aWindowState[6].Name = WINDOWSTATE_PROPERTY_UINAME"UIName";
1590 aWindowState[6].Value <<= rElementData.m_aUIName;
1591 aWindowState[7].Name = WINDOWSTATE_PROPERTY_LOCKED"Locked";
1592 aWindowState[7].Value <<= rElementData.m_aDockedData.m_bLocked;
1593 aWindowState[8].Name = WINDOWSTATE_PROPERTY_STYLE"Style";
1594 aWindowState[8].Value <<= static_cast<sal_uInt16>(rElementData.m_nStyle);
1595
1596 OUString aName = rElementData.m_aName;
1597 if ( xPersistentWindowState->hasByName( aName ))
1598 {
1599 uno::Reference< container::XNameReplace > xReplace( xPersistentWindowState, uno::UNO_QUERY );
1600 xReplace->replaceByName( aName, uno::makeAny( aWindowState ));
1601 }
1602 else
1603 {
1604 uno::Reference< container::XNameContainer > xInsert( xPersistentWindowState, uno::UNO_QUERY );
1605 xInsert->insertByName( aName, uno::makeAny( aWindowState ));
1606 }
1607 }
1608 catch (const uno::Exception&)
1609 {
1610 }
1611}
1612
1613/******************************************************************************
1614 LOOKUP PART FOR TOOLBARS
1615******************************************************************************/
1616
1617UIElement& ToolbarLayoutManager::impl_findToolbar( const OUString& aName )
1618{
1619 static UIElement aEmptyElement;
1620
1621 SolarMutexGuard g;
1622 for (auto & elem : m_aUIElements)
1623 {
1624 if ( elem.m_aName == aName )
1625 return elem;
1626 }
1627
1628 return aEmptyElement;
1629}
1630
1631UIElement ToolbarLayoutManager::implts_findToolbar( const OUString& aName )
1632{
1633 SolarMutexGuard g;
1634 return impl_findToolbar( aName );
1635}
1636
1637UIElement ToolbarLayoutManager::implts_findToolbar( const uno::Reference< uno::XInterface >& xToolbar )
1638{
1639 UIElement aToolbar;
1640
1641 SolarMutexGuard g;
1642 for (auto const& elem : m_aUIElements)
1643 {
1644 if ( elem.m_xUIElement.is() )
1645 {
1646 uno::Reference< uno::XInterface > xIfac( elem.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
1647 if ( xIfac == xToolbar )
1648 {
1649 aToolbar = elem;
1650 break;
1651 }
1652 }
1653 }
1654
1655 return aToolbar;
1656}
1657
1658uno::Reference< awt::XWindow > ToolbarLayoutManager::implts_getXWindow( const OUString& aName )
1659{
1660 uno::Reference< awt::XWindow > xWindow;
1661
1662 SolarMutexGuard g;
1663 for (auto const& elem : m_aUIElements)
1664 {
1665 if ( elem.m_aName == aName && elem.m_xUIElement.is() )
1666 {
1667 xWindow.set( elem.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
1668 break;
1669 }
1670 }
1671
1672 return xWindow;
1673}
1674
1675vcl::Window* ToolbarLayoutManager::implts_getWindow( const OUString& aName )
1676{
1677 uno::Reference< awt::XWindow > xWindow = implts_getXWindow( aName );
1678 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
1679
1680 return pWindow;
1681}
1682
1683bool ToolbarLayoutManager::implts_insertToolbar( const UIElement& rUIElement )
1684{
1685 UIElement aTempData;
1686 bool bFound( false );
1687 bool bResult( false );
1688
1689 aTempData = implts_findToolbar( rUIElement.m_aName );
1690 if ( aTempData.m_aName == rUIElement.m_aName )
1691 bFound = true;
1692
1693 if ( !bFound )
1694 {
1695 SolarMutexGuard g;
1696 m_aUIElements.push_back( rUIElement );
1697 bResult = true;
1698 }
1699
1700 return bResult;
1701}
1702
1703void ToolbarLayoutManager::implts_setToolbar( const UIElement& rUIElement )
1704{
1705 SolarMutexGuard g;
1706 UIElement& rData = impl_findToolbar( rUIElement.m_aName );
1707 if ( rData.m_aName == rUIElement.m_aName )
1708 rData = rUIElement;
1709 else
1710 m_aUIElements.push_back( rUIElement );
1711}
1712
1713/******************************************************************************
1714 LAYOUT CODE PART FOR TOOLBARS
1715******************************************************************************/
1716
1717awt::Point ToolbarLayoutManager::implts_findNextCascadeFloatingPos()
1718{
1719 const sal_Int32 nHotZoneX = 50;
1720 const sal_Int32 nHotZoneY = 50;
1721 const sal_Int32 nCascadeIndentX = 15;
1722 const sal_Int32 nCascadeIndentY = 15;
1723
1724 SolarMutexClearableGuard aReadLock;
1725 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
1726 uno::Reference< awt::XWindow > xTopDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] );
1727 uno::Reference< awt::XWindow > xLeftDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] );
1728 aReadLock.clear();
1729
1730 awt::Point aStartPos( nCascadeIndentX, nCascadeIndentY );
1731 awt::Point aCurrPos( aStartPos );
1732
1733 if ( xContainerWindow.is() )
1734 {
1735 SolarMutexGuard aGuard;
1736 VclPtr<vcl::Window> pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
1737 if ( pContainerWindow )
1738 aStartPos = AWTPoint(pContainerWindow->OutputToScreenPixel(VCLPoint(aStartPos)));
1739 }
1740
1741 // Determine size of top and left docking area
1742 awt::Rectangle aTopRect( xTopDockingWindow->getPosSize() );
1743 awt::Rectangle aLeftRect( xLeftDockingWindow->getPosSize() );
1744
1745 aStartPos.X += aLeftRect.Width + nCascadeIndentX;
1746 aStartPos.Y += aTopRect.Height + nCascadeIndentY;
1747 aCurrPos = aStartPos;
1748
1749 // Try to find a cascaded position for the new floating window
1750 for (auto const& elem : m_aUIElements)
1751 {
1752 if ( elem.m_xUIElement.is() )
1753 {
1754 uno::Reference< awt::XDockableWindow > xDockWindow( elem.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
1755 uno::Reference< awt::XWindow > xWindow( xDockWindow, uno::UNO_QUERY );
1756 if ( xDockWindow.is() && xDockWindow->isFloating() )
1757 {
1758 SolarMutexGuard aGuard;
1759 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
1760 if ( pWindow && pWindow->IsVisible() )
1761 {
1762 awt::Rectangle aFloatRect = xWindow->getPosSize();
1763 if ((( aFloatRect.X - nHotZoneX ) <= aCurrPos.X ) &&
1764 ( aFloatRect.X >= aCurrPos.X ) &&
1765 (( aFloatRect.Y - nHotZoneY ) <= aCurrPos.Y ) &&
1766 ( aFloatRect.Y >= aCurrPos.Y ))
1767 {
1768 aCurrPos.X = aFloatRect.X + nCascadeIndentX;
1769 aCurrPos.Y = aFloatRect.Y + nCascadeIndentY;
1770 }
1771 }
1772 }
1773 }
1774 }
1775
1776 return aCurrPos;
1777}
1778
1779void ToolbarLayoutManager::implts_sortUIElements()
1780{
1781 SolarMutexGuard g;
1782
1783 std::stable_sort( m_aUIElements.begin(), m_aUIElements.end()); // first created element should first
1784
1785 // We have to reset our temporary flags.
1786 for (auto & elem : m_aUIElements)
1787 elem.m_bUserActive = false;
1788}
1789
1790void ToolbarLayoutManager::implts_getUIElementVectorCopy( UIElementVector& rCopy )
1791{
1792 SolarMutexGuard g;
1793 rCopy = m_aUIElements;
1794}
1795
1796::Size ToolbarLayoutManager::implts_getTopBottomDockingAreaSizes()
1797{
1798 ::Size aSize;
1799 uno::Reference< awt::XWindow > xTopDockingAreaWindow;
1800 uno::Reference< awt::XWindow > xBottomDockingAreaWindow;
1801
1802 {
1803 SolarMutexGuard aReadLock;
1804 xTopDockingAreaWindow = m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)];
1805 xBottomDockingAreaWindow = m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)];
1806 }
1807
1808 if ( xTopDockingAreaWindow.is() )
1809 aSize.setWidth( xTopDockingAreaWindow->getPosSize().Height );
1810 if ( xBottomDockingAreaWindow.is() )
1811 aSize.setHeight( xBottomDockingAreaWindow->getPosSize().Height );
1812
1813 return aSize;
1814}
1815
1816void ToolbarLayoutManager::implts_getDockingAreaElementInfos( ui::DockingArea eDockingArea, std::vector< SingleRowColumnWindowData >& rRowColumnsWindowData )
1817{
1818 std::vector< UIElement > aWindowVector;
1819
1820 if (( eDockingArea < ui::DockingArea_DOCKINGAREA_TOP ) || ( eDockingArea > ui::DockingArea_DOCKINGAREA_RIGHT ))
1821 eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
1822
1823 uno::Reference< awt::XWindow > xDockAreaWindow;
1824
1825 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
1826 {
1827 SolarMutexGuard aReadLock;
1828 aWindowVector.reserve(m_aUIElements.size());
1829 xDockAreaWindow = m_xDockAreaWindows[static_cast<int>(eDockingArea)];
1830 for (auto const& elem : m_aUIElements)
1831 {
1832 if (elem.m_aDockedData.m_nDockedArea == eDockingArea && elem.m_bVisible)
1833 {
1834 uno::Reference<ui::XUIElement> xUIElement(elem.m_xUIElement);
1835 if (xUIElement.is())
1836 {
1837 uno::Reference<awt::XWindow> xWindow(xUIElement->getRealInterface(),
1838 uno::UNO_QUERY);
1839 uno::Reference<awt::XDockableWindow> xDockWindow(xWindow, uno::UNO_QUERY);
1840 if (xDockWindow.is())
1841 {
1842 if (!elem.m_bFloating)
1843 {
1844 // docked windows
1845 aWindowVector.push_back(elem);
1846 }
1847 else
1848 {
1849 // floating windows
1850 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xWindow);
1851 DockingManager* pDockMgr = vcl::Window::GetDockingManager();
1852 if (pDockMgr != nullptr)
1853 {
1854 ImplDockingWindowWrapper* pWrapper
1855 = pDockMgr->GetDockingWindowWrapper(pWindow);
1856 if (pWrapper != nullptr && pWrapper->GetFloatingWindow())
1857 {
1858 // update the position data of the floating window
1859 if (pWrapper->GetFloatingWindow()->UpdatePositionData())
1860 {
1861 awt::Rectangle aTmpRect = xWindow->getPosSize();
1862 UIElement uiElem = elem;
1863 uiElem.m_aFloatingData.m_aPos
1864 = awt::Point(aTmpRect.X, aTmpRect.Y);
1865 implts_setToolbar(uiElem);
1866 implts_writeWindowStateData(uiElem);
1867 }
1868 }
1869 }
1870 }
1871 }
1872 }
1873 }
1874 }
1875 }
1876 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
1877
1878 rRowColumnsWindowData.clear();
1879
1880 // Collect data from windows that are on the same row/column
1881 sal_Int32 j;
1882 sal_Int32 nIndex( 0 );
1883 sal_Int32 nLastPos( 0 );
1884 sal_Int32 nCurrPos( -1 );
1885 sal_Int32 nLastRowColPixelPos( 0 );
1886 awt::Rectangle aDockAreaRect;
1887
1888 if ( xDockAreaWindow.is() )
1889 aDockAreaRect = xDockAreaWindow->getPosSize();
1890
1891 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
1892 nLastRowColPixelPos = 0;
1893 else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
1894 nLastRowColPixelPos = aDockAreaRect.Height;
1895 else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
1896 nLastRowColPixelPos = 0;
1897 else
1898 nLastRowColPixelPos = aDockAreaRect.Width;
1899
1900 const sal_uInt32 nCount = aWindowVector.size();
1901 for ( j = 0; j < sal_Int32( nCount); j++ )
1902 {
1903 const UIElement& rElement = aWindowVector[j];
1904 uno::Reference< awt::XWindow > xWindow;
1905 uno::Reference< ui::XUIElement > xUIElement( rElement.m_xUIElement );
1906 awt::Rectangle aPosSize;
1907
1908 if ( !lcl_checkUIElement(xUIElement,aPosSize,xWindow) )
1909 continue;
1910 if ( isHorizontalDockingArea( eDockingArea ))
1911 {
1912 if ( nCurrPos == -1 )
1913 {
1914 nCurrPos = rElement.m_aDockedData.m_aPos.Y;
1915 nLastPos = 0;
1916
1917 SingleRowColumnWindowData aRowColumnWindowData;
1918 aRowColumnWindowData.nRowColumn = nCurrPos;
1919 rRowColumnsWindowData.push_back( aRowColumnWindowData );
1920 }
1921
1922 sal_Int32 nSpace( 0 );
1923 if ( rElement.m_aDockedData.m_aPos.Y != nCurrPos )
1924 {
1925 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
1926 nLastRowColPixelPos += rRowColumnsWindowData[nIndex].nStaticSize;
1927 else
1928 nLastRowColPixelPos -= rRowColumnsWindowData[nIndex].nStaticSize;
1929 ++nIndex;
1930 nLastPos = 0;
1931 nCurrPos = rElement.m_aDockedData.m_aPos.Y;
1932 SingleRowColumnWindowData aRowColumnWindowData;
1933 aRowColumnWindowData.nRowColumn = nCurrPos;
1934 rRowColumnsWindowData.push_back( aRowColumnWindowData );
1935 }
1936
1937 // Calc space before an element and store it
1938 nSpace = ( rElement.m_aDockedData.m_aPos.X - nLastPos );
1939 if ( rElement.m_aDockedData.m_aPos.X >= nLastPos )
1940 {
1941 rRowColumnsWindowData[nIndex].nSpace += nSpace;
1942 nLastPos = rElement.m_aDockedData.m_aPos.X + aPosSize.Width;
1943 }
1944 else
1945 {
1946 nSpace = 0;
1947 nLastPos += aPosSize.Width;
1948 }
1949 rRowColumnsWindowData[nIndex].aRowColumnSpace.push_back( nSpace );
1950
1951 rRowColumnsWindowData[nIndex].aRowColumnWindows.push_back( xWindow );
1952 rRowColumnsWindowData[nIndex].aUIElementNames.push_back( rElement.m_aName );
1953 rRowColumnsWindowData[nIndex].aRowColumnWindowSizes.emplace_back(
1954 rElement.m_aDockedData.m_aPos.X,
1955 rElement.m_aDockedData.m_aPos.Y,
1956 aPosSize.Width,
1957 aPosSize.Height );
1958 if ( rRowColumnsWindowData[nIndex].nStaticSize < aPosSize.Height )
1959 rRowColumnsWindowData[nIndex].nStaticSize = aPosSize.Height;
1960 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
1961 rRowColumnsWindowData[nIndex].aRowColumnRect = awt::Rectangle( 0, nLastRowColPixelPos,
1962 aDockAreaRect.Width, aPosSize.Height );
1963 else
1964 rRowColumnsWindowData[nIndex].aRowColumnRect = awt::Rectangle( 0, ( nLastRowColPixelPos - aPosSize.Height ),
1965 aDockAreaRect.Width, aPosSize.Height );
1966 rRowColumnsWindowData[nIndex].nVarSize += aPosSize.Width + nSpace;
1967 }
1968 else
1969 {
1970 if ( nCurrPos == -1 )
1971 {
1972 nCurrPos = rElement.m_aDockedData.m_aPos.X;
1973 nLastPos = 0;
1974
1975 SingleRowColumnWindowData aRowColumnWindowData;
1976 aRowColumnWindowData.nRowColumn = nCurrPos;
1977 rRowColumnsWindowData.push_back( aRowColumnWindowData );
1978 }
1979
1980 sal_Int32 nSpace( 0 );
1981 if ( rElement.m_aDockedData.m_aPos.X != nCurrPos )
1982 {
1983 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
1984 nLastRowColPixelPos += rRowColumnsWindowData[nIndex].nStaticSize;
1985 else
1986 nLastRowColPixelPos -= rRowColumnsWindowData[nIndex].nStaticSize;
1987 ++nIndex;
1988 nLastPos = 0;
1989 nCurrPos = rElement.m_aDockedData.m_aPos.X;
1990 SingleRowColumnWindowData aRowColumnWindowData;
1991 aRowColumnWindowData.nRowColumn = nCurrPos;
1992 rRowColumnsWindowData.push_back( aRowColumnWindowData );
1993 }
1994
1995 // Calc space before an element and store it
1996 nSpace = ( rElement.m_aDockedData.m_aPos.Y - nLastPos );
1997 if ( rElement.m_aDockedData.m_aPos.Y > nLastPos )
1998 {
1999 rRowColumnsWindowData[nIndex].nSpace += nSpace;
2000 nLastPos = rElement.m_aDockedData.m_aPos.Y + aPosSize.Height;
2001 }
2002 else
2003 {
2004 nSpace = 0;
2005 nLastPos += aPosSize.Height;
2006 }
2007 rRowColumnsWindowData[nIndex].aRowColumnSpace.push_back( nSpace );
2008
2009 rRowColumnsWindowData[nIndex].aRowColumnWindows.push_back( xWindow );
2010 rRowColumnsWindowData[nIndex].aUIElementNames.push_back( rElement.m_aName );
2011 rRowColumnsWindowData[nIndex].aRowColumnWindowSizes.emplace_back(
2012 rElement.m_aDockedData.m_aPos.X,
2013 rElement.m_aDockedData.m_aPos.Y,
2014 aPosSize.Width,
2015 aPosSize.Height );
2016 if ( rRowColumnsWindowData[nIndex].nStaticSize < aPosSize.Width )
2017 rRowColumnsWindowData[nIndex].nStaticSize = aPosSize.Width;
2018 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
2019 rRowColumnsWindowData[nIndex].aRowColumnRect = awt::Rectangle( nLastRowColPixelPos, 0,
2020 aPosSize.Width, aDockAreaRect.Height );
2021 else
2022 rRowColumnsWindowData[nIndex].aRowColumnRect = awt::Rectangle( ( nLastRowColPixelPos - aPosSize.Width ), 0,
2023 aPosSize.Width, aDockAreaRect.Height );
2024 rRowColumnsWindowData[nIndex].nVarSize += aPosSize.Height + nSpace;
2025 }
2026 }
2027}
2028
2029void ToolbarLayoutManager::implts_getDockingAreaElementInfoOnSingleRowCol( ui::DockingArea eDockingArea, sal_Int32 nRowCol, SingleRowColumnWindowData& rRowColumnWindowData )
2030{
2031 std::vector< UIElement > aWindowVector;
2032
2033 if (( eDockingArea < ui::DockingArea_DOCKINGAREA_TOP ) || ( eDockingArea > ui::DockingArea_DOCKINGAREA_RIGHT ))
2034 eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
2035
2036 bool bHorzDockArea = isHorizontalDockingArea( eDockingArea );
2037
2038 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
2039 {
2040 SolarMutexGuard aReadLock;
2041 for (auto const& elem : m_aUIElements)
2042 {
2043 if (elem.m_aDockedData.m_nDockedArea == eDockingArea)
2044 {
2045 bool bSameRowCol = bHorzDockArea ? (elem.m_aDockedData.m_aPos.Y == nRowCol)
2046 : (elem.m_aDockedData.m_aPos.X == nRowCol);
2047 uno::Reference<ui::XUIElement> xUIElement(elem.m_xUIElement);
2048
2049 if (bSameRowCol && xUIElement.is())
2050 {
2051 uno::Reference<awt::XWindow> xWindow(xUIElement->getRealInterface(),
2052 uno::UNO_QUERY);
2053 if (xWindow.is())
2054 {
2055 SolarMutexGuard aGuard;
2056 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xWindow);
2057 uno::Reference<awt::XDockableWindow> xDockWindow(xWindow, uno::UNO_QUERY);
2058 if (pWindow && elem.m_bVisible && xDockWindow.is() && !elem.m_bFloating)
2059 aWindowVector.push_back(elem); // docked windows
2060 }
2061 }
2062 }
2063 }
2064 }
2065 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
2066
2067 // Initialize structure
2068 rRowColumnWindowData.aUIElementNames.clear();
2069 rRowColumnWindowData.aRowColumnWindows.clear();
2070 rRowColumnWindowData.aRowColumnWindowSizes.clear();
2071 rRowColumnWindowData.aRowColumnSpace.clear();
2072 rRowColumnWindowData.nVarSize = 0;
2073 rRowColumnWindowData.nStaticSize = 0;
2074 rRowColumnWindowData.nSpace = 0;
2075 rRowColumnWindowData.nRowColumn = nRowCol;
2076
2077 // Collect data from windows that are on the same row/column
2078 sal_Int32 j;
2079 sal_Int32 nLastPos( 0 );
2080
2081 const sal_uInt32 nCount = aWindowVector.size();
2082 for ( j = 0; j < sal_Int32( nCount); j++ )
2083 {
2084 const UIElement& rElement = aWindowVector[j];
2085 uno::Reference< awt::XWindow > xWindow;
2086 uno::Reference< ui::XUIElement > xUIElement( rElement.m_xUIElement );
2087 awt::Rectangle aPosSize;
2088 if ( !lcl_checkUIElement(xUIElement,aPosSize,xWindow) )
2089 continue;
2090
2091 sal_Int32 nSpace;
2092 if ( isHorizontalDockingArea( eDockingArea ))
2093 {
2094 nSpace = ( rElement.m_aDockedData.m_aPos.X - nLastPos );
2095
2096 // Calc space before an element and store it
2097 if ( rElement.m_aDockedData.m_aPos.X > nLastPos )
2098 rRowColumnWindowData.nSpace += nSpace;
2099 else
2100 nSpace = 0;
2101
2102 nLastPos = rElement.m_aDockedData.m_aPos.X + aPosSize.Width;
2103
2104 rRowColumnWindowData.aRowColumnWindowSizes.emplace_back(
2105 rElement.m_aDockedData.m_aPos.X, rElement.m_aDockedData.m_aPos.Y,
2106 aPosSize.Width, aPosSize.Height );
2107 if ( rRowColumnWindowData.nStaticSize < aPosSize.Height )
2108 rRowColumnWindowData.nStaticSize = aPosSize.Height;
2109 rRowColumnWindowData.nVarSize += aPosSize.Width;
2110 }
2111 else
2112 {
2113 // Calc space before an element and store it
2114 nSpace = ( rElement.m_aDockedData.m_aPos.Y - nLastPos );
2115 if ( rElement.m_aDockedData.m_aPos.Y > nLastPos )
2116 rRowColumnWindowData.nSpace += nSpace;
2117 else
2118 nSpace = 0;
2119
2120 nLastPos = rElement.m_aDockedData.m_aPos.Y + aPosSize.Height;
2121
2122 rRowColumnWindowData.aRowColumnWindowSizes.emplace_back(
2123 rElement.m_aDockedData.m_aPos.X, rElement.m_aDockedData.m_aPos.Y,
2124 aPosSize.Width, aPosSize.Height );
2125 if ( rRowColumnWindowData.nStaticSize < aPosSize.Width )
2126 rRowColumnWindowData.nStaticSize = aPosSize.Width;
2127 rRowColumnWindowData.nVarSize += aPosSize.Height;
2128 }
2129
2130 rRowColumnWindowData.aUIElementNames.push_back( rElement.m_aName );
2131 rRowColumnWindowData.aRowColumnWindows.push_back( xWindow );
2132 rRowColumnWindowData.aRowColumnSpace.push_back( nSpace );
2133 rRowColumnWindowData.nVarSize += nSpace;
2134 }
2135}
2136
2137::tools::Rectangle ToolbarLayoutManager::implts_getWindowRectFromRowColumn(
2138 ui::DockingArea DockingArea,
2139 const SingleRowColumnWindowData& rRowColumnWindowData,
2140 const ::Point& rMousePos,
2141 const OUString& rExcludeElementName )
2142{
2143 ::tools::Rectangle aWinRect;
2144
2145 if (( DockingArea < ui::DockingArea_DOCKINGAREA_TOP ) || ( DockingArea > ui::DockingArea_DOCKINGAREA_RIGHT ))
2146 DockingArea = ui::DockingArea_DOCKINGAREA_TOP;
2147
2148 if ( rRowColumnWindowData.aRowColumnWindows.empty() )
2149 return aWinRect;
2150 else
2151 {
2152 SolarMutexClearableGuard aReadLock;
2153 VclPtr<vcl::Window> pContainerWindow( VCLUnoHelper::GetWindow( m_xContainerWindow ));
2154 VclPtr<vcl::Window> pDockingAreaWindow( VCLUnoHelper::GetWindow( m_xDockAreaWindows[static_cast<int>(DockingArea)] ));
2155 aReadLock.clear();
2156
2157 // Calc correct position of the column/row rectangle to be able to compare it with mouse pos/tracking rect
2158 SolarMutexGuard aGuard;
2159
2160 // Retrieve output size from container Window
2161 if ( pDockingAreaWindow && pContainerWindow )
2162 {
2163 const sal_uInt32 nCount = rRowColumnWindowData.aRowColumnWindows.size();
2164 for ( sal_uInt32 i = 0; i < nCount; i++ )
2165 {
2166 awt::Rectangle aWindowRect = rRowColumnWindowData.aRowColumnWindows[i]->getPosSize();
2167 ::tools::Rectangle aRect( aWindowRect.X, aWindowRect.Y, aWindowRect.X+aWindowRect.Width, aWindowRect.Y+aWindowRect.Height );
2168 aRect.SetPos( pContainerWindow->ScreenToOutputPixel( pDockingAreaWindow->OutputToScreenPixel( aRect.TopLeft() )));
2169 if ( aRect.IsInside( rMousePos ))
2170 {
2171 // Check if we have found the excluded element. If yes, we have to provide an empty rectangle.
2172 // We prevent that a toolbar cannot be moved when the mouse pointer is inside its own rectangle!
2173 if ( rExcludeElementName != rRowColumnWindowData.aUIElementNames[i] )
2174 return aRect;
2175 else
2176 break;
2177 }
2178 }
2179 }
2180 }
2181
2182 return aWinRect;
2183}
2184
2185::tools::Rectangle ToolbarLayoutManager::implts_determineFrontDockingRect(
2186 ui::DockingArea eDockingArea,
2187 sal_Int32 nRowCol,
2188 const ::tools::Rectangle& rDockedElementRect,
2189 const OUString& rMovedElementName,
2190 const ::tools::Rectangle& rMovedElementRect )
2191{
2192 SingleRowColumnWindowData aRowColumnWindowData;
2193
2194 bool bHorzDockArea( isHorizontalDockingArea( eDockingArea ));
2195 implts_getDockingAreaElementInfoOnSingleRowCol( eDockingArea, nRowCol, aRowColumnWindowData );
2196 if ( aRowColumnWindowData.aRowColumnWindows.empty() )
2197 return rMovedElementRect;
2198 else
2199 {
2200 sal_Int32 nSpace( 0 );
2201 ::tools::Rectangle aFrontDockingRect( rMovedElementRect );
2202 const sal_uInt32 nCount = aRowColumnWindowData.aRowColumnWindows.size();
2203 for ( sal_uInt32 i = 0; i < nCount; i++ )
2204 {
2205 if ( bHorzDockArea )
2206 {
2207 if ( aRowColumnWindowData.aRowColumnWindowSizes[i].X >= rDockedElementRect.Left() )
2208 {
2209 nSpace += aRowColumnWindowData.aRowColumnSpace[i];
2210 break;
2211 }
2212 else if ( aRowColumnWindowData.aUIElementNames[i] == rMovedElementName )
2213 nSpace += aRowColumnWindowData.aRowColumnWindowSizes[i].Width +
2214 aRowColumnWindowData.aRowColumnSpace[i];
2215 else
2216 nSpace = 0;
2217 }
2218 else
2219 {
2220 if ( aRowColumnWindowData.aRowColumnWindowSizes[i].Y >= rDockedElementRect.Top() )
2221 {
2222 nSpace += aRowColumnWindowData.aRowColumnSpace[i];
2223 break;
2224 }
2225 else if ( aRowColumnWindowData.aUIElementNames[i] == rMovedElementName )
2226 nSpace += aRowColumnWindowData.aRowColumnWindowSizes[i].Height +
2227 aRowColumnWindowData.aRowColumnSpace[i];
2228 else
2229 nSpace = 0;
2230 }
2231 }
2232
2233 if ( nSpace > 0 )
2234 {
2235 sal_Int32 nMove = std::min( nSpace, static_cast<sal_Int32>(aFrontDockingRect.getWidth()) );
2236 if ( bHorzDockArea )
2237 aFrontDockingRect.Move( -nMove, 0 );
2238 else
2239 aFrontDockingRect.Move( 0, -nMove );
2240 }
2241
2242 return aFrontDockingRect;
2243 }
2244}
2245
2246void ToolbarLayoutManager::implts_findNextDockingPos( ui::DockingArea DockingArea, const ::Size& aUIElementSize, awt::Point& rVirtualPos, ::Point& rPixelPos )
2247{
2248 SolarMutexClearableGuard aReadLock;
2249 if (( DockingArea < ui::DockingArea_DOCKINGAREA_TOP ) || ( DockingArea > ui::DockingArea_DOCKINGAREA_RIGHT ))
2250 DockingArea = ui::DockingArea_DOCKINGAREA_TOP;
2251 uno::Reference< awt::XWindow > xDockingWindow( m_xDockAreaWindows[static_cast<int>(DockingArea)] );
2252 ::Size aDockingWinSize;
2253
2254 // Retrieve output size from container Window
2255 vcl::Window* pDockingWindow = VCLUnoHelper::GetWindow( xDockingWindow ).get();
2256 if ( pDockingWindow )
2257 aDockingWinSize = pDockingWindow->GetOutputSizePixel();
2258 aReadLock.clear();
2259
2260 sal_Int32 nFreeRowColPixelPos( 0 );
2261 sal_Int32 nMaxSpace( 0 );
2262 sal_Int32 nNeededSpace( 0 );
2263 sal_Int32 nTopDockingAreaSize( 0 );
2264
2265 if ( isHorizontalDockingArea( DockingArea ))
2266 {
2267 nMaxSpace = aDockingWinSize.Width();
2268 nNeededSpace = aUIElementSize.Width();
2269 }
2270 else
2271 {
2272 nMaxSpace = aDockingWinSize.Height();
2273 nNeededSpace = aUIElementSize.Height();
2274 nTopDockingAreaSize = implts_getTopBottomDockingAreaSizes().Width();
2275 }
2276
2277 std::vector< SingleRowColumnWindowData > aRowColumnsWindowData;
2278
2279 implts_getDockingAreaElementInfos( DockingArea, aRowColumnsWindowData );
2280 sal_Int32 nPixelPos( 0 );
2281 const sal_uInt32 nCount = aRowColumnsWindowData.size();
2282 for ( sal_uInt32 i = 0; i < nCount; i++ )
2283 {
2284 SingleRowColumnWindowData& rRowColumnWindowData = aRowColumnsWindowData[i];
2285
2286 if (( DockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM ) ||
2287 ( DockingArea == ui::DockingArea_DOCKINGAREA_RIGHT ))
2288 nPixelPos += rRowColumnWindowData.nStaticSize;
2289
2290 if ((( nMaxSpace - rRowColumnWindowData.nVarSize ) >= nNeededSpace ) ||
2291 ( rRowColumnWindowData.nSpace >= nNeededSpace ))
2292 {
2293 // Check current row where we can find the needed space
2294 sal_Int32 nCurrPos( 0 );
2295 const sal_uInt32 nWindowSizesCount = rRowColumnWindowData.aRowColumnWindowSizes.size();
2296 for ( sal_uInt32 j = 0; j < nWindowSizesCount; j++ )
2297 {
2298 awt::Rectangle rRect = rRowColumnWindowData.aRowColumnWindowSizes[j];
2299 sal_Int32& rSpace = rRowColumnWindowData.aRowColumnSpace[j];
2300 if ( isHorizontalDockingArea( DockingArea ))
2301 {
2302 if ( rSpace >= nNeededSpace )
2303 {
2304 rVirtualPos = awt::Point( nCurrPos, rRowColumnWindowData.nRowColumn );
2305 if ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP )
2306 rPixelPos = ::Point( nCurrPos, nPixelPos );
2307 else
2308 rPixelPos = ::Point( nCurrPos, aDockingWinSize.Height() - nPixelPos );
2309 return;
2310 }
2311 nCurrPos = rRect.X + rRect.Width;
2312 }
2313 else
2314 {
2315 if ( rSpace >= nNeededSpace )
2316 {
2317 rVirtualPos = awt::Point( rRowColumnWindowData.nRowColumn, nCurrPos );
2318 if ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
2319 rPixelPos = ::Point( nPixelPos, nTopDockingAreaSize + nCurrPos );
2320 else
2321 rPixelPos = ::Point( aDockingWinSize.Width() - nPixelPos , nTopDockingAreaSize + nCurrPos );
2322 return;
2323 }
2324 nCurrPos = rRect.Y + rRect.Height;
2325 }
2326 }
2327
2328 if (( nCurrPos + nNeededSpace ) <= nMaxSpace )
2329 {
2330 if ( isHorizontalDockingArea( DockingArea ))
2331 {
2332 rVirtualPos = awt::Point( nCurrPos, rRowColumnWindowData.nRowColumn );
2333 if ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP )
2334 rPixelPos = ::Point( nCurrPos, nPixelPos );
2335 else
2336 rPixelPos = ::Point( nCurrPos, aDockingWinSize.Height() - nPixelPos );
2337 return;
2338 }
2339 else
2340 {
2341 rVirtualPos = awt::Point( rRowColumnWindowData.nRowColumn, nCurrPos );
2342 if ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
2343 rPixelPos = ::Point( nPixelPos, nTopDockingAreaSize + nCurrPos );
2344 else
2345 rPixelPos = ::Point( aDockingWinSize.Width() - nPixelPos , nTopDockingAreaSize + nCurrPos );
2346 return;
2347 }
2348 }
2349 }
2350
2351 if (( DockingArea == ui::DockingArea_DOCKINGAREA_TOP ) || ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT ))
2352 nPixelPos += rRowColumnWindowData.nStaticSize;
2353 }
2354
2355 sal_Int32 nNextFreeRowCol( 0 );
2356 sal_Int32 nRowColumnsCount = aRowColumnsWindowData.size();
2357 if ( nRowColumnsCount > 0 )
2358 nNextFreeRowCol = aRowColumnsWindowData[nRowColumnsCount-1].nRowColumn+1;
2359 else
2360 nNextFreeRowCol = 0;
2361
2362 if ( nNextFreeRowCol == 0 )
2363 {
2364 if ( DockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
2365 nFreeRowColPixelPos = aDockingWinSize.Height() - aUIElementSize.Height();
2366 else if ( DockingArea == ui::DockingArea_DOCKINGAREA_RIGHT )
2367 nFreeRowColPixelPos = aDockingWinSize.Width() - aUIElementSize.Width();
2368 }
2369
2370 if ( isHorizontalDockingArea( DockingArea ))
2371 {
2372 rVirtualPos = awt::Point( 0, nNextFreeRowCol );
2373 if ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP )
2374 rPixelPos = ::Point( 0, nFreeRowColPixelPos );
2375 else
2376 rPixelPos = ::Point( 0, aDockingWinSize.Height() - nFreeRowColPixelPos );
2377 }
2378 else
2379 {
2380 rVirtualPos = awt::Point( nNextFreeRowCol, 0 );
2381 rPixelPos = ::Point( aDockingWinSize.Width() - nFreeRowColPixelPos, 0 );
2382 }
2383}
2384
2385void ToolbarLayoutManager::implts_calcWindowPosSizeOnSingleRowColumn(
2386 sal_Int32 nDockingArea,
2387 sal_Int32 nOffset,
2388 SingleRowColumnWindowData& rRowColumnWindowData,
2389 const ::Size& rContainerSize )
2390{
2391 sal_Int32 nDiff(0);
2392 sal_Int32 nRCSpace( rRowColumnWindowData.nSpace );
2393 sal_Int32 nContainerClientSize(0);
2394
2395 if ( rRowColumnWindowData.aRowColumnWindows.empty() )
2396 return;
2397
2398 if ( isHorizontalDockingArea( nDockingArea ))
2399 {
2400 nContainerClientSize = rContainerSize.Width();
2401 nDiff = nContainerClientSize - rRowColumnWindowData.nVarSize;
2402 }
2403 else
2404 {
2405 sal_Int32 nTopDockingAreaSize = implts_getTopBottomDockingAreaSizes().Width();
2406 sal_Int32 nBottomDockingAreaSize = implts_getTopBottomDockingAreaSizes().Height();
2407 nContainerClientSize = ( rContainerSize.Height() - nTopDockingAreaSize - nBottomDockingAreaSize );
2408 nDiff = nContainerClientSize - rRowColumnWindowData.nVarSize;
2409 }
2410
2411 const sal_uInt32 nCount = rRowColumnWindowData.aRowColumnWindowSizes.size();
2412 if (( nDiff < 0 ) && ( nRCSpace > 0 ))
2413 {
2414 // First we try to reduce the size of blank space before/behind docked windows
2415 sal_Int32 i = nCount - 1;
2416 while ( i >= 0 )
2417 {
2418 sal_Int32 nSpace = rRowColumnWindowData.aRowColumnSpace[i];
2419 if ( nSpace >= -nDiff )
2420 {
2421 if ( isHorizontalDockingArea( nDockingArea ))
2422 {
2423 // Try to move this and all user elements behind with the calculated difference
2424 for ( sal_uInt32 j = i; j < nCount; j++ )
2425 rRowColumnWindowData.aRowColumnWindowSizes[j].X += nDiff;
2426 }
2427 else
2428 {
2429 // Try to move this and all user elements behind with the calculated difference
2430 for ( sal_uInt32 j = i; j < nCount; j++ )
2431 rRowColumnWindowData.aRowColumnWindowSizes[j].Y += nDiff;
2432 }
2433 nDiff = 0;
2434
2435 break;
2436 }
2437 else if ( nSpace > 0 )
2438 {
2439 if ( isHorizontalDockingArea( nDockingArea ))
2440 {
2441 // Try to move this and all user elements behind with the calculated difference
2442 for ( sal_uInt32 j = i; j < nCount; j++ )
2443 rRowColumnWindowData.aRowColumnWindowSizes[j].X -= nSpace;
2444 }
2445 else
2446 {
2447 // Try to move this and all user elements behind with the calculated difference
2448 for ( sal_uInt32 j = i; j < nCount; j++ )
2449 rRowColumnWindowData.aRowColumnWindowSizes[j].Y -= nSpace;
2450 }
2451 nDiff += nSpace;
2452 }
2453 --i;
2454 }
2455 }
2456
2457 // Check if we have to reduce further
2458 if ( nDiff < 0 )
2459 {
2460 // Now we have to reduce the size of certain docked windows
2461 sal_Int32 i = sal_Int32( nCount - 1 );
2462 while ( i >= 0 )
2463 {
2464 awt::Rectangle& rWinRect = rRowColumnWindowData.aRowColumnWindowSizes[i];
2465 ::Size aMinSize;
2466
2467 SolarMutexGuard aGuard;
2468 {
2469 uno::Reference< awt::XWindow > xWindow = rRowColumnWindowData.aRowColumnWindows[i];
2470 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
2471 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
2472 aMinSize = static_cast<ToolBox *>(pWindow.get())->CalcMinimumWindowSizePixel();
2473 }
2474
2475 if ( !aMinSize.IsEmpty() )
2476 {
2477 if ( isHorizontalDockingArea( nDockingArea ))
2478 {
2479 sal_Int32 nMaxReducation = rWinRect.Width - aMinSize.Width();
2480 if ( nMaxReducation >= -nDiff )
2481 {
2482 rWinRect.Width = rWinRect.Width + nDiff;
2483 nDiff = 0;
2484 }
2485 else
2486 {
2487 rWinRect.Width = aMinSize.Width();
2488 nDiff += nMaxReducation;
2489 }
2490
2491 // Try to move this and all user elements behind with the calculated difference
2492 for ( sal_uInt32 j = i; j < nCount; j++ )
2493 rRowColumnWindowData.aRowColumnWindowSizes[j].X += nDiff;
2494 }
2495 else
2496 {
2497 sal_Int32 nMaxReducation = rWinRect.Height - aMinSize.Height();
2498 if ( nMaxReducation >= -nDiff )
2499 {
2500 rWinRect.Height = rWinRect.Height + nDiff;
2501 nDiff = 0;
2502 }
2503 else
2504 {
2505 rWinRect.Height = aMinSize.Height();
2506 nDiff += nMaxReducation;
2507 }
2508
2509 // Try to move this and all user elements behind with the calculated difference
2510 for ( sal_uInt32 j = i; j < nCount; j++ )
2511 rRowColumnWindowData.aRowColumnWindowSizes[j].Y += nDiff;
2512 }
2513 }
2514
2515 if ( nDiff >= 0 )
2516 break;
2517
2518 --i;
2519 }
2520 }
2521
2522 SolarMutexClearableGuard aReadLock;
2523 VclPtr<vcl::Window> pDockAreaWindow = VCLUnoHelper::GetWindow( m_xDockAreaWindows[nDockingArea] );
2524 aReadLock.clear();
2525
2526 sal_Int32 nCurrPos( 0 );
2527
2528 SolarMutexGuard aGuard;
2529 for ( sal_uInt32 i = 0; i < nCount; i++ )
2530 {
2531 uno::Reference< awt::XWindow > xWindow = rRowColumnWindowData.aRowColumnWindows[i];
2532 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
2533 vcl::Window* pOldParentWindow = pWindow->GetParent();
2534
2535 if ( pDockAreaWindow != pOldParentWindow )
2536 pWindow->SetParent( pDockAreaWindow );
2537
2538 awt::Rectangle aWinRect = rRowColumnWindowData.aRowColumnWindowSizes[i];
2539 if ( isHorizontalDockingArea( nDockingArea ))
2540 {
2541 if ( aWinRect.X < nCurrPos )
2542 aWinRect.X = nCurrPos;
2543 pWindow->SetPosSizePixel( ::Point( aWinRect.X, nOffset ), ::Size( aWinRect.Width, rRowColumnWindowData.nStaticSize ));
2544 pWindow->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
2545 nCurrPos += ( aWinRect.X - nCurrPos ) + aWinRect.Width;
2546 }
2547 else
2548 {
2549 if ( aWinRect.Y < nCurrPos )
2550 aWinRect.Y = nCurrPos;
2551 pWindow->SetPosSizePixel( ::Point( nOffset, aWinRect.Y ), ::Size( rRowColumnWindowData.nStaticSize, aWinRect.Height ));
2552 pWindow->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
2553 nCurrPos += ( aWinRect.Y - nCurrPos ) + aWinRect.Height;
2554 }
2555 }
2556}
2557
2558void ToolbarLayoutManager::implts_setLayoutDirty()
2559{
2560 SolarMutexGuard g;
2561 m_bLayoutDirty = true;
2562}
2563
2564void ToolbarLayoutManager::implts_setLayoutInProgress( bool bInProgress )
2565{
2566 SolarMutexGuard g;
2567 m_bLayoutInProgress = bInProgress;
2568}
2569
2570::tools::Rectangle ToolbarLayoutManager::implts_calcHotZoneRect( const ::tools::Rectangle& rRect, sal_Int32 nHotZoneOffset )
2571{
2572 ::tools::Rectangle aRect( rRect );
2573
2574 aRect.AdjustLeft( -nHotZoneOffset );
2575 aRect.AdjustTop( -nHotZoneOffset );
2576 aRect.AdjustRight(nHotZoneOffset );
2577 aRect.AdjustBottom(nHotZoneOffset );
2578
2579 return aRect;
2580}
2581
2582void ToolbarLayoutManager::implts_calcDockingPosSize(
2583 UIElement& rUIElement,
2584 DockingOperation& rDockingOperation,
2585 ::tools::Rectangle& rTrackingRect,
2586 const Point& rMousePos )
2587{
2588 SolarMutexResettableGuard aReadLock;
2589 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
2590 ::Size aContainerWinSize;
2591 vcl::Window* pContainerWindow( nullptr );
2592 ::tools::Rectangle aDockingAreaOffsets( m_aDockingAreaOffsets );
2593 aReadLock.clear();
2594
2595 if ( !rUIElement.m_xUIElement.is() )
1
Taking false branch
2596 {
2597 rTrackingRect = ::tools::Rectangle();
2598 return;
2599 }
2600
2601 {
2602 // Retrieve output size from container Window
2603 SolarMutexGuard aGuard;
2604 pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow ).get();
2605 aContainerWinSize = pContainerWindow->GetOutputSizePixel();
2606 }
2607
2608 vcl::Window* pDockingAreaWindow( nullptr );
2609 uno::Reference< awt::XWindow > xWindow( rUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
2610 uno::Reference< awt::XWindow > xDockingAreaWindow;
2611 ::tools::Rectangle aTrackingRect( rTrackingRect );
2612 ui::DockingArea eDockedArea( rUIElement.m_aDockedData.m_nDockedArea );
2613 sal_Int32 nTopDockingAreaSize( implts_getTopBottomDockingAreaSizes().Width() );
2614 sal_Int32 nBottomDockingAreaSize( implts_getTopBottomDockingAreaSizes().Height() );
2615 bool bHorizontalDockArea(( eDockedArea == ui::DockingArea_DOCKINGAREA_TOP ) ||
2
Assuming 'eDockedArea' is not equal to 'DockingArea_DOCKINGAREA_TOP'
2616 ( eDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM ));
3
Assuming 'eDockedArea' is not equal to 'DockingArea_DOCKINGAREA_BOTTOM'
2617 sal_Int32 nMaxLeftRightDockAreaSize = aContainerWinSize.Height() -
2618 nTopDockingAreaSize -
2619 nBottomDockingAreaSize -
2620 aDockingAreaOffsets.Top() -
2621 aDockingAreaOffsets.Bottom();
2622 ::tools::Rectangle aDockingAreaRect;
2623
2624 aReadLock.reset();
2625 xDockingAreaWindow = m_xDockAreaWindows[static_cast<int>(eDockedArea)];
2626 aReadLock.clear();
2627
2628 {
2629 SolarMutexGuard aGuard;
2630 pDockingAreaWindow = VCLUnoHelper::GetWindow( xDockingAreaWindow ).get();
2631 VclPtr<vcl::Window> pDockWindow = VCLUnoHelper::GetWindow( xWindow );
2632 ToolBox* pToolBox( nullptr );
2633 if ( pDockWindow && pDockWindow->GetType() == WindowType::TOOLBOX )
2634 pToolBox = static_cast<ToolBox *>(pDockWindow.get());
2635
2636 aDockingAreaRect = ::tools::Rectangle( pDockingAreaWindow->GetPosPixel(), pDockingAreaWindow->GetSizePixel() );
2637 if ( pToolBox
3.1
'pToolBox' is null
3.1
'pToolBox' is null
3.1
'pToolBox' is null
)
4
Taking false branch
2638 {
2639 // docked toolbars always have one line
2640 ::Size aSize = pToolBox->CalcWindowSizePixel( 1, ImplConvertAlignment( eDockedArea ) );
2641 aTrackingRect.SetSize( ::Size( aSize.Width(), aSize.Height() ));
2642 }
2643 }
2644
2645 // default docking operation, dock on the given row/column
2646 bool bOpOutsideOfDockingArea( !aDockingAreaRect.IsInside( rMousePos ));
5
Assuming the condition is false
2647
2648 std::vector< SingleRowColumnWindowData > aRowColumnsWindowData;
2649
2650 rDockingOperation = DOCKOP_ON_COLROW;
2651 implts_getDockingAreaElementInfos( eDockedArea, aRowColumnsWindowData );
2652
2653 // determine current first row/column and last row/column
2654 sal_Int32 nMaxRowCol( -1 );
2655 sal_Int32 nMinRowCol( SAL_MAX_INT32((sal_Int32) 0x7FFFFFFF) );
2656 const sal_uInt32 nCount = aRowColumnsWindowData.size();
2657 for ( sal_uInt32 i = 0; i < nCount; i++ )
6
Assuming 'i' is >= 'nCount'
7
Loop condition is false. Execution continues on line 2665
2658 {
2659 if ( aRowColumnsWindowData[i].nRowColumn > nMaxRowCol )
2660 nMaxRowCol = aRowColumnsWindowData[i].nRowColumn;
2661 if ( aRowColumnsWindowData[i].nRowColumn < nMinRowCol )
2662 nMinRowCol = aRowColumnsWindowData[i].nRowColumn;
2663 }
2664
2665 if ( !bOpOutsideOfDockingArea
7.1
'bOpOutsideOfDockingArea' is false
7.1
'bOpOutsideOfDockingArea' is false
7.1
'bOpOutsideOfDockingArea' is false
)
8
Taking true branch
2666 {
2667 // docking inside our docking area
2668 sal_Int32 nIndex( -1 );
2669 sal_Int32 nRowCol( -1 );
2670 ::tools::Rectangle aWindowRect;
2671 ::tools::Rectangle aRowColumnRect;
2672
2673 const sal_uInt32 nWindowDataCount = aRowColumnsWindowData.size();
2674 for ( sal_uInt32 i = 0; i < nWindowDataCount; i++ )
9
Assuming 'i' is < 'nWindowDataCount'
10
Loop condition is true. Entering loop body
2675 {
2676 ::tools::Rectangle aRect( aRowColumnsWindowData[i].aRowColumnRect.X,
2677 aRowColumnsWindowData[i].aRowColumnRect.Y,
2678 aRowColumnsWindowData[i].aRowColumnRect.X + aRowColumnsWindowData[i].aRowColumnRect.Width,
2679 aRowColumnsWindowData[i].aRowColumnRect.Y + aRowColumnsWindowData[i].aRowColumnRect.Height );
2680
2681 {
2682 // Calc correct position of the column/row rectangle to be able to compare it with mouse pos/tracking rect
2683 SolarMutexGuard aGuard;
2684 aRect.SetPos( pContainerWindow->ScreenToOutputPixel( pDockingAreaWindow->OutputToScreenPixel( aRect.TopLeft() )));
2685 }
2686
2687 bool bIsInsideRowCol( aRect.IsInside( rMousePos ) );
2688 if ( bIsInsideRowCol )
11
Assuming 'bIsInsideRowCol' is true
12
Taking true branch
2689 {
2690 nIndex = i;
2691 nRowCol = aRowColumnsWindowData[i].nRowColumn;
2692 rDockingOperation = implts_determineDockingOperation( eDockedArea, aRect, rMousePos );
2693 aWindowRect = implts_getWindowRectFromRowColumn( eDockedArea, aRowColumnsWindowData[i], rMousePos, rUIElement.m_aName );
2694 aRowColumnRect = aRect;
2695 break;
13
Execution continues on line 2699
2696 }
2697 }
2698
2699 OSL_ENSURE( ( nIndex >= 0 ) && ( nRowCol >= 0 ), "Impossible case - no row/column found but mouse pointer is inside our docking area" )do { if (true && (!(( nIndex >= 0 ) && ( nRowCol
>= 0 )))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/framework/source/layoutmanager/toolbarlayoutmanager.cxx"
":" "2699" ": "), "%s", "Impossible case - no row/column found but mouse pointer is inside our docking area"
); } } while (false)
;
14
Assuming 'nRowCol' is >= 0
15
Taking false branch
16
Loop condition is false. Exiting loop
2700 if (( nIndex
16.1
'nIndex' is >= 0
16.1
'nIndex' is >= 0
16.1
'nIndex' is >= 0
>= 0 ) && ( nRowCol
16.2
'nRowCol' is >= 0
16.2
'nRowCol' is >= 0
16.2
'nRowCol' is >= 0
>= 0 ))
17
Taking true branch
2701 {
2702 if ( rDockingOperation
17.1
'rDockingOperation' is not equal to DOCKOP_ON_COLROW
17.1
'rDockingOperation' is not equal to DOCKOP_ON_COLROW
17.1
'rDockingOperation' is not equal to DOCKOP_ON_COLROW
== DOCKOP_ON_COLROW )
18
Taking false branch
2703 {
2704 if ( !aWindowRect.IsEmpty())
2705 {
2706 // Tracking rect is on a row/column and mouse is over a docked toolbar.
2707 // Determine if the tracking rect must be located before/after the docked toolbar.
2708
2709 ::tools::Rectangle aUIElementRect( aWindowRect );
2710 sal_Int32 nMiddle( bHorizontalDockArea ? ( aWindowRect.Left() + aWindowRect.getWidth() / 2 ) :
2711 ( aWindowRect.Top() + aWindowRect.getHeight() / 2 ));
2712 bool bInsertBefore( bHorizontalDockArea ? ( rMousePos.X() < nMiddle ) : ( rMousePos.Y() < nMiddle ));
2713 if ( bInsertBefore )
2714 {
2715 if ( bHorizontalDockArea )
2716 {
2717 sal_Int32 nSize = ::std::max( sal_Int32( 0 ), std::min( sal_Int32( aContainerWinSize.Width() - aWindowRect.Left() ),
2718 sal_Int32( aTrackingRect.getWidth() )));
2719 if ( nSize == 0 )
2720 nSize = aWindowRect.getWidth();
2721
2722 aUIElementRect.SetSize( ::Size( nSize, aWindowRect.getHeight() ));
2723 aWindowRect = implts_determineFrontDockingRect( eDockedArea, nRowCol, aWindowRect,rUIElement.m_aName, aUIElementRect );
2724
2725 // Set virtual position
2726 rUIElement.m_aDockedData.m_aPos.X = aWindowRect.Left();
2727 rUIElement.m_aDockedData.m_aPos.Y = nRowCol;
2728 }
2729 else
2730 {
2731 sal_Int32 nSize = ::std::max( sal_Int32( 0 ), std::min( sal_Int32(
2732 nTopDockingAreaSize + nMaxLeftRightDockAreaSize - aWindowRect.Top() ),
2733 sal_Int32( aTrackingRect.getHeight() )));
2734 if ( nSize == 0 )
2735 nSize = aWindowRect.getHeight();
2736
2737 aUIElementRect.SetSize( ::Size( aWindowRect.getWidth(), nSize ));
2738 aWindowRect = implts_determineFrontDockingRect( eDockedArea, nRowCol, aWindowRect, rUIElement.m_aName, aUIElementRect );
2739
2740 // Set virtual position
2741 sal_Int32 nPosY = pDockingAreaWindow->ScreenToOutputPixel(
2742 pContainerWindow->OutputToScreenPixel( aWindowRect.TopLeft() )).Y();
2743 rUIElement.m_aDockedData.m_aPos.X = nRowCol;
2744 rUIElement.m_aDockedData.m_aPos.Y = nPosY;
2745 }
2746
2747 rTrackingRect = aWindowRect;
2748 return;
2749 }
2750 else
2751 {
2752 if ( bHorizontalDockArea )
2753 {
2754 sal_Int32 nSize = ::std::max( sal_Int32( 0 ), std::min( sal_Int32(( aContainerWinSize.Width() ) - aWindowRect.Right() ),
2755 sal_Int32( aTrackingRect.getWidth() )));
2756 if ( nSize == 0 )
2757 {
2758 aUIElementRect.SetPos( ::Point( aContainerWinSize.Width() - aTrackingRect.getWidth(), aWindowRect.Top() ));
2759 aUIElementRect.SetSize( ::Size( aTrackingRect.getWidth(), aWindowRect.getHeight() ));
2760 rUIElement.m_aDockedData.m_aPos.X = aUIElementRect.Left();
2761
2762 }
2763 else
2764 {
2765 aUIElementRect.SetPos( ::Point( aWindowRect.Right(), aWindowRect.Top() ));
2766 aUIElementRect.SetSize( ::Size( nSize, aWindowRect.getHeight() ));
2767 rUIElement.m_aDockedData.m_aPos.X = aWindowRect.Right();
2768 }
2769
2770 // Set virtual position
2771 rUIElement.m_aDockedData.m_aPos.Y = nRowCol;
2772 }
2773 else
2774 {
2775 sal_Int32 nSize = ::std::max( sal_Int32( 0 ), std::min( sal_Int32( nTopDockingAreaSize + nMaxLeftRightDockAreaSize - aWindowRect.Bottom() ),
2776 sal_Int32( aTrackingRect.getHeight() )));
2777 aUIElementRect.SetPos( ::Point( aWindowRect.Left(), aWindowRect.Bottom() ));
2778 aUIElementRect.SetSize( ::Size( aWindowRect.getWidth(), nSize ));
2779
2780 // Set virtual position
2781 sal_Int32 nPosY( 0 );
2782 {
2783 SolarMutexGuard aGuard;
2784 nPosY = pDockingAreaWindow->ScreenToOutputPixel(
2785 pContainerWindow->OutputToScreenPixel( aWindowRect.BottomRight() )).Y();
2786 }
2787 rUIElement.m_aDockedData.m_aPos.X = nRowCol;
2788 rUIElement.m_aDockedData.m_aPos.Y = nPosY;
2789 }
2790
2791 rTrackingRect = aUIElementRect;
2792 return;
2793 }
2794 }
2795 else
2796 {
2797 implts_setTrackingRect( eDockedArea, rMousePos, aTrackingRect );
2798 rTrackingRect = implts_calcTrackingAndElementRect(
2799 eDockedArea, nRowCol, rUIElement,
2800 aTrackingRect, aRowColumnRect, aContainerWinSize );
2801 return;
2802 }
2803 }
2804 else
2805 {
2806 if ((( nRowCol == nMinRowCol ) && ( rDockingOperation == DOCKOP_BEFORE_COLROW )) ||
19
Assuming 'nRowCol' is not equal to 'nMinRowCol'
2807 (( nRowCol
19.1
'nRowCol' is not equal to 'nMaxRowCol'
19.1
'nRowCol' is not equal to 'nMaxRowCol'
19.1
'nRowCol' is not equal to 'nMaxRowCol'
== nMaxRowCol ) && ( rDockingOperation == DOCKOP_AFTER_COLROW )))
2808 bOpOutsideOfDockingArea = true;
2809 else
2810 {
2811 // handle docking before/after a row
2812 implts_setTrackingRect( eDockedArea, rMousePos, aTrackingRect );
2813 rTrackingRect = implts_calcTrackingAndElementRect(
20
Calling 'ToolbarLayoutManager::implts_calcTrackingAndElementRect'
2814 eDockedArea, nRowCol, rUIElement,
2815 aTrackingRect, aRowColumnRect, aContainerWinSize );
2816
2817 sal_Int32 nOffsetX( 0 );
2818 sal_Int32 nOffsetY( 0 );
2819 if ( bHorizontalDockArea )
2820 nOffsetY = sal_Int32( floor( aRowColumnRect.getHeight() / 2.0 + 0.5 ));
2821 else
2822 nOffsetX = sal_Int32( floor( aRowColumnRect.getWidth() / 2.0 + 0.5 ));
2823
2824 if ( rDockingOperation == DOCKOP_BEFORE_COLROW )
2825 {
2826 if (( eDockedArea == ui::DockingArea_DOCKINGAREA_TOP ) || ( eDockedArea == ui::DockingArea_DOCKINGAREA_LEFT ))
2827 {
2828 // Docking before/after means move track rectangle half column/row.
2829 // As left and top are ordered 0...n instead of right and bottom
2830 // which uses n...0, we have to use negative values for top/left.
2831 nOffsetX *= -1;
2832 nOffsetY *= -1;
2833 }
2834 }
2835 else
2836 {
2837 if (( eDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM ) || ( eDockedArea == ui::DockingArea_DOCKINGAREA_RIGHT ))
2838 {
2839 // Docking before/after means move track rectangle half column/row.
2840 // As left and top are ordered 0...n instead of right and bottom
2841 // which uses n...0, we have to use negative values for top/left.
2842 nOffsetX *= -1;
2843 nOffsetY *= -1;
2844 }
2845 nRowCol++;
2846 }
2847
2848 if ( bHorizontalDockArea )
2849 rUIElement.m_aDockedData.m_aPos.Y = nRowCol;
2850 else
2851 rUIElement.m_aDockedData.m_aPos.X = nRowCol;
2852
2853 rTrackingRect.Move( nOffsetX, nOffsetY );
2854 rTrackingRect.SetSize( aTrackingRect.GetSize() );
2855 }
2856 }
2857 }
2858 }
2859
2860 // Docking outside of our docking window area =>
2861 // Users want to dock before/after first/last docked element or to an empty docking area
2862 if ( !bOpOutsideOfDockingArea )
2863 return;
2864
2865 // set correct size for docking
2866 implts_setTrackingRect( eDockedArea, rMousePos, aTrackingRect );
2867 rTrackingRect = aTrackingRect;
2868
2869 if ( bHorizontalDockArea )
2870 {
2871 sal_Int32 nPosX( std::max( sal_Int32( rTrackingRect.Left()), sal_Int32( 0 )));
2872 if (( nPosX + rTrackingRect.getWidth()) > aContainerWinSize.Width() )
2873 nPosX = std::min( nPosX,
2874 std::max( sal_Int32( aContainerWinSize.Width() - rTrackingRect.getWidth() ),
2875 sal_Int32( 0 )));
2876
2877 sal_Int32 nSize = std::min( aContainerWinSize.Width(), rTrackingRect.getWidth() );
2878 sal_Int32 nDockHeight = std::max( static_cast<sal_Int32>(aDockingAreaRect.getHeight()), sal_Int32( 0 ));
2879 if ( nDockHeight == 0 )
2880 {
2881 sal_Int32 nPosY( std::max( aDockingAreaRect.Top(), aDockingAreaRect.Bottom() ));
2882 if ( eDockedArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
2883 nPosY -= rTrackingRect.getHeight();
2884 rTrackingRect.SetPos( Point( nPosX, nPosY ));
2885 rUIElement.m_aDockedData.m_aPos.Y = 0;
2886 }
2887 else if ( rMousePos.Y() < ( aDockingAreaRect.Top() + ( nDockHeight / 2 )))
2888 {
2889 rTrackingRect.SetPos( Point( nPosX, aDockingAreaRect.Top() - rTrackingRect.getHeight() ));
2890 if ( eDockedArea == ui::DockingArea_DOCKINGAREA_TOP )
2891 rUIElement.m_aDockedData.m_aPos.Y = 0;
2892 else
2893 rUIElement.m_aDockedData.m_aPos.Y = ( nMaxRowCol >= 0 ) ? nMaxRowCol+1 : 0;
2894 rDockingOperation = DOCKOP_BEFORE_COLROW;
2895 }
2896 else
2897 {
2898 rTrackingRect.SetPos( Point( nPosX, aDockingAreaRect.Bottom() ));
2899 if ( eDockedArea == ui::DockingArea_DOCKINGAREA_TOP )
2900 rUIElement.m_aDockedData.m_aPos.Y = ( nMaxRowCol >= 0 ) ? nMaxRowCol+1 : 0;
2901 else
2902 rUIElement.m_aDockedData.m_aPos.Y = 0;
2903 rDockingOperation = DOCKOP_AFTER_COLROW;
2904 }
2905 rTrackingRect.setWidth( nSize );
2906
2907 {
2908 SolarMutexGuard aGuard;
2909 nPosX = pDockingAreaWindow->ScreenToOutputPixel(
2910 pContainerWindow->OutputToScreenPixel( rTrackingRect.TopLeft() )).X();
2911 }
2912 rUIElement.m_aDockedData.m_aPos.X = nPosX;
2913 }
2914 else
2915 {
2916 sal_Int32 nMaxDockingAreaHeight = std::max<sal_Int32>( 0, nMaxLeftRightDockAreaSize );
2917 sal_Int32 nPosY( std::max<sal_Int32>( aTrackingRect.Top(), nTopDockingAreaSize ));
2918 if (( nPosY + aTrackingRect.getHeight()) > ( nTopDockingAreaSize + nMaxDockingAreaHeight ))
2919 nPosY = std::min( nPosY,
2920 std::max<sal_Int32>( nTopDockingAreaSize + ( nMaxDockingAreaHeight - aTrackingRect.getHeight() ),
2921 nTopDockingAreaSize ));
2922
2923 sal_Int32 nSize = std::min( nMaxDockingAreaHeight, static_cast<sal_Int32>(aTrackingRect.getHeight()) );
2924 sal_Int32 nDockWidth = std::max( static_cast<sal_Int32>(aDockingAreaRect.getWidth()), sal_Int32( 0 ));
2925 if ( nDockWidth == 0 )
2926 {
2927 sal_Int32 nPosX( std::max( aDockingAreaRect.Left(), aDockingAreaRect.Right() ));
2928 if ( eDockedArea == ui::DockingArea_DOCKINGAREA_RIGHT )
2929 nPosX -= rTrackingRect.getWidth();
2930 rTrackingRect.SetPos( Point( nPosX, nPosY ));
2931 rUIElement.m_aDockedData.m_aPos.X = 0;
2932 }
2933 else if ( rMousePos.X() < ( aDockingAreaRect.Left() + ( nDockWidth / 2 )))
2934 {
2935 rTrackingRect.SetPos( Point( aDockingAreaRect.Left() - rTrackingRect.getWidth(), nPosY ));
2936 if ( eDockedArea == ui::DockingArea_DOCKINGAREA_LEFT )
2937 rUIElement.m_aDockedData.m_aPos.X = 0;
2938 else
2939 rUIElement.m_aDockedData.m_aPos.X = ( nMaxRowCol >= 0 ) ? nMaxRowCol+1 : 0;
2940 rDockingOperation = DOCKOP_BEFORE_COLROW;
2941 }
2942 else
2943 {
2944 rTrackingRect.SetPos( Point( aDockingAreaRect.Right(), nPosY ));
2945 if ( eDockedArea == ui::DockingArea_DOCKINGAREA_LEFT )
2946 rUIElement.m_aDockedData.m_aPos.X = ( nMaxRowCol >= 0 ) ? nMaxRowCol+1 : 0;
2947 else
2948 rUIElement.m_aDockedData.m_aPos.X = 0;
2949 rDockingOperation = DOCKOP_AFTER_COLROW;
2950 }
2951 rTrackingRect.setHeight( nSize );
2952
2953 {
2954 SolarMutexGuard aGuard;
2955 nPosY = pDockingAreaWindow->ScreenToOutputPixel(
2956 pContainerWindow->OutputToScreenPixel( rTrackingRect.TopLeft() )).Y();
2957 }
2958 rUIElement.m_aDockedData.m_aPos.Y = nPosY;
2959 }
2960}
2961
2962framework::ToolbarLayoutManager::DockingOperation ToolbarLayoutManager::implts_determineDockingOperation(
2963 ui::DockingArea DockingArea,
2964 const ::tools::Rectangle& rRowColRect,
2965 const Point& rMousePos )
2966{
2967 constexpr sal_Int32 nHorzVerticalRegionSize = 6;
2968 constexpr sal_Int32 nHorzVerticalMoveRegion = 4;
2969
2970 if ( rRowColRect.IsInside( rMousePos ))
2971 {
2972 if ( isHorizontalDockingArea( DockingArea ))
2973 {
2974 sal_Int32 nRegion = rRowColRect.getHeight() / nHorzVerticalRegionSize;
2975 sal_Int32 nPosY = rRowColRect.Top() + nRegion;
2976
2977 if ( rMousePos.Y() < nPosY )
2978 return ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP ) ? DOCKOP_BEFORE_COLROW : DOCKOP_AFTER_COLROW;
2979 else if ( rMousePos.Y() < ( nPosY + nRegion*nHorzVerticalMoveRegion ))
2980 return DOCKOP_ON_COLROW;
2981 else
2982 return ( DockingArea == ui::DockingArea_DOCKINGAREA_TOP ) ? DOCKOP_AFTER_COLROW : DOCKOP_BEFORE_COLROW;
2983 }
2984 else
2985 {
2986 sal_Int32 nRegion = rRowColRect.getWidth() / nHorzVerticalRegionSize;
2987 sal_Int32 nPosX = rRowColRect.Left() + nRegion;
2988
2989 if ( rMousePos.X() < nPosX )
2990 return ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT ) ? DOCKOP_BEFORE_COLROW : DOCKOP_AFTER_COLROW;
2991 else if ( rMousePos.X() < ( nPosX + nRegion*nHorzVerticalMoveRegion ))
2992 return DOCKOP_ON_COLROW;
2993 else
2994 return ( DockingArea == ui::DockingArea_DOCKINGAREA_LEFT ) ? DOCKOP_AFTER_COLROW : DOCKOP_BEFORE_COLROW;
2995 }
2996 }
2997 else
2998 return DOCKOP_ON_COLROW;
2999}
3000
3001::tools::Rectangle ToolbarLayoutManager::implts_calcTrackingAndElementRect(
3002 ui::DockingArea eDockingArea,
3003 sal_Int32 nRowCol,
3004 UIElement& rUIElement,
3005 const ::tools::Rectangle& rTrackingRect,
3006 const ::tools::Rectangle& rRowColumnRect,
3007 const ::Size& rContainerWinSize )
3008{
3009 SolarMutexResettableGuard aReadGuard;
3010 ::tools::Rectangle aDockingAreaOffsets( m_aDockingAreaOffsets );
3011 aReadGuard.clear();
3012
3013 bool bHorizontalDockArea( isHorizontalDockingArea( eDockingArea ));
3014
3015 sal_Int32 nTopDockingAreaSize( implts_getTopBottomDockingAreaSizes().Width() );
3016 sal_Int32 nBottomDockingAreaSize( implts_getTopBottomDockingAreaSizes().Height() );
3017
3018 sal_Int32 nMaxLeftRightDockAreaSize = rContainerWinSize.Height() -
3019 nTopDockingAreaSize -
3020 nBottomDockingAreaSize -
3021 aDockingAreaOffsets.Top() -
3022 aDockingAreaOffsets.Bottom();
3023
3024 ::tools::Rectangle aTrackingRect( rTrackingRect );
3025 if ( bHorizontalDockArea )
21
Assuming 'bHorizontalDockArea' is false
22
Taking false branch
3026 {
3027 sal_Int32 nPosX( std::max( sal_Int32( rTrackingRect.Left()), sal_Int32( 0 )));
3028 if (( nPosX + rTrackingRect.getWidth()) > rContainerWinSize.Width() )
3029 nPosX = std::min( nPosX,
3030 std::max( sal_Int32( rContainerWinSize.Width() - rTrackingRect.getWidth() ),
3031 sal_Int32( 0 )));
3032
3033 sal_Int32 nSize = std::min( rContainerWinSize.Width(), rTrackingRect.getWidth() );
3034
3035 aTrackingRect.SetPos( ::Point( nPosX, rRowColumnRect.Top() ));
3036 aTrackingRect.setWidth( nSize );
3037 aTrackingRect.setHeight( rRowColumnRect.getHeight() );
3038
3039 // Set virtual position
3040 rUIElement.m_aDockedData.m_aPos.X = nPosX;
3041 rUIElement.m_aDockedData.m_aPos.Y = nRowCol;
3042 }
3043 else
3044 {
3045 sal_Int32 nMaxDockingAreaHeight = std::max<sal_Int32>( 0, nMaxLeftRightDockAreaSize );
3046
3047 sal_Int32 nPosY( std::max<sal_Int32>( aTrackingRect.Top(), nTopDockingAreaSize ));
3048 if (( nPosY + aTrackingRect.getHeight()) > ( nTopDockingAreaSize + nMaxDockingAreaHeight ))
23
Assuming the condition is false
24
Taking false branch
3049 nPosY = std::min( nPosY,
3050 std::max<sal_Int32>( nTopDockingAreaSize + ( nMaxDockingAreaHeight - aTrackingRect.getHeight() ),
3051 nTopDockingAreaSize ));
3052
3053 sal_Int32 nSize = std::min( nMaxDockingAreaHeight, static_cast<sal_Int32>(aTrackingRect.getHeight()) );
3054
3055 aTrackingRect.SetPos( ::Point( rRowColumnRect.Left(), nPosY ));
3056 aTrackingRect.setWidth( rRowColumnRect.getWidth() );
3057 aTrackingRect.setHeight( nSize );
3058
3059 aReadGuard.reset();
3060 uno::Reference< awt::XWindow > xDockingAreaWindow( m_xDockAreaWindows[static_cast<int>(eDockingArea)] );
3061 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
3062 aReadGuard.clear();
3063
3064 sal_Int32 nDockPosY( 0 );
3065 {
3066 SolarMutexGuard aGuard;
3067 vcl::Window* pDockingAreaWindow = VCLUnoHelper::GetWindow( xDockingAreaWindow ).get();
25
Calling implicit destructor for 'VclPtr<vcl::Window>'
26
Calling '~Reference'
34
Returning from '~Reference'
35
Returning from destructor for 'VclPtr<vcl::Window>'
3068 VclPtr<vcl::Window> pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
3069 nDockPosY = pDockingAreaWindow->ScreenToOutputPixel( pContainerWindow->OutputToScreenPixel( ::Point( 0, nPosY ))).Y();
36
Use of memory after it is freed
3070 }
3071
3072 // Set virtual position
3073 rUIElement.m_aDockedData.m_aPos.X = nRowCol;
3074 rUIElement.m_aDockedData.m_aPos.Y = nDockPosY;
3075 }
3076
3077 return aTrackingRect;
3078}
3079
3080void ToolbarLayoutManager::implts_setTrackingRect( ui::DockingArea eDockingArea, const ::Point& rMousePos, ::tools::Rectangle& rTrackingRect )
3081{
3082 ::Point aPoint( rTrackingRect.TopLeft());
3083 if ( isHorizontalDockingArea( eDockingArea ))
3084 aPoint.setX( rMousePos.X() );
3085 else
3086 aPoint.setY( rMousePos.Y() );
3087 rTrackingRect.SetPos( aPoint );
3088}
3089
3090void ToolbarLayoutManager::implts_renumberRowColumnData(
3091 ui::DockingArea eDockingArea,
3092 const UIElement& rUIElement )
3093{
3094 SolarMutexClearableGuard aReadLock;
3095 uno::Reference< container::XNameAccess > xPersistentWindowState( m_xPersistentWindowState );
3096 aReadLock.clear();
3097
3098 bool bHorzDockingArea( isHorizontalDockingArea( eDockingArea ));
3099 sal_Int32 nRowCol( bHorzDockingArea ? rUIElement.m_aDockedData.m_aPos.Y : rUIElement.m_aDockedData.m_aPos.X );
3100
3101 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3102 {
3103 SolarMutexGuard aWriteLock;
3104 for (auto& elem : m_aUIElements)
3105 {
3106 if ((elem.m_aDockedData.m_nDockedArea == eDockingArea)
3107 && (elem.m_aName != rUIElement.m_aName))
3108 {
3109 // Don't change toolbars without a valid docking position!
3110 if (isDefaultPos(elem.m_aDockedData.m_aPos))
3111 continue;
3112
3113 sal_Int32 nWindowRowCol
3114 = bHorzDockingArea ? elem.m_aDockedData.m_aPos.Y : elem.m_aDockedData.m_aPos.X;
3115 if (nWindowRowCol >= nRowCol)
3116 {
3117 if (bHorzDockingArea)
3118 elem.m_aDockedData.m_aPos.Y += 1;
3119 else
3120 elem.m_aDockedData.m_aPos.X += 1;
3121 }
3122 }
3123 }
3124 }
3125 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3126
3127 // We have to change the persistent window state part
3128 if ( !xPersistentWindowState.is() )
3129 return;
3130
3131 try
3132 {
3133 const uno::Sequence< OUString > aWindowElements = xPersistentWindowState->getElementNames();
3134 for ( OUString const & rWindowElementName : aWindowElements )
3135 {
3136 if ( rUIElement.m_aName != rWindowElementName )
3137 {
3138 try
3139 {
3140 uno::Sequence< beans::PropertyValue > aPropValueSeq;
3141 awt::Point aDockedPos;
3142 ui::DockingArea nDockedArea( ui::DockingArea_DOCKINGAREA_DEFAULT );
3143
3144 xPersistentWindowState->getByName( rWindowElementName ) >>= aPropValueSeq;
3145 for ( beans::PropertyValue const & rProp : std::as_const(aPropValueSeq) )
3146 {
3147 if ( rProp.Name == WINDOWSTATE_PROPERTY_DOCKINGAREA"DockingArea" )
3148 rProp.Value >>= nDockedArea;
3149 else if ( rProp.Name == WINDOWSTATE_PROPERTY_DOCKPOS"DockPos" )
3150 rProp.Value >>= aDockedPos;
3151 }
3152
3153 // Don't change toolbars without a valid docking position!
3154 if ( isDefaultPos( aDockedPos ))
3155 continue;
3156
3157 sal_Int32 nWindowRowCol = bHorzDockingArea ? aDockedPos.Y : aDockedPos.X;
3158 if (( nDockedArea == eDockingArea ) && ( nWindowRowCol >= nRowCol ))
3159 {
3160 if ( bHorzDockingArea )
3161 aDockedPos.Y += 1;
3162 else
3163 aDockedPos.X += 1;
3164
3165 uno::Reference< container::XNameReplace > xReplace( xPersistentWindowState, uno::UNO_QUERY );
3166 xReplace->replaceByName( rWindowElementName, makeAny( aPropValueSeq ));
3167 }
3168 }
3169 catch (const uno::Exception&)
3170 {
3171 }
3172 }
3173 }
3174 }
3175 catch (const uno::Exception&)
3176 {
3177 }
3178}
3179
3180// XWindowListener
3181
3182void SAL_CALL ToolbarLayoutManager::windowResized( const awt::WindowEvent& aEvent )
3183{
3184 SolarMutexClearableGuard aWriteLock;
3185 bool bLocked( m_bDockingInProgress );
3186 bool bLayoutInProgress( m_bLayoutInProgress );
3187 aWriteLock.clear();
3188
3189 // Do not do anything if we are in the middle of a docking process. This would interfere all other
3190 // operations. We will store the new position and size in the docking handlers.
3191 // Do not do anything if we are in the middle of our layouting process. We will adapt the position
3192 // and size of the user interface elements.
3193 if ( bLocked || bLayoutInProgress )
3194 return;
3195
3196 bool bNotify( false );
3197 uno::Reference< awt::XWindow > xWindow( aEvent.Source, uno::UNO_QUERY );
3198
3199 UIElement aUIElement = implts_findToolbar( aEvent.Source );
3200 if ( aUIElement.m_xUIElement.is() )
3201 {
3202 if ( aUIElement.m_bFloating )
3203 {
3204 uno::Reference< awt::XWindow2 > xWindow2( xWindow, uno::UNO_QUERY );
3205
3206 if( xWindow2.is() )
3207 {
3208 awt::Rectangle aPos = xWindow2->getPosSize();
3209 awt::Size aSize = xWindow2->getOutputSize(); // always use output size for consistency
3210 bool bVisible = xWindow2->isVisible();
3211
3212 // update element data
3213 aUIElement.m_aFloatingData.m_aPos = awt::Point(aPos.X, aPos.Y);
3214 aUIElement.m_aFloatingData.m_aSize = aSize;
3215 aUIElement.m_bVisible = bVisible;
3216 }
3217
3218 implts_writeWindowStateData( aUIElement );
3219 }
3220 else
3221 {
3222 implts_setLayoutDirty();
3223 bNotify = true;
3224 }
3225 }
3226
3227 if ( bNotify )
3228 m_pParentLayouter->requestLayout();
3229}
3230
3231void SAL_CALL ToolbarLayoutManager::windowMoved( const awt::WindowEvent& /*aEvent*/ )
3232{
3233}
3234
3235void SAL_CALL ToolbarLayoutManager::windowShown( const lang::EventObject& /*aEvent*/ )
3236{
3237}
3238
3239void SAL_CALL ToolbarLayoutManager::windowHidden( const lang::EventObject& /*aEvent*/ )
3240{
3241}
3242
3243// XDockableWindowListener
3244
3245void SAL_CALL ToolbarLayoutManager::startDocking( const awt::DockingEvent& e )
3246{
3247 bool bWinFound( false );
3248
3249 SolarMutexClearableGuard aReadGuard;
3250 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
3251 uno::Reference< awt::XWindow2 > xWindow( e.Source, uno::UNO_QUERY );
3252 aReadGuard.clear();
3253
3254 UIElement aUIElement = implts_findToolbar( e.Source );
3255
3256 if ( aUIElement.m_xUIElement.is() && xWindow.is() )
3257 {
3258 bWinFound = true;
3259 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
3260 if ( xDockWindow->isFloating() )
3261 {
3262 awt::Rectangle aPos = xWindow->getPosSize();
3263 awt::Size aSize = xWindow->getOutputSize();
3264
3265 aUIElement.m_aFloatingData.m_aPos = awt::Point(aPos.X, aPos.Y);
3266 aUIElement.m_aFloatingData.m_aSize = aSize;
3267
3268 SolarMutexGuard aGuard;
3269
3270 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
3271 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
3272 {
3273 ToolBox* pToolBox = static_cast<ToolBox *>(pWindow.get());
3274 aUIElement.m_aFloatingData.m_nLines = pToolBox->GetFloatingLines();
3275 aUIElement.m_aFloatingData.m_bIsHorizontal = isToolboxHorizontalAligned( pToolBox );
3276 }
3277 }
3278 }
3279
3280 SolarMutexGuard g;
3281 m_bDockingInProgress = bWinFound;
3282 m_aDockUIElement = aUIElement;
3283 m_aDockUIElement.m_bUserActive = true;
3284}
3285
3286awt::DockingData SAL_CALL ToolbarLayoutManager::docking( const awt::DockingEvent& e )
3287{
3288 constexpr sal_Int32 MAGNETIC_DISTANCE_UNDOCK = 25;
3289 constexpr sal_Int32 MAGNETIC_DISTANCE_DOCK = 20;
3290
3291 SolarMutexClearableGuard aReadLock;
3292 awt::DockingData aDockingData;
3293 uno::Reference< awt::XDockableWindow > xDockWindow( e.Source, uno::UNO_QUERY );
3294 uno::Reference< awt::XWindow > xWindow( e.Source, uno::UNO_QUERY );
3295 uno::Reference< awt::XWindow > xTopDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_TOP)] );
3296 uno::Reference< awt::XWindow > xLeftDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_LEFT)] );
3297 uno::Reference< awt::XWindow > xRightDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_RIGHT)] );
3298 uno::Reference< awt::XWindow > xBottomDockingWindow( m_xDockAreaWindows[int(ui::DockingArea_DOCKINGAREA_BOTTOM)] );
3299 uno::Reference< awt::XWindow2 > xContainerWindow( m_xContainerWindow );
3300 UIElement aUIDockingElement( m_aDockUIElement );
3301
3302 bool bDockingInProgress( m_bDockingInProgress );
3303 aReadLock.clear();
3304
3305 if ( bDockingInProgress )
3306 aDockingData.TrackingRectangle = e.TrackingRectangle;
3307
3308 if ( bDockingInProgress && xDockWindow.is() && xWindow.is() )
3309 {
3310 try
3311 {
3312 SolarMutexGuard aGuard;
3313
3314 DockingOperation eDockingOperation( DOCKOP_ON_COLROW );
3315 ui::DockingArea eDockingArea( ui::DockingArea(-1) ); // none
3316 sal_Int32 nMagneticZone( aUIDockingElement.m_bFloating ? MAGNETIC_DISTANCE_DOCK : MAGNETIC_DISTANCE_UNDOCK );
3317 ::tools::Rectangle aTrackingRect( e.TrackingRectangle.X, e.TrackingRectangle.Y,
3318 ( e.TrackingRectangle.X + e.TrackingRectangle.Width ),
3319 ( e.TrackingRectangle.Y + e.TrackingRectangle.Height ));
3320
3321 awt::Rectangle aTmpRect = xTopDockingWindow->getPosSize();
3322 ::tools::Rectangle aTopDockRect( aTmpRect.X, aTmpRect.Y, aTmpRect.Width, aTmpRect.Height );
3323 ::tools::Rectangle aHotZoneTopDockRect( implts_calcHotZoneRect( aTopDockRect, nMagneticZone ));
3324
3325 aTmpRect = xBottomDockingWindow->getPosSize();
3326 ::tools::Rectangle aBottomDockRect( aTmpRect.X, aTmpRect.Y, ( aTmpRect.X + aTmpRect.Width), ( aTmpRect.Y + aTmpRect.Height ));
3327 ::tools::Rectangle aHotZoneBottomDockRect( implts_calcHotZoneRect( aBottomDockRect, nMagneticZone ));
3328
3329 aTmpRect = xLeftDockingWindow->getPosSize();
3330 ::tools::Rectangle aLeftDockRect( aTmpRect.X, aTmpRect.Y, ( aTmpRect.X + aTmpRect.Width ), ( aTmpRect.Y + aTmpRect.Height ));
3331 ::tools::Rectangle aHotZoneLeftDockRect( implts_calcHotZoneRect( aLeftDockRect, nMagneticZone ));
3332
3333 aTmpRect = xRightDockingWindow->getPosSize();
3334 ::tools::Rectangle aRightDockRect( aTmpRect.X, aTmpRect.Y, ( aTmpRect.X + aTmpRect.Width ), ( aTmpRect.Y + aTmpRect.Height ));
3335 ::tools::Rectangle aHotZoneRightDockRect( implts_calcHotZoneRect( aRightDockRect, nMagneticZone ));
3336
3337 VclPtr<vcl::Window> pContainerWindow( VCLUnoHelper::GetWindow( xContainerWindow ) );
3338 ::Point aMousePos( pContainerWindow->ScreenToOutputPixel( ::Point( e.MousePos.X, e.MousePos.Y )));
3339
3340 if ( aHotZoneTopDockRect.IsInside( aMousePos ))
3341 eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
3342 else if ( aHotZoneBottomDockRect.IsInside( aMousePos ))
3343 eDockingArea = ui::DockingArea_DOCKINGAREA_BOTTOM;
3344 else if ( aHotZoneLeftDockRect.IsInside( aMousePos ))
3345 eDockingArea = ui::DockingArea_DOCKINGAREA_LEFT;
3346 else if ( aHotZoneRightDockRect.IsInside( aMousePos ))
3347 eDockingArea = ui::DockingArea_DOCKINGAREA_RIGHT;
3348
3349 // Higher priority for movements inside the real docking area
3350 if ( aTopDockRect.IsInside( aMousePos ))
3351 eDockingArea = ui::DockingArea_DOCKINGAREA_TOP;
3352 else if ( aBottomDockRect.IsInside( aMousePos ))
3353 eDockingArea = ui::DockingArea_DOCKINGAREA_BOTTOM;
3354 else if ( aLeftDockRect.IsInside( aMousePos ))
3355 eDockingArea = ui::DockingArea_DOCKINGAREA_LEFT;
3356 else if ( aRightDockRect.IsInside( aMousePos ))
3357 eDockingArea = ui::DockingArea_DOCKINGAREA_RIGHT;
3358
3359 // Determine if we have a toolbar and set alignment according to the docking area!
3360 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
3361 ToolBox* pToolBox = nullptr;
3362 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
3363 pToolBox = static_cast<ToolBox *>(pWindow.get());
3364
3365 if ( eDockingArea != ui::DockingArea(-1) )
3366 {
3367 if ( eDockingArea == ui::DockingArea_DOCKINGAREA_TOP )
3368 {
3369 aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_TOP;
3370 aUIDockingElement.m_bFloating = false;
3371 }
3372 else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_BOTTOM )
3373 {
3374 aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_BOTTOM;
3375 aUIDockingElement.m_bFloating = false;
3376 }
3377 else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_LEFT )
3378 {
3379 aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_LEFT;
3380 aUIDockingElement.m_bFloating = false;
3381 }
3382 else if ( eDockingArea == ui::DockingArea_DOCKINGAREA_RIGHT )
3383 {
3384 aUIDockingElement.m_aDockedData.m_nDockedArea = ui::DockingArea_DOCKINGAREA_RIGHT;
3385 aUIDockingElement.m_bFloating = false;
3386 }
3387
3388 ::Point aOutputPos = pContainerWindow->ScreenToOutputPixel( aTrackingRect.TopLeft() );
3389 aTrackingRect.SetPos( aOutputPos );
3390
3391 ::tools::Rectangle aNewDockingRect( aTrackingRect );
3392
3393 implts_calcDockingPosSize( aUIDockingElement, eDockingOperation, aNewDockingRect, aMousePos );
3394
3395 ::Point aScreenPos = pContainerWindow->OutputToScreenPixel( aNewDockingRect.TopLeft() );
3396 aDockingData.TrackingRectangle = awt::Rectangle( aScreenPos.X(), aScreenPos.Y(),
3397 aNewDockingRect.getWidth(), aNewDockingRect.getHeight() );
3398 }
3399 else if (pToolBox)
3400 {
3401 bool bIsHorizontal = isToolboxHorizontalAligned( pToolBox );
3402 awt::Size aFloatSize = aUIDockingElement.m_aFloatingData.m_aSize;
3403 if ( aFloatSize.Width > 0 && aFloatSize.Height > 0 )
3404 {
3405 aUIDockingElement.m_aFloatingData.m_aPos = AWTPoint(pContainerWindow->ScreenToOutputPixel(VCLPoint(e.MousePos)));
3406 aDockingData.TrackingRectangle.Height = aFloatSize.Height;
3407 aDockingData.TrackingRectangle.Width = aFloatSize.Width;
3408 }
3409 else
3410 {
3411 aFloatSize = AWTSize(pToolBox->CalcWindowSizePixel());
3412 if ( !bIsHorizontal )
3413 {
3414 // Floating toolbars are always horizontal aligned! We have to swap
3415 // width/height if we have a vertical aligned toolbar.
3416 sal_Int32 nTemp = aFloatSize.Height;
3417 aFloatSize.Height = aFloatSize.Width;
3418 aFloatSize.Width = nTemp;
3419 }
3420
3421 aDockingData.TrackingRectangle.Height = aFloatSize.Height;
3422 aDockingData.TrackingRectangle.Width = aFloatSize.Width;
3423
3424 // For the first time we don't have any data about the floating size of a toolbar.
3425 // We calculate it and store it for later use.
3426 aUIDockingElement.m_aFloatingData.m_aPos = AWTPoint(pContainerWindow->ScreenToOutputPixel(VCLPoint(e.MousePos)));
3427 aUIDockingElement.m_aFloatingData.m_aSize = aFloatSize;
3428 aUIDockingElement.m_aFloatingData.m_nLines = pToolBox->GetFloatingLines();
3429 aUIDockingElement.m_aFloatingData.m_bIsHorizontal = isToolboxHorizontalAligned( pToolBox );
3430 }
3431 aDockingData.TrackingRectangle.X = e.MousePos.X;
3432 aDockingData.TrackingRectangle.Y = e.MousePos.Y;
3433 }
3434
3435 aDockingData.bFloating = ( eDockingArea == ui::DockingArea(-1) );
3436
3437 // Write current data to the member docking progress data
3438 SolarMutexGuard g;
3439 m_aDockUIElement.m_bFloating = aDockingData.bFloating;
3440 if ( !aDockingData.bFloating )
3441 {
3442 m_aDockUIElement.m_aDockedData = aUIDockingElement.m_aDockedData;
3443
3444 m_eDockOperation = eDockingOperation;
3445 }
3446 else
3447 m_aDockUIElement.m_aFloatingData = aUIDockingElement.m_aFloatingData;
3448 }
3449 catch (const uno::Exception&)
3450 {
3451 }
3452 }
3453
3454 return aDockingData;
3455}
3456
3457void SAL_CALL ToolbarLayoutManager::endDocking( const awt::EndDockingEvent& e )
3458{
3459 if (e.bCancelled)
3460 return;
3461
3462 bool bDockingInProgress( false );
3463 bool bStartDockFloated( false );
3464 bool bFloating( false );
3465 UIElement aUIDockingElement;
3466
3467 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3468 SolarMutexResettableGuard aWriteLock;
3469 bDockingInProgress = m_bDockingInProgress;
3470 aUIDockingElement = m_aDockUIElement;
3471 bFloating = aUIDockingElement.m_bFloating;
3472
3473 UIElement& rUIElement = impl_findToolbar( aUIDockingElement.m_aName );
3474 if ( rUIElement.m_aName == aUIDockingElement.m_aName )
3475 {
3476 if ( aUIDockingElement.m_bFloating )
3477 {
3478 // Write last position into position data
3479 uno::Reference< awt::XWindow > xWindow( aUIDockingElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
3480 rUIElement.m_aFloatingData = aUIDockingElement.m_aFloatingData;
3481 awt::Rectangle aTmpRect = xWindow->getPosSize();
3482 rUIElement.m_aFloatingData.m_aPos = awt::Point(aTmpRect.X, aTmpRect.Y);
3483 // make changes also for our local data as we use it to make data persistent
3484 aUIDockingElement.m_aFloatingData = rUIElement.m_aFloatingData;
3485 }
3486 else
3487 {
3488 rUIElement.m_aDockedData = aUIDockingElement.m_aDockedData;
3489 rUIElement.m_aFloatingData.m_aSize = aUIDockingElement.m_aFloatingData.m_aSize;
3490
3491 if ( m_eDockOperation != DOCKOP_ON_COLROW )
3492 {
3493 // we have to renumber our row/column data to insert a new row/column
3494 implts_renumberRowColumnData(aUIDockingElement.m_aDockedData.m_nDockedArea, aUIDockingElement );
3495 }
3496 }
3497
3498 bStartDockFloated = rUIElement.m_bFloating;
3499 rUIElement.m_bFloating = m_aDockUIElement.m_bFloating;
3500 rUIElement.m_bUserActive = true;
3501 }
3502
3503 // reset member for next docking operation
3504 m_aDockUIElement.m_xUIElement.clear();
3505 m_eDockOperation = DOCKOP_ON_COLROW;
3506 aWriteLock.clear();
3507 /* SAFE AREA ----------------------------------------------------------------------------------------------- */
3508
3509 implts_writeWindowStateData( aUIDockingElement );
3510
3511 if ( bDockingInProgress )
3512 {
3513 SolarMutexGuard aGuard;
3514 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( uno::Reference< awt::XWindow >( e.Source, uno::UNO_QUERY ));
3515 ToolBox* pToolBox = nullptr;
3516 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
3517 pToolBox = static_cast<ToolBox *>(pWindow.get());
3518
3519 if ( pToolBox )
3520 {
3521 if( e.bFloating )
3522 {
3523 if ( aUIDockingElement.m_aFloatingData.m_bIsHorizontal )
3524 pToolBox->SetAlign();
3525 else
3526 pToolBox->SetAlign( WindowAlign::Left );
3527 }
3528 else
3529 {
3530 ::Size aSize;
3531
3532 pToolBox->SetAlign( ImplConvertAlignment( aUIDockingElement.m_aDockedData.m_nDockedArea) );
3533
3534 // Docked toolbars have always one line
3535 aSize = pToolBox->CalcWindowSizePixel( 1 );
3536
3537 // Lock layouting updates as our listener would be called due to SetSizePixel
3538 pToolBox->SetOutputSizePixel( aSize );
3539 }
3540 }
3541 }
3542
3543 implts_sortUIElements();
3544
3545 aWriteLock.reset();
3546 m_bDockingInProgress = false;
3547 m_bLayoutDirty = !bStartDockFloated || !bFloating;
3548 bool bNotify = m_bLayoutDirty;
3549 aWriteLock.clear();
3550
3551 if ( bNotify )
3552 m_pParentLayouter->requestLayout();
3553}
3554
3555sal_Bool SAL_CALL ToolbarLayoutManager::prepareToggleFloatingMode( const lang::EventObject& e )
3556{
3557 SolarMutexClearableGuard aReadLock;
3558 bool bDockingInProgress = m_bDockingInProgress;
3559 aReadLock.clear();
3560
3561 UIElement aUIDockingElement = implts_findToolbar( e.Source );
3562 bool bWinFound( !aUIDockingElement.m_aName.isEmpty() );
3563 uno::Reference< awt::XWindow > xWindow( e.Source, uno::UNO_QUERY );
3564
3565 if ( bWinFound && xWindow.is() )
3566 {
3567 if ( !bDockingInProgress )
3568 {
3569 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
3570 if ( xDockWindow->isFloating() )
3571 {
3572 {
3573 SolarMutexGuard aGuard;
3574 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
3575 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
3576 {
3577 ToolBox* pToolBox = static_cast< ToolBox *>( pWindow.get() );
3578 aUIDockingElement.m_aFloatingData.m_aPos = AWTPoint(pToolBox->GetPosPixel());
3579 aUIDockingElement.m_aFloatingData.m_aSize = AWTSize(pToolBox->GetOutputSizePixel());
3580 aUIDockingElement.m_aFloatingData.m_nLines = pToolBox->GetFloatingLines();
3581 aUIDockingElement.m_aFloatingData.m_bIsHorizontal = isToolboxHorizontalAligned( pToolBox );
3582 }
3583 }
3584
3585 UIElement aUIElement = implts_findToolbar( aUIDockingElement.m_aName );
3586 if ( aUIElement.m_aName == aUIDockingElement.m_aName )
3587 implts_setToolbar( aUIDockingElement );
3588 }
3589 }
3590 }
3591
3592 return true;
3593}
3594
3595void SAL_CALL ToolbarLayoutManager::toggleFloatingMode( const lang::EventObject& e )
3596{
3597 UIElement aUIDockingElement;
3598
3599 SolarMutexResettableGuard aReadLock;
3600 bool bDockingInProgress( m_bDockingInProgress );
3601 if ( bDockingInProgress )
3602 aUIDockingElement = m_aDockUIElement;
3603 aReadLock.clear();
3604
3605 vcl::Window* pWindow( nullptr );
3606 ToolBox* pToolBox( nullptr );
3607 uno::Reference< awt::XWindow2 > xWindow;
3608
3609 {
3610 SolarMutexGuard aGuard;
3611 xWindow.set( e.Source, uno::UNO_QUERY );
3612 pWindow = VCLUnoHelper::GetWindow( xWindow ).get();
3613
3614 if ( pWindow && pWindow->GetType() == WindowType::TOOLBOX )
3615 pToolBox = static_cast<ToolBox *>(pWindow);
3616 }
3617
3618 if ( !bDockingInProgress )
3619 {
3620 aUIDockingElement = implts_findToolbar( e.Source );
3621 bool bWinFound = !aUIDockingElement.m_aName.isEmpty();
3622
3623 if ( bWinFound && xWindow.is() )
3624 {
3625 aUIDockingElement.m_bFloating = !aUIDockingElement.m_bFloating;
3626 aUIDockingElement.m_bUserActive = true;
3627
3628 implts_setLayoutInProgress();
3629 if ( aUIDockingElement.m_bFloating )
3630 {
3631 SolarMutexGuard aGuard;
3632 if ( pToolBox )
3633 {
3634 pToolBox->SetLineCount( aUIDockingElement.m_aFloatingData.m_nLines );
3635 if ( aUIDockingElement.m_aFloatingData.m_bIsHorizontal )
3636 pToolBox->SetAlign();
3637 else
3638 pToolBox->SetAlign( WindowAlign::Left );
3639 }
3640
3641 bool bUndefPos = hasDefaultPosValue( aUIDockingElement.m_aFloatingData.m_aPos );
3642 bool bSetSize = !hasEmptySize( aUIDockingElement.m_aFloatingData.m_aSize );
3643
3644 if ( bUndefPos )
3645 aUIDockingElement.m_aFloatingData.m_aPos = implts_findNextCascadeFloatingPos();
3646
3647 if ( !bSetSize )
3648 {
3649 if ( pToolBox )
3650 aUIDockingElement.m_aFloatingData.m_aSize = AWTSize(pToolBox->CalcFloatingWindowSizePixel());
3651 else if ( pWindow )
3652 aUIDockingElement.m_aFloatingData.m_aSize = AWTSize(pWindow->GetOutputSizePixel());
3653 }
3654
3655 xWindow->setPosSize( aUIDockingElement.m_aFloatingData.m_aPos.X,
3656 aUIDockingElement.m_aFloatingData.m_aPos.Y,
3657 0, 0, awt::PosSize::POS );
3658 xWindow->setOutputSize(aUIDockingElement.m_aFloatingData.m_aSize);
3659 }
3660 else
3661 {
3662 if ( isDefaultPos( aUIDockingElement.m_aDockedData.m_aPos ))
3663 {
3664 // Docking on its default position without a preset position -
3665 // we have to find a good place for it.
3666 ::Point aPixelPos;
3667 awt::Point aDockPos;
3668 ::Size aSize;
3669
3670 {
3671 SolarMutexGuard aGuard;
3672 if ( pToolBox )
3673 aSize = pToolBox->CalcWindowSizePixel( 1, ImplConvertAlignment( aUIDockingElement.m_aDockedData.m_nDockedArea ) );
3674 else if ( pWindow )
3675 aSize = pWindow->GetSizePixel();
3676 }
3677
3678 implts_findNextDockingPos(aUIDockingElement.m_aDockedData.m_nDockedArea, aSize, aDockPos, aPixelPos );
3679 aUIDockingElement.m_aDockedData.m_aPos = aDockPos;
3680 }
3681
3682 SolarMutexGuard aGuard;
3683 if ( pToolBox )
3684 {
3685 pToolBox->SetAlign( ImplConvertAlignment( aUIDockingElement.m_aDockedData.m_nDockedArea) );
3686 ::Size aSize = pToolBox->CalcWindowSizePixel( 1 );
3687 awt::Rectangle aRect = xWindow->getPosSize();
3688 xWindow->setPosSize( aRect.X, aRect.Y, 0, 0, awt::PosSize::POS );
3689 xWindow->setOutputSize( AWTSize( aSize ) );
3690 }
3691 }
3692
3693 implts_setLayoutInProgress( false );
3694 implts_setToolbar( aUIDockingElement );
3695 implts_writeWindowStateData( aUIDockingElement );
3696 implts_sortUIElements();
3697 implts_setLayoutDirty();
3698
3699 aReadLock.reset();
3700 LayoutManager* pParentLayouter( m_pParentLayouter );
3701 aReadLock.clear();
3702
3703 if ( pParentLayouter )
3704 pParentLayouter->requestLayout();
3705 }
3706 }
3707 else
3708 {
3709 SolarMutexGuard aGuard;
3710 if ( pToolBox )
3711 {
3712 if ( aUIDockingElement.m_bFloating )
3713 {
3714 if ( aUIDockingElement.m_aFloatingData.m_bIsHorizontal )
3715 pToolBox->SetAlign();
3716 else
3717 pToolBox->SetAlign( WindowAlign::Left );
3718 }
3719 else
3720 pToolBox->SetAlign( ImplConvertAlignment( aUIDockingElement.m_aDockedData.m_nDockedArea) );
3721 }
3722 }
3723}
3724
3725void SAL_CALL ToolbarLayoutManager::closed( const lang::EventObject& e )
3726{
3727 OUString aName;
3728 UIElement aUIElement;
3729
3730 {
3731 SolarMutexGuard aWriteLock;
3732 for (auto& elem : m_aUIElements)
3733 {
3734 uno::Reference<ui::XUIElement> xUIElement(elem.m_xUIElement);
3735 if (xUIElement.is())
3736 {
3737 uno::Reference<uno::XInterface> xIfac(xUIElement->getRealInterface(),
3738 uno::UNO_QUERY);
3739 if (xIfac == e.Source)
3740 {
3741 aName = elem.m_aName;
3742
3743 // user closes a toolbar =>
3744 // context sensitive toolbar: only destroy toolbar and store state.
3745 // non context sensitive toolbar: make it invisible, store state and destroy it.
3746 if (!elem.m_bContextSensitive)
3747 elem.m_bVisible = false;
3748
3749 aUIElement = elem;
3750 break;
3751 }
3752 }
3753 }
3754 }
3755
3756 // destroy element
3757 if ( aName.isEmpty() )
3758 return;
3759
3760 implts_writeWindowStateData( aUIElement );
3761 destroyToolbar( aName );
3762
3763 SolarMutexClearableGuard aReadLock;
3764 bool bLayoutDirty = m_bLayoutDirty;
3765 LayoutManager* pParentLayouter( m_pParentLayouter );
3766 aReadLock.clear();
3767
3768 if ( bLayoutDirty && pParentLayouter )
3769 pParentLayouter->requestLayout();
3770}
3771
3772void SAL_CALL ToolbarLayoutManager::endPopupMode( const awt::EndPopupModeEvent& /*e*/ )
3773{
3774}
3775
3776// XUIConfigurationListener
3777
3778void SAL_CALL ToolbarLayoutManager::elementInserted( const ui::ConfigurationEvent& rEvent )
3779{
3780 UIElement aUIElement = implts_findToolbar( rEvent.ResourceURL );
3781
3782 uno::Reference< ui::XUIElementSettings > xElementSettings( aUIElement.m_xUIElement, uno::UNO_QUERY );
3783 if ( xElementSettings.is() )
3784 {
3785 uno::Reference< beans::XPropertySet > xPropSet( xElementSettings, uno::UNO_QUERY );
3786 if ( xPropSet.is() )
3787 {
3788 if ( rEvent.Source == uno::Reference< uno::XInterface >( m_xDocCfgMgr, uno::UNO_QUERY ))
3789 xPropSet->setPropertyValue( "ConfigurationSource", makeAny( m_xDocCfgMgr ));
3790 }
3791 xElementSettings->updateSettings();
3792 }
3793 else
3794 {
3795 OUString aElementType;
3796 OUString aElementName;
3797 parseResourceURL( rEvent.ResourceURL, aElementType, aElementName );
3798 if ( aElementName.indexOf( "custom_" ) != -1 )
3799 {
3800 // custom toolbar must be directly created, shown and layouted!
3801 createToolbar( rEvent.ResourceURL );
3802 uno::Reference< ui::XUIElement > xUIElement = getToolbar( rEvent.ResourceURL );
3803 if ( xUIElement.is() )
3804 {
3805 OUString aUIName;
3806 uno::Reference< ui::XUIConfigurationManager > xCfgMgr;
3807 uno::Reference< beans::XPropertySet > xPropSet;
3808
3809 try
3810 {
3811 xCfgMgr.set( rEvent.Source, uno::UNO_QUERY );
3812 xPropSet.set( xCfgMgr->getSettings( rEvent.ResourceURL, false ), uno::UNO_QUERY );
3813
3814 if ( xPropSet.is() )
3815 xPropSet->getPropertyValue("UIName") >>= aUIName;
3816 }
3817 catch (const container::NoSuchElementException&)
3818 {
3819 }
3820 catch (const beans::UnknownPropertyException&)
3821 {
3822 }
3823 catch (const lang::WrappedTargetException&)
3824 {
3825 }
3826
3827 {
3828 SolarMutexGuard aGuard;
3829 vcl::Window* pWindow = getWindowFromXUIElement( xUIElement );
3830 if ( pWindow )
3831 pWindow->SetText( aUIName );
3832 }
3833
3834 showToolbar( rEvent.ResourceURL );
3835 }
3836 }
3837 }
3838}
3839
3840void SAL_CALL ToolbarLayoutManager::elementRemoved( const ui::ConfigurationEvent& rEvent )
3841{
3842 SolarMutexClearableGuard aReadLock;
3843 uno::Reference< awt::XWindow > xContainerWindow = m_xContainerWindow;
3844 uno::Reference< ui::XUIConfigurationManager > xModuleCfgMgr( m_xModuleCfgMgr );
3845 uno::Reference< ui::XUIConfigurationManager > xDocCfgMgr( m_xDocCfgMgr );
3846 aReadLock.clear();
3847
3848 UIElement aUIElement = implts_findToolbar( rEvent.ResourceURL );
3849 uno::Reference< ui::XUIElementSettings > xElementSettings( aUIElement.m_xUIElement, uno::UNO_QUERY );
3850 if ( !xElementSettings.is() )
3851 return;
3852
3853 bool bNoSettings( false );
3854 OUString aConfigSourcePropName( "ConfigurationSource" );
3855 uno::Reference< uno::XInterface > xElementCfgMgr;
3856 uno::Reference< beans::XPropertySet > xPropSet( xElementSettings, uno::UNO_QUERY );
3857
3858 if ( xPropSet.is() )
3859 xPropSet->getPropertyValue( aConfigSourcePropName ) >>= xElementCfgMgr;
3860
3861 if ( !xElementCfgMgr.is() )
3862 return;
3863
3864 // Check if the same UI configuration manager has changed => check further
3865 if ( rEvent.Source == xElementCfgMgr )
3866 {
3867 // Same UI configuration manager where our element has its settings
3868 if ( rEvent.Source == uno::Reference< uno::XInterface >( xDocCfgMgr, uno::UNO_QUERY ))
3869 {
3870 // document settings removed
3871 if ( xModuleCfgMgr->hasSettings( rEvent.ResourceURL ))
3872 {
3873 xPropSet->setPropertyValue( aConfigSourcePropName, makeAny( xModuleCfgMgr ));
3874 xElementSettings->updateSettings();
3875 return;
3876 }
3877 }
3878
3879 bNoSettings = true;
3880 }
3881
3882 // No settings anymore, element must be destroyed
3883 if ( xContainerWindow.is() && bNoSettings )
3884 destroyToolbar( rEvent.ResourceURL );
3885}
3886
3887void SAL_CALL ToolbarLayoutManager::elementReplaced( const ui::ConfigurationEvent& rEvent )
3888{
3889 UIElement aUIElement = implts_findToolbar( rEvent.ResourceURL );
3890
3891 uno::Reference< ui::XUIElementSettings > xElementSettings( aUIElement.m_xUIElement, uno::UNO_QUERY );
3892 if ( !xElementSettings.is() )
3893 return;
3894
3895 uno::Reference< uno::XInterface > xElementCfgMgr;
3896 uno::Reference< beans::XPropertySet > xPropSet( xElementSettings, uno::UNO_QUERY );
3897
3898 if ( xPropSet.is() )
3899 xPropSet->getPropertyValue( "ConfigurationSource" ) >>= xElementCfgMgr;
3900
3901 if ( !xElementCfgMgr.is() )
3902 return;
3903
3904 // Check if the same UI configuration manager has changed => update settings
3905 if ( rEvent.Source != xElementCfgMgr )
3906 return;
3907
3908 xElementSettings->updateSettings();
3909
3910 SolarMutexClearableGuard aWriteLock;
3911 bool bNotify = !aUIElement.m_bFloating;
3912 m_bLayoutDirty = bNotify;
3913 LayoutManager* pParentLayouter( m_pParentLayouter );
3914 aWriteLock.clear();
3915
3916 if ( bNotify && pParentLayouter )
3917 pParentLayouter->requestLayout();
3918}
3919
3920uno::Reference< ui::XUIElement > ToolbarLayoutManager::getToolbar( const OUString& aName )
3921{
3922 return implts_findToolbar( aName ).m_xUIElement;
3923}
3924
3925uno::Sequence< uno::Reference< ui::XUIElement > > ToolbarLayoutManager::getToolbars()
3926{
3927 uno::Sequence< uno::Reference< ui::XUIElement > > aSeq;
3928
3929 SolarMutexGuard g;
3930 if ( !m_aUIElements.empty() )
3931 {
3932 sal_uInt32 nCount(0);
3933 for (auto const& elem : m_aUIElements)
3934 {
3935 if ( elem.m_xUIElement.is() )
3936 {
3937 ++nCount;
3938 aSeq.realloc( nCount );
3939 aSeq[nCount-1] = elem.m_xUIElement;
3940 }
3941 }
3942 }
3943
3944 return aSeq;
3945}
3946
3947bool ToolbarLayoutManager::floatToolbar( const OUString& rResourceURL )
3948{
3949 UIElement aUIElement = implts_findToolbar( rResourceURL );
3950 if ( aUIElement.m_xUIElement.is() )
3951 {
3952 try
3953 {
3954 uno::Reference< awt::XDockableWindow > xDockWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
3955 if ( xDockWindow.is() && !xDockWindow->isFloating() )
3956 {
3957 aUIElement.m_bFloating = true;
3958 implts_writeWindowStateData( aUIElement );
3959 xDockWindow->setFloatingMode( true );
3960
3961 implts_setLayoutDirty();
3962 implts_setToolbar( aUIElement );
3963 return true;
3964 }
3965 }
3966 catch (const lang::DisposedException&)
3967 {
3968 }
3969 }
3970
3971 return false;
3972}
3973
3974bool ToolbarLayoutManager::lockToolbar( const OUString& rResourceURL )
3975{
3976 UIElement aUIElement = implts_findToolbar( rResourceURL );
3977 if ( aUIElement.m_xUIElement.is() )
3978 {
3979 try
3980 {
3981 uno::Reference< awt::XDockableWindow > xDockWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
3982 if ( xDockWindow.is() && !xDockWindow->isFloating() && !xDockWindow->isLocked() )
3983 {
3984 aUIElement.m_aDockedData.m_bLocked = true;
3985 implts_writeWindowStateData( aUIElement );
3986 xDockWindow->lock();
3987
3988 implts_setLayoutDirty();
3989 implts_setToolbar( aUIElement );
3990 return true;
3991 }
3992 }
3993 catch (const lang::DisposedException&)
3994 {
3995 }
3996 }
3997
3998 return false;
3999}
4000
4001bool ToolbarLayoutManager::unlockToolbar( const OUString& rResourceURL )
4002{
4003 UIElement aUIElement = implts_findToolbar( rResourceURL );
4004 if ( aUIElement.m_xUIElement.is() )
4005 {
4006 try
4007 {
4008 uno::Reference< awt::XDockableWindow > xDockWindow( aUIElement.m_xUIElement->getRealInterface(), uno::UNO_QUERY );
4009 if ( xDockWindow.is() && !xDockWindow->isFloating() && xDockWindow->isLocked() )
4010 {
4011 aUIElement.m_aDockedData.m_bLocked = false;
4012 implts_writeWindowStateData( aUIElement );
4013 xDockWindow->unlock();
4014
4015 implts_setLayoutDirty();
4016 implts_setToolbar( aUIElement );
4017 return true;
4018 }
4019 }
4020 catch (const lang::DisposedException&)
4021 {
4022 }
4023 }
4024
4025 return false;
4026}
4027
4028bool ToolbarLayoutManager::isToolbarVisible( const OUString& rResourceURL )
4029{
4030 uno::Reference< awt::XWindow2 > xWindow2( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
4031 return ( xWindow2.is() && xWindow2->isVisible() );
4032}
4033
4034bool ToolbarLayoutManager::isToolbarFloating( const OUString& rResourceURL )
4035{
4036 uno::Reference< awt::XDockableWindow > xDockWindow( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
4037 return ( xDockWindow.is() && xDockWindow->isFloating() );
4038}
4039
4040bool ToolbarLayoutManager::isToolbarDocked( const OUString& rResourceURL )
4041{
4042 return !isToolbarFloating( rResourceURL );
4043}
4044
4045bool ToolbarLayoutManager::isToolbarLocked( const OUString& rResourceURL )
4046{
4047 uno::Reference< awt::XDockableWindow > xDockWindow( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
4048 return ( xDockWindow.is() && xDockWindow->isLocked() );
4049}
4050
4051awt::Size ToolbarLayoutManager::getToolbarSize( const OUString& rResourceURL )
4052{
4053 vcl::Window* pWindow = implts_getWindow( rResourceURL );
4054
4055 SolarMutexGuard aGuard;
4056 if ( pWindow )
4057 {
4058 ::Size aSize = pWindow->GetSizePixel();
4059 awt::Size aWinSize;
4060 aWinSize.Width = aSize.Width();
4061 aWinSize.Height = aSize.Height();
4062 return aWinSize;
4063 }
4064
4065 return awt::Size();
4066}
4067
4068awt::Point ToolbarLayoutManager::getToolbarPos( const OUString& rResourceURL )
4069{
4070 awt::Point aPos;
4071 UIElement aUIElement = implts_findToolbar( rResourceURL );
4072
4073 uno::Reference< awt::XWindow > xWindow( implts_getXWindow( rResourceURL ));
4074 if ( xWindow.is() )
4075 {
4076 if ( aUIElement.m_bFloating )
4077 {
4078 awt::Rectangle aRect = xWindow->getPosSize();
4079 aPos.X = aRect.X;
4080 aPos.Y = aRect.Y;
4081 }
4082 else
4083 aPos = aUIElement.m_aDockedData.m_aPos;
4084 }
4085
4086 return aPos;
4087}
4088
4089void ToolbarLayoutManager::setToolbarSize( const OUString& rResourceURL, const awt::Size& aSize )
4090{
4091 uno::Reference< awt::XWindow2 > xWindow( implts_getXWindow( rResourceURL ), uno::UNO_QUERY );
4092 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
4093 UIElement aUIElement = implts_findToolbar( rResourceURL );
4094
4095 if ( xWindow.is() && xDockWindow.is() && xDockWindow->isFloating() )
4096 {
4097 xWindow->setOutputSize( aSize );
4098 aUIElement.m_aFloatingData.m_aSize = aSize;
4099 implts_setToolbar( aUIElement );
4100 implts_writeWindowStateData( aUIElement );
4101 implts_sortUIElements();
4102 }
4103}
4104
4105void ToolbarLayoutManager::setToolbarPos( const OUString& rResourceURL, const awt::Point& aPos )
4106{
4107 uno::Reference< awt::XWindow > xWindow( implts_getXWindow( rResourceURL ));
4108 uno::Reference< awt::XDockableWindow > xDockWindow( xWindow, uno::UNO_QUERY );
4109 UIElement aUIElement = implts_findToolbar( rResourceURL );
4110
4111 if ( xWindow.is() && xDockWindow.is() && xDockWindow->isFloating() )
4112 {
4113 xWindow->setPosSize( aPos.X, aPos.Y, 0, 0, awt::PosSize::POS );
4114 aUIElement.m_aFloatingData.m_aPos = aPos;
4115 implts_setToolbar( aUIElement );
4116 implts_writeWindowStateData( aUIElement );
4117 implts_sortUIElements();
4118 }
4119}
4120
4121void ToolbarLayoutManager::setToolbarPosSize( const OUString& rResourceURL, const awt::Point& aPos, const awt::Size& aSize )
4122{
4123 setToolbarPos( rResourceURL, aPos );
4124 setToolbarSize( rResourceURL, aSize );
4125}
4126
4127} // namespace framework
4128
4129/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/rtl/ref.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#ifndef INCLUDED_RTL_REF_HXX
21#define INCLUDED_RTL_REF_HXX
22
23#include "sal/config.h"
24
25#include <cassert>
26#include <cstddef>
27#include <functional>
28#ifdef LIBO_INTERNAL_ONLY1
29#include <type_traits>
30#endif
31
32#include "sal/types.h"
33
34namespace rtl
35{
36
37/** Template reference class for reference type.
38*/
39template <class reference_type>
40class Reference
41{
42 /** The <b>reference_type</b> body pointer.
43 */
44 reference_type * m_pBody;
45
46
47public:
48 /** Constructor...
49 */
50 Reference()
51 : m_pBody (NULL__null)
52 {}
53
54
55 /** Constructor...
56 */
57 Reference (reference_type * pBody, __sal_NoAcquire)
58 : m_pBody (pBody)
59 {
60 }
61
62 /** Constructor...
63 */
64 Reference (reference_type * pBody)
65 : m_pBody (pBody)
66 {
67 if (m_pBody)
68 m_pBody->acquire();
69 }
70
71 /** Copy constructor...
72 */
73 Reference (const Reference<reference_type> & handle)
74 : m_pBody (handle.m_pBody)
75 {
76 if (m_pBody)
77 m_pBody->acquire();
78 }
79
80#ifdef LIBO_INTERNAL_ONLY1
81 /** Move constructor...
82 */
83 Reference (Reference<reference_type> && handle) noexcept
84 : m_pBody (handle.m_pBody)
85 {
86 handle.m_pBody = nullptr;
87 }
88#endif
89
90#if defined LIBO_INTERNAL_ONLY1
91 /** Up-casting conversion constructor: Copies interface reference.
92
93 Does not work for up-casts to ambiguous bases.
94
95 @param rRef another reference
96 */
97 template< class derived_type >
98 inline Reference(
99 const Reference< derived_type > & rRef,
100 std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 )
101 : m_pBody (rRef.get())
102 {
103 if (m_pBody)
104 m_pBody->acquire();
105 }
106#endif
107
108 /** Destructor...
109 */
110 ~Reference() COVERITY_NOEXCEPT_FALSE
111 {
112 if (m_pBody)
27
Assuming field 'm_pBody' is non-null
28
Taking true branch
113 m_pBody->release();
29
Calling 'VclReferenceBase::release'
33
Returning; memory was released
114 }
115
116 /** Set...
117 Similar to assignment.
118 */
119 Reference<reference_type> &
120 SAL_CALL set (reference_type * pBody)
121 {
122 if (pBody)
123 pBody->acquire();
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld)
127 pOld->release();
128 return *this;
129 }
130
131 /** Assignment.
132 Unbinds this instance from its body (if bound) and
133 bind it to the body represented by the handle.
134 */
135 Reference<reference_type> &
136 SAL_CALL operator= (const Reference<reference_type> & handle)
137 {
138 return set( handle.m_pBody );
139 }
140
141#ifdef LIBO_INTERNAL_ONLY1
142 /** Assignment.
143 * Unbinds this instance from its body (if bound),
144 * bind it to the body represented by the handle, and
145 * set the body represented by the handle to nullptr.
146 */
147 Reference<reference_type> &
148 operator= (Reference<reference_type> && handle)
149 {
150 // self-movement guts ourself
151 if (m_pBody)
152 m_pBody->release();
153 m_pBody = handle.m_pBody;
154 handle.m_pBody = nullptr;
155 return *this;
156 }
157#endif
158
159 /** Assignment...
160 */
161 Reference<reference_type> &
162 SAL_CALL operator= (reference_type * pBody)
163 {
164 return set( pBody );
165 }
166
167 /** Unbind the body from this handle.
168 Note that for a handle representing a large body,
169 "handle.clear().set(new body());" _might_
170 perform a little bit better than "handle.set(new body());",
171 since in the second case two large objects exist in memory
172 (the old body and the new body).
173 */
174 Reference<reference_type> & SAL_CALL clear()
175 {
176 if (m_pBody)
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
181 }
182 return *this;
183 }
184
185
186 /** Get the body. Can be used instead of operator->().
187 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
188 are the same.
189 */
190 reference_type * SAL_CALL get() const
191 {
192 return m_pBody;
193 }
194
195
196 /** Probably most common used: handle->someBodyOp().
197 */
198 reference_type * SAL_CALL operator->() const
199 {
200 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 200, __extension__ __PRETTY_FUNCTION__))
;
201 return m_pBody;
202 }
203
204
205 /** Allows (*handle).someBodyOp().
206 */
207 reference_type & SAL_CALL operator*() const
208 {
209 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 209, __extension__ __PRETTY_FUNCTION__))
;
210 return *m_pBody;
211 }
212
213
214 /** Returns True if the handle does point to a valid body.
215 */
216 bool SAL_CALL is() const
217 {
218 return (m_pBody != NULL__null);
219 }
220
221#if defined LIBO_INTERNAL_ONLY1
222 /** Returns True if the handle does point to a valid body.
223 */
224 explicit operator bool() const
225 {
226 return is();
227 }
228#endif
229
230 /** Returns True if this points to pBody.
231 */
232 bool SAL_CALL operator== (const reference_type * pBody) const
233 {
234 return (m_pBody == pBody);
235 }
236
237
238 /** Returns True if handle points to the same body.
239 */
240 bool
241 SAL_CALL operator== (const Reference<reference_type> & handle) const
242 {
243 return (m_pBody == handle.m_pBody);
244 }
245
246
247 /** Needed to place References into STL collection.
248 */
249 bool
250 SAL_CALL operator!= (const Reference<reference_type> & handle) const
251 {
252 return (m_pBody != handle.m_pBody);
253 }
254
255
256 /** Needed to place References into STL collection.
257 */
258 bool
259 SAL_CALL operator< (const Reference<reference_type> & handle) const
260 {
261 return (m_pBody < handle.m_pBody);
262 }
263
264
265 /** Needed to place References into STL collection.
266 */
267 bool
268 SAL_CALL operator> (const Reference<reference_type> & handle) const
269 {
270 return (m_pBody > handle.m_pBody);
271 }
272};
273
274} // namespace rtl
275
276#if defined LIBO_INTERNAL_ONLY1
277namespace std
278{
279
280/// @cond INTERNAL
281/**
282 Make rtl::Reference hashable by default for use in STL containers.
283
284 @since LibreOffice 6.3
285*/
286template<typename T>
287struct hash<::rtl::Reference<T>>
288{
289 std::size_t operator()(::rtl::Reference<T> const & s) const
290 { return std::size_t(s.get()); }
291};
292/// @endcond
293
294}
295
296#endif
297
298#endif /* ! INCLUDED_RTL_REF_HXX */
299
300/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclreferencebase.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19#ifndef INCLUDED_VCL_Reference_HXX
20#define INCLUDED_VCL_Reference_HXX
21
22#include <vcl/dllapi.h>
23#include <osl/interlck.h>
24
25class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase
26{
27 mutable oslInterlockedCount mnRefCnt;
28
29 template<typename T> friend class VclPtr;
30
31public:
32 void acquire() const
33 {
34 osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1);
35 }
36
37 void release() const
38 {
39 if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0)
30
Assuming the condition is true
31
Taking true branch
40 delete this;
32
Memory is released
41 }
42#ifdef DBG_UTIL
43#ifndef _WIN32
44 sal_Int32 getRefCount() const { return mnRefCnt; }
45#endif
46#endif
47
48
49private:
50 VclReferenceBase(const VclReferenceBase&) = delete;
51 VclReferenceBase& operator=(const VclReferenceBase&) = delete;
52
53 bool mbDisposed : 1;
54
55protected:
56 VclReferenceBase();
57protected:
58 virtual ~VclReferenceBase();
59
60protected:
61 virtual void dispose();
62
63public:
64 void disposeOnce();
65 bool isDisposed() const { return mbDisposed; }
66
67};
68#endif