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 <config_feature_desktop.h>
21 #include <comphelper/lok.hxx>
22 #include <comphelper/processfactory.hxx>
23
24 #include <sfx2/docfile.hxx>
25 #include <sfx2/objface.hxx>
26 #include <sfx2/objsh.hxx>
27 #include <sfx2/app.hxx>
28 #include <workwin.hxx>
29 #include <sfx2/viewfrm.hxx>
30 #include <sfx2/module.hxx>
31 #include <sfx2/dispatch.hxx>
32 #include <sfx2/dockwin.hxx>
33 #include <sfx2/viewsh.hxx>
34 #include <splitwin.hxx>
35 #include <childwinimpl.hxx>
36 #include <sfx2/msgpool.hxx>
37 #include <sfx2/request.hxx>
38 #include <sfx2/sfxsids.hrc>
39 #include <sfx2/toolbarids.hxx>
40 #include <vcl/taskpanelist.hxx>
41 #include <vcl/toolbox.hxx>
42 #include <vcl/svapp.hxx>
43 #include <tools/diagnose_ex.h>
44 #include <svl/itempool.hxx>
45 #include <svl/itemiter.hxx>
46 #include <svl/whiter.hxx>
47 #include <svl/intitem.hxx>
48 #include <svl/eitem.hxx>
49 #include <tools/svborder.hxx>
50 #include <unotools/moduleoptions.hxx>
51 #include <com/sun/star/ui/XUIElement.hpp>
52 #include <com/sun/star/frame/LayoutManagerEvents.hpp>
53 #include <com/sun/star/frame/ModuleManager.hpp>
54 #include <com/sun/star/frame/XLayoutManager.hpp>
55 #include <com/sun/star/frame/XLayoutManagerEventBroadcaster.hpp>
56 #include <com/sun/star/beans/XPropertySet.hpp>
57 #include <com/sun/star/awt/XWindow.hpp>
58 #include <com/sun/star/lang/DisposedException.hpp>
59 #include <type_traits>
60 #include <unordered_map>
61 #include <sfx2/notebookbar/SfxNotebookBar.hxx>
62
63 using namespace ::com::sun::star;
64 using namespace ::com::sun::star::uno;
65
66 struct ResIdToResName
67 {
68 ToolbarId const eId;
69 const char* pName;
70 };
71
72 static const ResIdToResName pToolBarResToName[] =
73 {
74 { ToolbarId::FullScreenToolbox, "fullscreenbar" },
75 { ToolbarId::EnvToolbox, "standardbar", },
76 { ToolbarId::SvxTbx_Form_Navigation, "formsnavigationbar" },
77 { ToolbarId::SvxTbx_Form_Filter, "formsfilterbar" },
78 { ToolbarId::SvxTbx_Text_Control_Attributes, "formtextobjectbar" },
79 { ToolbarId::SvxTbx_Controls, "formcontrols" },
80 { ToolbarId::SvxTbx_FormDesign, "formdesign" },
81 { ToolbarId::Math_Toolbox, "toolbar" }, //math
82 { ToolbarId::Text_Toolbox_Sc, "textobjectbar" }, //calc
83 { ToolbarId::Draw_Objectbar, "drawobjectbar" },
84 { ToolbarId::Graphic_Objectbar, "graphicobjectbar" },
85 { ToolbarId::Objectbar_Format, "formatobjectbar" },
86 { ToolbarId::Objectbar_Preview, "previewbar" },
87 { ToolbarId::Objectbar_Tools, "toolbar" }, //calc
88 { ToolbarId::Bezier_Toolbox_Sd, "bezierobjectbar" }, //draw/impress
89 { ToolbarId::Gluepoints_Toolbox, "gluepointsobjectbar" },
90 { ToolbarId::Draw_Graf_Toolbox, "graphicobjectbar" },
91 { ToolbarId::Draw_Obj_Toolbox, "drawingobjectbar" }, //impress
92 { ToolbarId::Draw_Text_Toolbox_Sd, "textobjectbar" }, //impress
93 { ToolbarId::Draw_Toolbox_Sd, "toolbar" }, //impress
94 { ToolbarId::Draw_Options_Toolbox, "optionsbar" },
95 { ToolbarId::Draw_CommonTask_Toolbox, "commontaskbar" },
96 { ToolbarId::Graphic_Obj_Toolbox, "drawingobjectbar" }, //draw
97 { ToolbarId::Outline_Toolbox, "outlinetoolbar" }, //impress
98 { ToolbarId::Slide_Toolbox, "slideviewtoolbar" },
99 { ToolbarId::Slide_Obj_Toolbox, "slideviewobjectbar" },
100 { ToolbarId::Bezier_Toolbox_Sw, "bezierobjectbar" },
101 { ToolbarId::Draw_Toolbox_Sw, "drawingobjectbar" },
102 { ToolbarId::Draw_Text_Toolbox_Sw, "drawtextobjectbar" },
103 { ToolbarId::Frame_Toolbox, "frameobjectbar" },
104 { ToolbarId::Grafik_Toolbox, "graphicobjectbar" },
105 { ToolbarId::Num_Toolbox, "numobjectbar" },
106 { ToolbarId::Ole_Toolbox, "oleobjectbar" },
107 { ToolbarId::Table_Toolbox, "tableobjectbar" },
108 { ToolbarId::Text_Toolbox_Sw, "textobjectbar" },
109 { ToolbarId::PView_Toolbox, "previewobjectbar" }, //writer
110 { ToolbarId::Webtools_Toolbox, "toolbar" }, //web
111 { ToolbarId::Webtext_Toolbox, "textobjectbar" },
112 { ToolbarId::Tools_Toolbox, "toolbar" }, //writer
113 { ToolbarId::Webframe_Toolbox, "frameobjectbar" }, //web
114 { ToolbarId::Webgraphic_Toolbox, "graphicobjectbar" },
115 { ToolbarId::Webole_Toolbox, "oleobjectbar" },
116 { ToolbarId::Basicide_Objectbar, "macrobar" },
117 { ToolbarId::Svx_Fontwork_Bar, "fontworkobjectbar" }, //global
118 { ToolbarId::Svx_Extrusion_Bar, "extrusionobjectbar" },
119 { ToolbarId::FormLayer_Toolbox, "formsobjectbar" },
120 { ToolbarId::Module_Toolbox, "viewerbar" }, //writer (plugin)
121 { ToolbarId::Objectbar_App, "viewerbar" }, //calc (plugin)
122 { ToolbarId::Draw_Viewer_Toolbox, "viewerbar" }, //impress(plugin)
123 { ToolbarId::Draw_Media_Toolbox, "mediaobjectbar" }, //draw/impress
124 { ToolbarId::Media_Objectbar, "mediaobjectbar" }, //calc
125 { ToolbarId::Media_Toolbox, "mediaobjectbar" }, //writer
126 { ToolbarId::None, "" }
127 };
128
129 // Sort the Children according their alignment
130 // The order corresponds to the enum SfxChildAlignment (->CHILDWIN.HXX).
131
132 static constexpr OUStringLiteral g_aLayoutManagerPropName = "LayoutManager";
133
134 // Help to make changes to the alignment compatible!
LayoutManagerListener(SfxWorkWindow * pWrkWin)135 LayoutManagerListener::LayoutManagerListener(
136 SfxWorkWindow* pWrkWin ) :
137 m_bHasFrame( false ),
138 m_pWrkWin( pWrkWin )
139 {
140 }
141
~LayoutManagerListener()142 LayoutManagerListener::~LayoutManagerListener()
143 {
144 }
145
setFrame(const css::uno::Reference<css::frame::XFrame> & xFrame)146 void LayoutManagerListener::setFrame( const css::uno::Reference< css::frame::XFrame >& xFrame )
147 {
148 SolarMutexGuard aGuard;
149 if ( !m_pWrkWin || m_bHasFrame )
150 return;
151
152 m_xFrame = xFrame;
153 m_bHasFrame = true;
154
155 if ( !xFrame.is() )
156 return;
157
158 css::uno::Reference< css::beans::XPropertySet > xPropSet( xFrame, UNO_QUERY );
159 css::uno::Reference< css::frame::XLayoutManagerEventBroadcaster > xLayoutManager;
160 if ( !xPropSet.is() )
161 return;
162
163 try
164 {
165 Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
166 aValue >>= xLayoutManager;
167
168 if ( xLayoutManager.is() )
169 xLayoutManager->addLayoutManagerEventListener(
170 css::uno::Reference< css::frame::XLayoutManagerListener >(
171 static_cast< OWeakObject* >( this ), css::uno::UNO_QUERY ));
172
173 xPropSet.set( xLayoutManager, UNO_QUERY );
174 if ( xPropSet.is() )
175 {
176 aValue = xPropSet->getPropertyValue( "LockCount" );
177 aValue >>= m_pWrkWin->m_nLock;
178 }
179 }
180 catch ( css::lang::DisposedException& )
181 {
182 }
183 catch ( const css::uno::RuntimeException& )
184 {
185 throw;
186 }
187 catch ( css::uno::Exception& )
188 {
189 }
190 }
191
192
193 // XComponent
194
addEventListener(const css::uno::Reference<css::lang::XEventListener> &)195 void SAL_CALL LayoutManagerListener::addEventListener(
196 const css::uno::Reference< css::lang::XEventListener >& )
197 {
198 // do nothing, only internal class
199 }
200
removeEventListener(const css::uno::Reference<css::lang::XEventListener> &)201 void SAL_CALL LayoutManagerListener::removeEventListener(
202 const css::uno::Reference< css::lang::XEventListener >& )
203 {
204 // do nothing, only internal class
205 }
206
dispose()207 void SAL_CALL LayoutManagerListener::dispose()
208 {
209 SolarMutexGuard aGuard;
210
211 // reset member
212 m_pWrkWin = nullptr;
213
214 css::uno::Reference< css::frame::XFrame > xFrame( m_xFrame.get(), css::uno::UNO_QUERY );
215 if ( !xFrame.is() )
216 return;
217
218 m_xFrame.clear();
219 m_bHasFrame = false;
220
221 css::uno::Reference< css::beans::XPropertySet > xPropSet( xFrame, css::uno::UNO_QUERY );
222 css::uno::Reference< css::frame::XLayoutManagerEventBroadcaster > xLayoutManager;
223 if ( !xPropSet.is() )
224 return;
225
226 try
227 {
228 css::uno::Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
229 aValue >>= xLayoutManager;
230
231 // remove as listener from layout manager
232 if ( xLayoutManager.is() )
233 xLayoutManager->removeLayoutManagerEventListener(
234 css::uno::Reference< css::frame::XLayoutManagerListener >(
235 static_cast< OWeakObject* >( this ), css::uno::UNO_QUERY ));
236 }
237 catch ( css::lang::DisposedException& )
238 {
239 }
240 catch ( const css::uno::RuntimeException& )
241 {
242 throw;
243 }
244 catch ( css::uno::Exception& )
245 {
246 }
247 }
248
249
250 // XEventListener
251
disposing(const css::lang::EventObject &)252 void SAL_CALL LayoutManagerListener::disposing(
253 const css::lang::EventObject& )
254 {
255 SolarMutexGuard aGuard;
256 m_pWrkWin = nullptr;
257 m_bHasFrame = false;
258 m_xFrame.clear();
259 }
260
261
262 // XLayoutManagerEventListener
263
layoutEvent(const css::lang::EventObject &,::sal_Int16 eLayoutEvent,const css::uno::Any &)264 void SAL_CALL LayoutManagerListener::layoutEvent(
265 const css::lang::EventObject&,
266 ::sal_Int16 eLayoutEvent,
267 const css::uno::Any& )
268 {
269 SolarMutexGuard aGuard;
270 if ( !m_pWrkWin )
271 return;
272
273 if ( eLayoutEvent == css::frame::LayoutManagerEvents::VISIBLE )
274 {
275 m_pWrkWin->MakeVisible_Impl( true );
276 m_pWrkWin->ShowChildren_Impl();
277 m_pWrkWin->ArrangeChildren_Impl();
278 }
279 else if ( eLayoutEvent == css::frame::LayoutManagerEvents::INVISIBLE )
280 {
281 m_pWrkWin->MakeVisible_Impl( false );
282 m_pWrkWin->HideChildren_Impl();
283 m_pWrkWin->ArrangeChildren_Impl();
284 }
285 else if ( eLayoutEvent == css::frame::LayoutManagerEvents::LOCK )
286 {
287 m_pWrkWin->Lock_Impl( true );
288 }
289 else if ( eLayoutEvent == css::frame::LayoutManagerEvents::UNLOCK )
290 {
291 m_pWrkWin->Lock_Impl( false );
292 }
293 }
294
295 namespace
296 {
297 struct ToolbarIdHash
298 {
operator ()__anon3d2b2e450111::ToolbarIdHash299 size_t operator()(ToolbarId t) const
300 {
301 typedef std::underlying_type<ToolbarId>::type underlying_type;
302 return std::hash<underlying_type>()(static_cast<underlying_type>(t));
303 }
304 };
305
306 class FilledToolBarResIdToResourceURLMap
307 {
308 private:
309 typedef std::unordered_map<ToolbarId, OUString, ToolbarIdHash> ToolBarResIdToResourceURLMap;
310 ToolBarResIdToResourceURLMap m_aResIdToResourceURLMap;
311 public:
FilledToolBarResIdToResourceURLMap()312 FilledToolBarResIdToResourceURLMap()
313 {
314 sal_Int32 nIndex( 0 );
315 while (pToolBarResToName[nIndex].eId != ToolbarId::None)
316 {
317 OUString aResourceURL( OUString::createFromAscii( pToolBarResToName[nIndex].pName ));
318 m_aResIdToResourceURLMap.emplace(pToolBarResToName[nIndex].eId, aResourceURL);
319 ++nIndex;
320 }
321 }
322
findURL(ToolbarId eId) const323 OUString findURL(ToolbarId eId) const
324 {
325 ToolBarResIdToResourceURLMap::const_iterator aIter = m_aResIdToResourceURLMap.find(eId);
326 if ( aIter != m_aResIdToResourceURLMap.end() )
327 return aIter->second;
328 return OUString();
329 }
330 };
331
332 class theFilledToolBarResIdToResourceURLMap
333 : public rtl::Static<FilledToolBarResIdToResourceURLMap,
334 theFilledToolBarResIdToResourceURLMap>
335 {
336 };
337 }
338
GetResourceURLFromToolbarId(ToolbarId eId)339 static OUString GetResourceURLFromToolbarId(ToolbarId eId)
340 {
341 return theFilledToolBarResIdToResourceURLMap::get().findURL(eId);
342 }
343
TbxMatch(sal_uInt16 nPos)344 static sal_uInt16 TbxMatch( sal_uInt16 nPos )
345 {
346 switch ( nPos )
347 {
348 case SFX_OBJECTBAR_APPLICATION :
349 return 0;
350 case SFX_OBJECTBAR_OPTIONS:
351 return 1;
352 case SFX_OBJECTBAR_MACRO:
353 return 2;
354 case SFX_OBJECTBAR_OBJECT:
355 return 3;
356 case SFX_OBJECTBAR_TOOLS:
357 return 4;
358 case SFX_OBJECTBAR_FULLSCREEN:
359 case SFX_OBJECTBAR_COMMONTASK:
360 case SFX_OBJECTBAR_RECORDING:
361 return nPos+1;
362 default:
363 return nPos;
364 }
365 }
366
ChildAlignValue(SfxChildAlignment eAlign)367 static sal_uInt16 ChildAlignValue(SfxChildAlignment eAlign)
368 {
369 sal_uInt16 ret = 17;
370
371 switch (eAlign)
372 {
373 case SfxChildAlignment::HIGHESTTOP:
374 ret = 1;
375 break;
376 case SfxChildAlignment::LOWESTBOTTOM:
377 ret = 2;
378 break;
379 case SfxChildAlignment::FIRSTLEFT:
380 ret = 3;
381 break;
382 case SfxChildAlignment::LASTRIGHT:
383 ret = 4;
384 break;
385 case SfxChildAlignment::LEFT:
386 ret = 5;
387 break;
388 case SfxChildAlignment::RIGHT:
389 ret = 6;
390 break;
391 case SfxChildAlignment::FIRSTRIGHT:
392 ret = 7;
393 break;
394 case SfxChildAlignment::LASTLEFT:
395 ret = 8;
396 break;
397 case SfxChildAlignment::TOP:
398 ret = 9;
399 break;
400 case SfxChildAlignment::BOTTOM:
401 ret = 10;
402 break;
403 case SfxChildAlignment::TOOLBOXTOP:
404 ret = 11;
405 break;
406 case SfxChildAlignment::TOOLBOXBOTTOM:
407 ret = 12;
408 break;
409 case SfxChildAlignment::LOWESTTOP:
410 ret = 13;
411 break;
412 case SfxChildAlignment::HIGHESTBOTTOM:
413 ret = 14;
414 break;
415 case SfxChildAlignment::TOOLBOXLEFT:
416 ret = 15;
417 break;
418 case SfxChildAlignment::TOOLBOXRIGHT:
419 ret = 16;
420 break;
421 case SfxChildAlignment::NOALIGNMENT:
422 break; // -Wall not handled...
423 }
424
425 return ret;
426 }
427
Sort_Impl()428 void SfxWorkWindow::Sort_Impl()
429 {
430 aSortedList.clear();
431 for (size_t i = 0; i < aChildren.size(); ++i)
432 {
433 SfxChild_Impl *pCli = aChildren[i].get();
434 if (pCli)
435 {
436 decltype(aSortedList)::size_type k;
437 for (k=0; k<aSortedList.size(); k++)
438 if (ChildAlignValue( aChildren[aSortedList[k]]->eAlign ) >
439 ChildAlignValue(pCli->eAlign))
440 break;
441 aSortedList.insert( aSortedList.begin() + k, i );
442 }
443 }
444
445 bSorted = true;
446 }
447
448 static constexpr OUStringLiteral g_aStatusBarResName( "private:resource/statusbar/statusbar" );
449 static constexpr OUStringLiteral g_aTbxTypeName( "private:resource/toolbar/" );
450 static constexpr OUStringLiteral g_aProgressBarResName( "private:resource/progressbar/progressbar" );
451
452 // constructor for workwin of a Frame
453
SfxWorkWindow(vcl::Window * pWin,SfxFrame * pFrm,SfxFrame * pMaster)454 SfxWorkWindow::SfxWorkWindow( vcl::Window *pWin, SfxFrame *pFrm, SfxFrame* pMaster ) :
455 pBindings(&pFrm->GetCurrentViewFrame()->GetBindings()),
456 pWorkWin (pWin),
457 pActiveChild( nullptr ),
458 nUpdateMode(SfxVisibilityFlags::Standard),
459 nChildren( 0 ),
460 nOrigMode( SfxVisibilityFlags::Invisible ),
461 bSorted( true ),
462 bDockingAllowed(true),
463 bInternalDockingAllowed(true),
464 bAllChildrenVisible(true),
465 #if HAVE_FEATURE_DESKTOP
466 bIsFullScreen( false ),
467 bShowStatusBar( true ),
468 #else
469 bIsFullScreen( sal_True ),
470 bShowStatusBar( sal_False ),
471 #endif
472 m_nLock( 0 ),
473 pMasterFrame( pMaster ),
474 pFrame( pFrm )
475 {
476 DBG_ASSERT (pBindings, "No Bindings!");
477
478 pBindings->SetWorkWindow_Impl( this );
479
480 // For the ObjectBars an integral place in the Childlist is reserved,
481 // so that they always come in a defined order.
482 for (int i=0; i<SFX_OBJECTBAR_MAX; ++i)
483 aChildren.push_back( nullptr );
484
485 // create and initialize layout manager listener
486 Reference< css::frame::XFrame > xFrame = GetFrameInterface();
487 LayoutManagerListener* pLayoutManagerListener = new LayoutManagerListener( this );
488 m_xLayoutManagerListener.set( static_cast< cppu::OWeakObject* >( pLayoutManagerListener ),
489 css::uno::UNO_QUERY );
490 pLayoutManagerListener->setFrame( xFrame );
491
492 SfxShell* pConfigShell = pFrm->GetCurrentViewFrame();
493 if ( pConfigShell && pConfigShell->GetObjectShell() )
494 {
495 bShowStatusBar = ( !pConfigShell->GetObjectShell()->IsInPlaceActive() );
496 bDockingAllowed = true;
497 bInternalDockingAllowed = true;
498 }
499
500 // The required split windows (one for each side) can be created
501 for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX; n++ )
502 {
503 // The SplitWindows excludes direct ChildWindows of the WorkWindows
504 // and receives the docked window.
505
506 SfxChildAlignment eAlign =
507 ( n == SFX_SPLITWINDOWS_LEFT ? SfxChildAlignment::LEFT :
508 n == SFX_SPLITWINDOWS_RIGHT ? SfxChildAlignment::RIGHT :
509 n == SFX_SPLITWINDOWS_TOP ? SfxChildAlignment::TOP :
510 SfxChildAlignment::BOTTOM );
511 VclPtr<SfxSplitWindow> pSplitWin = VclPtr<SfxSplitWindow>::Create(pWorkWin, eAlign, this, true );
512 pSplit[n] = pSplitWin;
513 }
514
515 nOrigMode = SfxVisibilityFlags::Standard;
516 nUpdateMode = SfxVisibilityFlags::Standard;
517 }
518
519
520 // Destructor
521
~SfxWorkWindow()522 SfxWorkWindow::~SfxWorkWindow()
523 {
524
525 // Delete SplitWindows
526 for (VclPtr<SfxSplitWindow> & p : pSplit)
527 {
528 if (p->GetWindowCount())
529 ReleaseChild_Impl(*p);
530 p.disposeAndClear();
531 }
532
533 // Delete help structure for Child-Windows
534 DBG_ASSERT( aChildren.empty(), "dangling children" );
535
536 if ( m_xLayoutManagerListener.is() )
537 m_xLayoutManagerListener->dispose();
538 }
539
Lock_Impl(bool bLock)540 void SfxWorkWindow::Lock_Impl( bool bLock )
541 {
542 if ( bLock )
543 m_nLock++;
544 else
545 --m_nLock;
546 if ( m_nLock<0 )
547 {
548 OSL_FAIL("Lock count underflow!");
549 assert(m_nLock >= 0);
550 m_nLock = 0;
551 }
552
553 if ( !m_nLock )
554 ArrangeChildren_Impl();
555 }
556
557
558 // Helper method to release the child lists. Should the destructor not be
559 // called after this, instead work continues, then space for the object bars
560 // and split windows has to be reserved in the same way as in the constructor
561 // of SfxWorkWindow.
562
DeleteControllers_Impl()563 void SfxWorkWindow::DeleteControllers_Impl()
564 {
565
566 // Lock SplitWindows (which means suppressing the Resize-Reaction of the
567 // DockingWindows)
568 for (size_t n=0; n<SFX_SPLITWINDOWS_MAX; n++ )
569 {
570 VclPtr<SfxSplitWindow> const &p = pSplit[n];
571 if (p->GetWindowCount())
572 p->Lock();
573 }
574
575 // Delete Child-Windows
576 while(!aChildWins.empty())
577 {
578 std::unique_ptr<SfxChildWin_Impl> pCW = std::move(*aChildWins.begin());
579 aChildWins.erase(aChildWins.begin());
580 SfxChildWindow *pChild = pCW->pWin;
581 if (pChild)
582 {
583 if (comphelper::LibreOfficeKit::isActive())
584 {
585 vcl::Window* pWindow = pChild->GetWindow();
586 if (pWindow)
587 {
588 pWindow->ReleaseLOKNotifier();
589 }
590 }
591 pChild->Hide();
592
593 // If the child window is a direct child window and not in a
594 // SplitWindow, cancel it at the workwindow.
595 // After TH a cancellation on the SplitWindow is not necessary
596 // since this window is also destroyed (see below).
597 if (pCW->pCli)
598 {
599 if (pChild->GetController())
600 ReleaseChild_Impl(*pChild->GetController());
601 else
602 ReleaseChild_Impl(*pChild->GetWindow());
603 }
604
605 pCW->pWin = nullptr;
606 pWorkWin->GetSystemWindow()->GetTaskPaneList()->RemoveWindow( pChild->GetWindow() );
607 pChild->Destroy();
608 }
609
610 // ATTENTION: The array itself is cleared after this loop!!
611 // Therefore we have to set every array entry to zero as it could be
612 // accessed by calling pChild->Destroy().
613 // Window::NotifyAllChildren() calls SfxWorkWindow::DataChanged_Impl for
614 // 8-bit displays (WM_QUERYPALETTECHANGED message due to focus change)!!
615 }
616
617 Reference< css::frame::XFrame > xFrame = GetFrameInterface();
618 Reference< css::beans::XPropertySet > xPropSet( xFrame, UNO_QUERY );
619 Reference< css::frame::XLayoutManager > xLayoutManager;
620 if ( xPropSet.is() )
621 {
622 try
623 {
624 Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
625 aValue >>= xLayoutManager;
626 }
627 catch ( Exception& )
628 {
629 }
630 }
631
632 if ( xLayoutManager.is() )
633 {
634 xLayoutManager->reset();
635
636 // Delete StatusBar
637 ResetStatusBar_Impl();
638
639 // Delete ObjectBars (this is done last, so that aChildren does not
640 // receive dead Pointers)
641 for (SfxObjectBar_Impl & i : aObjBarList)
642 {
643 // Not every position must be occupied
644 ToolbarId eId = i.eId;
645 if (eId != ToolbarId::None)
646 i.eId = ToolbarId::None;
647 }
648 }
649
650 // ObjectBars are all released at once, since they occupy a
651 // fixed contiguous area in the array pChild
652 aChildren.clear();
653 bSorted = false;
654
655 nChildren = 0;
656 }
657
658
659 // for placing the child window.
660
ArrangeChildren_Impl(bool bForce)661 void SfxWorkWindow::ArrangeChildren_Impl( bool bForce )
662 {
663 if ( pFrame->IsClosing_Impl() || ( m_nLock && !bForce ))
664 return;
665
666 SfxInPlaceClient *pClient = nullptr;
667 SfxViewFrame *pF = pFrame->GetCurrentViewFrame();
668 if ( pF && pF->GetViewShell() )
669 pClient = pF->GetViewShell()->GetIPClient();
670
671 if ( pClient )
672 return;
673
674 aClientArea = GetTopRect_Impl();
675 if ( aClientArea.IsEmpty() )
676 return;
677
678 SvBorder aBorder;
679 if ( nChildren && IsVisible_Impl() )
680 aBorder = Arrange_Impl();
681 // If the current application document contains an IPClient, then the
682 // object through SetTopToolFramePixel has to be assigned the available
683 // space. The object will then point to its UITools and sets the app border
684 // (-> SfxInPlaceEnv_Impl:: ArrangeChildren_Impl ()). Otherwise the
685 // app border is set here directly to possibly overwrite the Border that
686 // was set by an object from another document. The object does not set
687 // the SetAppBorder when it removes its UI tools so that no-dithering
688 // ObjectBar arises.
689 // (->SfxInPlaceEnv_Impl::ArrangeChildren_Impl())
690
691 pMasterFrame->SetToolSpaceBorderPixel_Impl( aBorder );
692
693 ArrangeAutoHideWindows( nullptr );
694 }
695
FlushPendingChildSizes()696 void SfxWorkWindow::FlushPendingChildSizes()
697 {
698 // tdf#116865, if any windows are being resized, i.e. their
699 // resize timer is active, then calling GetSizePixel on
700 // them forces the timer to fire and sets the final
701 // size to which they are getting resized towards.
702 for (size_t i = 0; i < aChildren.size(); ++i)
703 {
704 SfxChild_Impl *pCli = aChildren[i].get();
705 if (!pCli || !pCli->pWin)
706 continue;
707 (void)pCli->pWin->GetSizePixel();
708 }
709 }
710
Arrange_Impl()711 SvBorder SfxWorkWindow::Arrange_Impl()
712
713 /* [Description]
714
715 This method organizes all visible child windows so that the docked window
716 sorted in order from the outside to the inside are placed after one
717 another. If a visible window does not fit anymore into the free
718 ClientArea, it is set to "not visible".
719 */
720 {
721 //tdf#116865 trigger pending sizing timers now so we arrange
722 //with the final size of the client area.
723 //
724 //Otherwise calling GetSizePixel in the following loop will trigger the
725 //timers, causing reentry into Arrange_Impl again where the inner
726 //Arrange_Impl arranges with the final size, and then returns to this outer
727 //Arrange_Impl which would rearrange with the old client area size
728 FlushPendingChildSizes();
729 aClientArea = GetTopRect_Impl();
730 aUpperClientArea = aClientArea;
731
732 SvBorder aBorder;
733 if ( !nChildren )
734 return aBorder;
735
736 if (!bSorted)
737 Sort_Impl();
738
739 Point aPos;
740 Size aSize;
741 tools::Rectangle aTmp( aClientArea );
742
743 for (sal_uInt16 n : aSortedList)
744 {
745 SfxChild_Impl* pCli = aChildren[n].get();
746 if ( !pCli->pWin )
747 continue;
748
749 // First, we assume that there is room for the window.
750 pCli->nVisible |= SfxChildVisibility::FITS_IN;
751
752 // Skip invisible windows
753 if (pCli->nVisible != SfxChildVisibility::VISIBLE)
754 continue;
755
756 if ( pCli->bResize )
757 aSize = pCli->aSize;
758 else
759 aSize = pCli->pWin->GetSizePixel();
760
761 SvBorder aTemp = aBorder;
762 bool bAllowHiding = true;
763 switch ( pCli->eAlign )
764 {
765 case SfxChildAlignment::HIGHESTTOP:
766 case SfxChildAlignment::TOP:
767 case SfxChildAlignment::TOOLBOXTOP:
768 case SfxChildAlignment::LOWESTTOP:
769 aSize.setWidth( aTmp.GetWidth() );
770 if ( pCli->pWin->GetType() == WindowType::SPLITWINDOW )
771 aSize = static_cast<SplitWindow *>(pCli->pWin.get())->CalcLayoutSizePixel( aSize );
772 bAllowHiding = false;
773 aBorder.Top() += aSize.Height();
774 aPos = aTmp.TopLeft();
775 aTmp.AdjustTop(aSize.Height() );
776 if ( pCli->eAlign == SfxChildAlignment::HIGHESTTOP )
777 aUpperClientArea.AdjustTop(aSize.Height() );
778 break;
779
780 case SfxChildAlignment::LOWESTBOTTOM:
781 case SfxChildAlignment::BOTTOM:
782 case SfxChildAlignment::TOOLBOXBOTTOM:
783 case SfxChildAlignment::HIGHESTBOTTOM:
784 aSize.setWidth( aTmp.GetWidth() );
785 if ( pCli->pWin->GetType() == WindowType::SPLITWINDOW )
786 aSize = static_cast<SplitWindow *>(pCli->pWin.get())->CalcLayoutSizePixel( aSize );
787 aBorder.Bottom() += aSize.Height();
788 aPos = aTmp.BottomLeft();
789 aPos.AdjustY( -(aSize.Height()-1) );
790 aTmp.AdjustBottom( -(aSize.Height()) );
791 if ( pCli->eAlign == SfxChildAlignment::LOWESTBOTTOM )
792 aUpperClientArea.AdjustBottom( -(aSize.Height()) );
793 break;
794
795 case SfxChildAlignment::FIRSTLEFT:
796 case SfxChildAlignment::LEFT:
797 case SfxChildAlignment::LASTLEFT:
798 case SfxChildAlignment::TOOLBOXLEFT:
799 aSize.setHeight( aTmp.GetHeight() );
800 if ( pCli->pWin->GetType() == WindowType::SPLITWINDOW )
801 aSize = static_cast<SplitWindow *>(pCli->pWin.get())->CalcLayoutSizePixel( aSize );
802 bAllowHiding = false;
803 aBorder.Left() += aSize.Width();
804 aPos = aTmp.TopLeft();
805 aTmp.AdjustLeft(aSize.Width() );
806 if ( pCli->eAlign != SfxChildAlignment::TOOLBOXLEFT )
807 aUpperClientArea.AdjustLeft(aSize.Width() );
808 break;
809
810 case SfxChildAlignment::FIRSTRIGHT:
811 case SfxChildAlignment::RIGHT:
812 case SfxChildAlignment::LASTRIGHT:
813 case SfxChildAlignment::TOOLBOXRIGHT:
814 aSize.setHeight( aTmp.GetHeight() );
815 if ( pCli->pWin->GetType() == WindowType::SPLITWINDOW )
816 aSize = static_cast<SplitWindow *>(pCli->pWin.get())->CalcLayoutSizePixel( aSize );
817 aBorder.Right() += aSize.Width();
818 aPos = aTmp.TopRight();
819 aPos.AdjustX( -(aSize.Width()-1) );
820 aTmp.AdjustRight( -(aSize.Width()) );
821 if ( pCli->eAlign != SfxChildAlignment::TOOLBOXRIGHT )
822 aUpperClientArea.AdjustRight( -(aSize.Width()) );
823 break;
824
825 default:
826 pCli->aSize = pCli->pWin->GetSizePixel();
827 pCli->bResize = false;
828 continue;
829 }
830
831 pCli->pWin->SetPosSizePixel( aPos, aSize );
832 pCli->bResize = false;
833 pCli->aSize = aSize;
834 if( bAllowHiding && !RequestTopToolSpacePixel_Impl( aBorder ) )
835 {
836 pCli->nVisible ^= SfxChildVisibility::FITS_IN;
837 aBorder = aTemp;
838 }
839 }
840
841 if ( aClientArea.GetWidth() >= aBorder.Left() + aBorder.Right() )
842 {
843 aClientArea.AdjustLeft(aBorder.Left() );
844 aClientArea.AdjustRight( -(aBorder.Right()) );
845 }
846 else
847 {
848 aBorder.Left() = aClientArea.Left();
849 aBorder.Right() = aClientArea.Right();
850 aClientArea.SetRight( aTmp.Left() );
851 aClientArea.SetLeft( aTmp.Left() );
852 }
853
854 if ( aClientArea.GetHeight() >= aBorder.Top() + aBorder.Bottom() )
855 {
856 aClientArea.AdjustTop(aBorder.Top() );
857 aClientArea.AdjustBottom( -(aBorder.Bottom()) );
858 }
859 else
860 {
861 aBorder.Top() = aClientArea.Top();
862 aBorder.Bottom() = aClientArea.Bottom();
863 aClientArea.SetTop(aTmp.Top());
864 aClientArea.SetBottom(aTmp.Top());
865 }
866
867 return IsDockingAllowed() ? aBorder : SvBorder();
868 }
869
PrepareClose_Impl()870 bool SfxWorkWindow::PrepareClose_Impl()
871 {
872 for (const std::unique_ptr<SfxChildWin_Impl> &pCW : aChildWins)
873 {
874 SfxChildWindow *pChild = pCW->pWin;
875 if ( pChild && !pChild->QueryClose() )
876 return false;
877 }
878
879 return true;
880 }
881
RegisterChild_Impl(vcl::Window & rWindow,SfxChildAlignment eAlign)882 SfxChild_Impl* SfxWorkWindow::RegisterChild_Impl( vcl::Window& rWindow,
883 SfxChildAlignment eAlign )
884 {
885 DBG_ASSERT( aChildren.size() < 255, "too many children" );
886 DBG_ASSERT( SfxChildAlignValid(eAlign), "invalid align" );
887 DBG_ASSERT( !FindChild_Impl(&rWindow), "child registered more than once" );
888
889
890 if ( rWindow.GetParent() != pWorkWin )
891 rWindow.SetParent( pWorkWin );
892
893 auto pChild = std::make_unique<SfxChild_Impl>(rWindow, rWindow.GetSizePixel(),
894 eAlign, rWindow.IsVisible());
895
896 aChildren.push_back(std::move(pChild));
897 bSorted = false;
898 nChildren++;
899 return aChildren.back().get();
900 }
901
RegisterChild_Impl(std::shared_ptr<SfxDialogController> & rController,SfxChildAlignment eAlign)902 SfxChild_Impl* SfxWorkWindow::RegisterChild_Impl(std::shared_ptr<SfxDialogController>& rController,
903 SfxChildAlignment eAlign )
904 {
905 DBG_ASSERT( aChildren.size() < 255, "too many children" );
906 DBG_ASSERT( SfxChildAlignValid(eAlign), "invalid align" );
907
908 auto pChild = std::make_unique<SfxChild_Impl>(rController, eAlign);
909
910 aChildren.push_back(std::move(pChild));
911 bSorted = false;
912 nChildren++;
913 return aChildren.back().get();
914 }
915
ReleaseChild_Impl(vcl::Window & rWindow)916 void SfxWorkWindow::ReleaseChild_Impl( vcl::Window& rWindow )
917 {
918
919 SfxChild_Impl *pChild = nullptr;
920 decltype(aChildren)::size_type nPos;
921 for ( nPos = 0; nPos < aChildren.size(); ++nPos )
922 {
923 pChild = aChildren[nPos].get();
924 if ( pChild && pChild->pWin == &rWindow )
925 {
926 bSorted = false;
927 nChildren--;
928 aChildren.erase(aChildren.begin() + nPos);
929 return;
930 }
931 }
932 OSL_FAIL( "releasing unregistered child" );
933 }
934
ReleaseChild_Impl(SfxDialogController & rController)935 void SfxWorkWindow::ReleaseChild_Impl(SfxDialogController& rController)
936 {
937
938 SfxChild_Impl *pChild = nullptr;
939 decltype(aChildren)::size_type nPos;
940 for ( nPos = 0; nPos < aChildren.size(); ++nPos )
941 {
942 pChild = aChildren[nPos].get();
943 if (pChild && pChild->xController.get() == &rController)
944 {
945 bSorted = false;
946 nChildren--;
947 aChildren.erase(aChildren.begin() + nPos);
948 return;
949 }
950 }
951 OSL_FAIL( "releasing unregistered child" );
952 }
953
FindChild_Impl(const vcl::Window * rWindow) const954 SfxChild_Impl* SfxWorkWindow::FindChild_Impl( const vcl::Window* rWindow ) const
955 {
956
957 sal_uInt16 nCount = aChildren.size();
958 for ( sal_uInt16 nPos = 0; nPos < nCount; ++nPos )
959 {
960 SfxChild_Impl *pChild = aChildren[nPos].get();
961 if ( pChild && pChild->pWin == rWindow )
962 return pChild;
963 }
964
965 return nullptr;
966 }
967
968
ShowChildren_Impl()969 void SfxWorkWindow::ShowChildren_Impl()
970 {
971
972 bool bInvisible = ( !IsVisible_Impl() || ( !pWorkWin->IsReallyVisible() && !pWorkWin->IsReallyShown() ));
973
974 for (std::unique_ptr<SfxChild_Impl>& pCli : aChildren)
975 {
976 if (!pCli)
977 continue;
978 SfxChildWin_Impl* pCW = nullptr;
979 if (pCli->pWin || pCli->xController)
980 {
981 // We have to find the SfxChildWin_Impl to retrieve the
982 // SFX_CHILDWIN flags that can influence visibility.
983 for (const std::unique_ptr<SfxChildWin_Impl>& pCWin : aChildWins)
984 {
985 SfxChild_Impl* pChild = pCWin->pCli;
986 if ( pChild == pCli.get() )
987 {
988 pCW = pCWin.get();
989 break;
990 }
991 }
992
993 bool bVisible( !bInvisible );
994 if ( pCW )
995 {
996 // Check flag SFX_CHILDWIN_NEVERHIDE that forces us to show
997 // the child window even in situations where no child window is
998 // visible.
999 SfxChildWindowFlags nFlags = pCW->aInfo.nFlags;
1000 bVisible = !bInvisible || ( nFlags & SfxChildWindowFlags::NEVERHIDE );
1001 }
1002
1003 if ( SfxChildVisibility::VISIBLE == (pCli->nVisible & SfxChildVisibility::VISIBLE) && bVisible )
1004 {
1005 ShowFlags nFlags = pCli->bSetFocus ? ShowFlags::NONE : ShowFlags::NoFocusChange | ShowFlags::NoActivate;
1006 if (pCli->xController)
1007 {
1008 if (!pCli->xController->getDialog()->get_visible())
1009 {
1010 auto xController = pCli->xController;
1011 weld::DialogController::runAsync(xController,
1012 [=](sal_Int32 /*nResult*/){ xController->Close(); });
1013 }
1014 }
1015 else
1016 pCli->pWin->Show(true, nFlags);
1017 pCli->bSetFocus = false;
1018 }
1019 else
1020 {
1021 if (pCli->xController)
1022 {
1023 if (pCli->xController->getDialog()->get_visible())
1024 pCli->xController->response(RET_CLOSE);
1025 }
1026 else
1027 pCli->pWin->Hide();
1028 }
1029 }
1030 }
1031 }
1032
1033
HideChildren_Impl()1034 void SfxWorkWindow::HideChildren_Impl()
1035 {
1036 for ( sal_uInt16 nPos = aChildren.size(); nPos > 0; --nPos )
1037 {
1038 SfxChild_Impl *pChild = aChildren[nPos-1].get();
1039 if (!pChild)
1040 continue;
1041 if (pChild->xController)
1042 pChild->xController->response(RET_CLOSE);
1043 else if (pChild->pWin)
1044 pChild->pWin->Hide();
1045 }
1046 }
1047
ResetObjectBars_Impl()1048 void SfxWorkWindow::ResetObjectBars_Impl()
1049 {
1050 for ( auto & n: aObjBarList )
1051 n.bDestroy = true;
1052
1053 for ( auto & n: aChildWins )
1054 n->nId = 0;
1055 }
1056
SetObjectBar_Impl(sal_uInt16 nPos,SfxVisibilityFlags nFlags,ToolbarId eId)1057 void SfxWorkWindow::SetObjectBar_Impl(sal_uInt16 nPos, SfxVisibilityFlags nFlags, ToolbarId eId)
1058 {
1059 DBG_ASSERT( nPos < SFX_OBJECTBAR_MAX, "object bar position overflow" );
1060
1061 SfxObjectBar_Impl aObjBar;
1062 aObjBar.eId = eId;
1063 aObjBar.nMode = nFlags;
1064
1065 for (SfxObjectBar_Impl & rBar : aObjBarList)
1066 {
1067 if ( rBar.eId == aObjBar.eId )
1068 {
1069 rBar = aObjBar;
1070 return;
1071 }
1072 }
1073
1074 aObjBarList.push_back( aObjBar );
1075 }
1076
IsVisible_Impl(SfxVisibilityFlags nMode) const1077 bool SfxWorkWindow::IsVisible_Impl( SfxVisibilityFlags nMode ) const
1078 {
1079 switch( nUpdateMode )
1080 {
1081 case SfxVisibilityFlags::Standard:
1082 return true;
1083 case SfxVisibilityFlags::Invisible:
1084 return false;
1085 case SfxVisibilityFlags::Client:
1086 case SfxVisibilityFlags::Server:
1087 return bool(nMode & nUpdateMode);
1088 default:
1089 return (nMode & nOrigMode ) ||
1090 nOrigMode == SfxVisibilityFlags::Standard;
1091 }
1092 }
1093
UpdateObjectBars_Impl()1094 void SfxWorkWindow::UpdateObjectBars_Impl()
1095 {
1096 if ( pFrame->IsClosing_Impl() )
1097 return;
1098
1099 UpdateObjectBars_Impl2();
1100
1101 {
1102 ArrangeChildren_Impl( false );
1103
1104 ShowChildren_Impl();
1105 }
1106
1107 ShowChildren_Impl();
1108 }
1109
GetStatusIndicator()1110 Reference< css::task::XStatusIndicator > SfxWorkWindow::GetStatusIndicator()
1111 {
1112 Reference< css::beans::XPropertySet > xPropSet( GetFrameInterface(), UNO_QUERY );
1113 Reference< css::frame::XLayoutManager > xLayoutManager;
1114 Reference< css::task::XStatusIndicator > xStatusIndicator;
1115
1116 if ( xPropSet.is() )
1117 {
1118 Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
1119 aValue >>= xLayoutManager;
1120 if ( xLayoutManager.is() )
1121 {
1122 xLayoutManager->createElement( g_aProgressBarResName );
1123 xLayoutManager->showElement( g_aProgressBarResName );
1124
1125 Reference< css::ui::XUIElement > xProgressBar =
1126 xLayoutManager->getElement( g_aProgressBarResName );
1127 if ( xProgressBar.is() )
1128 {
1129 xStatusIndicator.set( xProgressBar->getRealInterface(), UNO_QUERY );
1130 }
1131 }
1132 }
1133
1134 return xStatusIndicator;
1135 }
1136
1137
IsPluginMode(SfxObjectShell const * pObjShell)1138 bool SfxWorkWindow::IsPluginMode( SfxObjectShell const * pObjShell )
1139 {
1140 if ( pObjShell && pObjShell->GetMedium() )
1141 {
1142 const SfxBoolItem* pViewOnlyItem = SfxItemSet::GetItem<SfxBoolItem>(pObjShell->GetMedium()->GetItemSet(), SID_VIEWONLY, false);
1143 if ( pViewOnlyItem && pViewOnlyItem->GetValue() )
1144 return true;
1145 }
1146
1147 return false;
1148 }
1149
1150
GetFrameInterface()1151 css::uno::Reference< css::frame::XFrame > SfxWorkWindow::GetFrameInterface()
1152 {
1153 css::uno::Reference< css::frame::XFrame > xFrame;
1154
1155 SfxDispatcher* pDispatcher( GetBindings().GetDispatcher() );
1156 if ( pDispatcher )
1157 {
1158 SfxViewFrame* pViewFrame = pDispatcher->GetFrame();
1159 if ( pViewFrame )
1160 xFrame = pViewFrame->GetFrame().GetFrameInterface();
1161 }
1162
1163 return xFrame;
1164 }
1165
1166
UpdateObjectBars_Impl2()1167 void SfxWorkWindow::UpdateObjectBars_Impl2()
1168 {
1169 // Lock SplitWindows (which means suppressing the Resize-Reaction of the
1170 // DockingWindows)
1171 for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX; n++ )
1172 {
1173 VclPtr<SfxSplitWindow> const & p = pSplit[n];
1174 if (p->GetWindowCount())
1175 p->Lock();
1176 }
1177
1178 Reference< css::beans::XPropertySet > xPropSet( GetFrameInterface(), UNO_QUERY );
1179 Reference< css::frame::XLayoutManager > xLayoutManager;
1180
1181 if ( xPropSet.is() )
1182 {
1183 Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
1184 aValue >>= xLayoutManager;
1185 }
1186
1187 if ( !xLayoutManager.is() )
1188 return;
1189
1190 bool bPluginMode( false );
1191 SfxDispatcher* pDispatcher( GetBindings().GetDispatcher() );
1192
1193 if ( pDispatcher )
1194 {
1195 SfxViewFrame* pViewFrame = pDispatcher->GetFrame();
1196 if ( pViewFrame )
1197 bPluginMode = IsPluginMode( pViewFrame->GetObjectShell() );
1198 }
1199
1200 // Iterate over all Toolboxes
1201 xLayoutManager->lock();
1202 for ( auto const & n: aObjBarList )
1203 {
1204 ToolbarId eId = n.eId;
1205 bool bDestroy = n.bDestroy;
1206
1207 // Determine the valid mode for the ToolBox
1208 SfxVisibilityFlags nTbxMode = n.nMode;
1209 bool bFullScreenTbx( nTbxMode & SfxVisibilityFlags::FullScreen );
1210 nTbxMode &= ~SfxVisibilityFlags::FullScreen;
1211 nTbxMode &= ~SfxVisibilityFlags::Viewer;
1212
1213 // Is a ToolBox required in this context ?
1214 bool bModesMatching = (nUpdateMode != SfxVisibilityFlags::Invisible) && ((nTbxMode & nUpdateMode) == nUpdateMode);
1215 if ( bDestroy || sfx2::SfxNotebookBar::IsActive())
1216 {
1217 OUString aTbxId = g_aTbxTypeName + GetResourceURLFromToolbarId(eId);
1218 xLayoutManager->destroyElement( aTbxId );
1219 }
1220 else if ( eId != ToolbarId::None && ( ( bModesMatching && !bIsFullScreen ) ||
1221 ( bIsFullScreen && bFullScreenTbx ) ) )
1222 {
1223 OUString aTbxId = g_aTbxTypeName + GetResourceURLFromToolbarId(eId);
1224 if ( !IsDockingAllowed() && !xLayoutManager->isElementFloating( aTbxId ))
1225 xLayoutManager->destroyElement( aTbxId );
1226 else
1227 {
1228 xLayoutManager->requestElement( aTbxId );
1229 if ( bPluginMode )
1230 xLayoutManager->lockWindow( aTbxId );
1231 }
1232 }
1233 else if ( eId != ToolbarId::None )
1234 {
1235 // Delete the Toolbox at this Position if possible
1236 OUString aTbxId = g_aTbxTypeName + GetResourceURLFromToolbarId(eId);
1237 xLayoutManager->destroyElement( aTbxId );
1238 }
1239 }
1240
1241 UpdateStatusBar_Impl();
1242
1243 // unlocking automatically forces Layout
1244 xLayoutManager->unlock();
1245
1246 UpdateChildWindows_Impl();
1247
1248 // Unlock the SplitWindows again
1249 for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX; n++ )
1250 {
1251 VclPtr<SfxSplitWindow> const & p = pSplit[n];
1252 if (p->GetWindowCount())
1253 p->Lock(false);
1254 }
1255 }
1256
UpdateChildWindows_Impl()1257 void SfxWorkWindow::UpdateChildWindows_Impl()
1258 {
1259 // tdf#100870, tdf#101320: don't use range-based for loop when
1260 // container is modified
1261 for ( size_t n=0; n<aChildWins.size(); n++ )
1262 {
1263 // any current or in the context available Childwindows
1264 SfxChildWin_Impl *pCW = aChildWins[n].get();
1265 SfxChildWindow *pChildWin = pCW->pWin;
1266 bool bCreate = false;
1267 if ( pCW->nId && (pCW->aInfo.nFlags & SfxChildWindowFlags::ALWAYSAVAILABLE || IsVisible_Impl( pCW->nVisibility ) ) )
1268 {
1269 // In the context is an appropriate ChildWindow allowed;
1270 // it is also turned on?
1271 if ( pChildWin == nullptr && pCW->bCreate )
1272 {
1273 // Internal docking is only used for embedding into another
1274 // container. We force the floating state of all floatable
1275 // child windows.
1276 if ( !bInternalDockingAllowed )
1277 {
1278 // Special case for all non-floatable child windows. We have
1279 // to prevent the creation here!
1280 bCreate = !( pCW->aInfo.nFlags & SfxChildWindowFlags::FORCEDOCK );
1281 }
1282 else if ( !IsDockingAllowed() || bIsFullScreen ) // || !bInternalDocking )
1283 {
1284 // In Presentation mode or FullScreen only FloatingWindows
1285 SfxChildAlignment eAlign;
1286 if ( pCW->aInfo.GetExtraData_Impl( &eAlign ) )
1287 bCreate = ( eAlign == SfxChildAlignment::NOALIGNMENT );
1288 }
1289 else
1290 bCreate = true;
1291
1292 // Currently, no window here, but it is enabled; windows
1293 // Create window and if possible theContext
1294 if ( bCreate )
1295 CreateChildWin_Impl( pCW, false );
1296
1297 if ( !bAllChildrenVisible && pCW->pCli )
1298 pCW->pCli->nVisible &= ~SfxChildVisibility::ACTIVE;
1299 }
1300 else if ( pChildWin )
1301 {
1302 // Window already exists, it should also be visible?
1303 if ( ( !bIsFullScreen || pChildWin->GetAlignment() == SfxChildAlignment::NOALIGNMENT ) && bAllChildrenVisible )
1304 {
1305 // Update Mode is compatible; definitely enable it
1306 bCreate = true;
1307 if ( pCW->pCli )
1308 {
1309 // The window is a direct Child
1310 if ((IsDockingAllowed() && bInternalDockingAllowed)
1311 || pCW->pCli->eAlign == SfxChildAlignment::NOALIGNMENT)
1312 pCW->pCli->nVisible |= SfxChildVisibility::NOT_HIDDEN;
1313 }
1314 else
1315 {
1316 if ( pCW->bCreate && IsDockingAllowed() && bInternalDockingAllowed )
1317 // The window ia within a SplitWindow
1318 static_cast<SfxDockingWindow*>(pChildWin->GetWindow())->Reappear_Impl();
1319 }
1320
1321 if ( pCW->nInterfaceId != pChildWin->GetContextId() )
1322 pChildWin->CreateContext( pCW->nInterfaceId, GetBindings() );
1323 }
1324 }
1325 }
1326
1327 if ( pChildWin && !bCreate )
1328 {
1329 if ( !pChildWin->QueryClose() || pChildWin->IsHideNotDelete() || Application::IsUICaptured() )
1330 {
1331 if ( pCW->pCli )
1332 {
1333 if ( pCW->pCli->nVisible & SfxChildVisibility::NOT_HIDDEN )
1334 pCW->pCli->nVisible ^= SfxChildVisibility::NOT_HIDDEN;
1335 }
1336 else
1337 static_cast<SfxDockingWindow*>(pChildWin->GetWindow())->Disappear_Impl();
1338 }
1339 else
1340 RemoveChildWin_Impl( pCW );
1341 }
1342 }
1343 }
1344
CreateChildWin_Impl(SfxChildWin_Impl * pCW,bool bSetFocus)1345 void SfxWorkWindow::CreateChildWin_Impl( SfxChildWin_Impl *pCW, bool bSetFocus )
1346 {
1347 pCW->aInfo.bVisible = true;
1348
1349 SfxChildWindow *pChildWin = SfxChildWindow::CreateChildWindow( pCW->nId, pWorkWin, &GetBindings(), pCW->aInfo).release();
1350 if (!pChildWin)
1351 return;
1352
1353 if ( bSetFocus )
1354 bSetFocus = pChildWin->WantsFocus();
1355 pChildWin->SetWorkWindow_Impl( this );
1356
1357 // At least the extra string is changed during the evaluation,
1358 // also get it anewed
1359 SfxChildWinInfo aInfo = pChildWin->GetInfo();
1360 pCW->aInfo.aExtraString = aInfo.aExtraString;
1361 pCW->aInfo.bVisible = aInfo.bVisible;
1362 pCW->aInfo.nFlags |= aInfo.nFlags;
1363
1364 // The creation was successful
1365 GetBindings().Invalidate(pCW->nId);
1366
1367 sal_uInt16 nPos = pChildWin->GetPosition();
1368 if (nPos != CHILDWIN_NOPOS)
1369 {
1370 DBG_ASSERT(nPos < SFX_OBJECTBAR_MAX, "Illegal objectbar position!");
1371 if ( aChildren[TbxMatch(nPos)] )// &&
1372 {
1373 // ChildWindow replaces ObjectBar
1374 aChildren[TbxMatch(nPos)]->nVisible ^= SfxChildVisibility::NOT_HIDDEN;
1375 }
1376 }
1377
1378 // make childwin keyboard accessible
1379 pWorkWin->GetSystemWindow()->GetTaskPaneList()->AddWindow( pChildWin->GetWindow() );
1380
1381 pCW->pWin = pChildWin;
1382
1383 if ( pChildWin->GetAlignment() == SfxChildAlignment::NOALIGNMENT || pChildWin->GetWindow()->GetParent() == pWorkWin)
1384 {
1385 // The window is not docked or docked outside of one split windows
1386 // and must therefore be registered explicitly as a Child
1387 if (pChildWin->GetController())
1388 pCW->pCli = RegisterChild_Impl(pChildWin->GetController(), pChildWin->GetAlignment());
1389 else
1390 pCW->pCli = RegisterChild_Impl(*(pChildWin->GetWindow()), pChildWin->GetAlignment());
1391 pCW->pCli->nVisible = SfxChildVisibility::VISIBLE;
1392 if ( pChildWin->GetAlignment() != SfxChildAlignment::NOALIGNMENT && bIsFullScreen )
1393 pCW->pCli->nVisible ^= SfxChildVisibility::ACTIVE;
1394 pCW->pCli->bSetFocus = bSetFocus;
1395 }
1396 else
1397 {
1398 // A docked window which parent is not a WorkingWindow, must lie
1399 // in a SplitWindow and thus not be explicitly registered.
1400 // This happens already in the initialization of SfxDockingWindows!
1401 }
1402
1403 if ( pCW->nInterfaceId != pChildWin->GetContextId() )
1404 pChildWin->CreateContext( pCW->nInterfaceId, GetBindings() );
1405
1406 // Save the information in the INI file
1407 SaveStatus_Impl(pChildWin, pCW->aInfo);
1408 }
1409
RemoveChildWin_Impl(SfxChildWin_Impl * pCW)1410 void SfxWorkWindow::RemoveChildWin_Impl( SfxChildWin_Impl *pCW )
1411 {
1412 sal_uInt16 nId = pCW->nSaveId;
1413 SfxChildWindow *pChildWin = pCW->pWin;
1414
1415 // Save the information in the INI file
1416 SfxChildWindowFlags nFlags = pCW->aInfo.nFlags;
1417 pCW->aInfo = pChildWin->GetInfo();
1418 pCW->aInfo.nFlags |= nFlags;
1419 SaveStatus_Impl(pChildWin, pCW->aInfo);
1420
1421 pChildWin->Hide();
1422
1423 if ( pCW->pCli )
1424 {
1425 // Child window is a direct child window and must therefore unregister
1426 // itself from the WorkWindow
1427 pCW->pCli = nullptr;
1428 if (pChildWin->GetController())
1429 ReleaseChild_Impl(*pChildWin->GetController());
1430 else
1431 ReleaseChild_Impl(*pChildWin->GetWindow());
1432 }
1433 else
1434 {
1435 // ChildWindow is within a SplitWindow and unregister itself in
1436 // the destructor.
1437 }
1438
1439 pWorkWin->GetSystemWindow()->GetTaskPaneList()->RemoveWindow( pChildWin->GetWindow() );
1440 pCW->pWin = nullptr;
1441 pChildWin->Destroy();
1442
1443 GetBindings().Invalidate( nId );
1444 }
1445
ResetStatusBar_Impl()1446 void SfxWorkWindow::ResetStatusBar_Impl()
1447 {
1448 aStatBar.eId = StatusBarId::None;
1449 }
1450
SetStatusBar_Impl(StatusBarId eId)1451 void SfxWorkWindow::SetStatusBar_Impl(StatusBarId eId)
1452 {
1453 if (eId != StatusBarId::None && bShowStatusBar && IsVisible_Impl())
1454 aStatBar.eId = eId;
1455 }
1456
UpdateStatusBar_Impl()1457 void SfxWorkWindow::UpdateStatusBar_Impl()
1458 {
1459 Reference< css::beans::XPropertySet > xPropSet( GetFrameInterface(), UNO_QUERY );
1460 Reference< css::frame::XLayoutManager > xLayoutManager;
1461
1462 Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
1463 aValue >>= xLayoutManager;
1464
1465 // No status bar, if no ID is required or when in FullScreenView or
1466 // if disabled
1467 if (aStatBar.eId != StatusBarId::None && IsDockingAllowed() && bInternalDockingAllowed && bShowStatusBar &&
1468 !bIsFullScreen)
1469 {
1470 // Id has changed, thus create a suitable Statusbarmanager, this takes
1471 // over the current status bar;
1472 if ( xLayoutManager.is() )
1473 xLayoutManager->requestElement( g_aStatusBarResName );
1474 }
1475 else
1476 {
1477 // Destroy the current StatusBar
1478 // The Manager only creates the Status bar, does not destroy it.
1479 if ( xLayoutManager.is() )
1480 xLayoutManager->destroyElement( g_aStatusBarResName );
1481 }
1482 }
1483
MakeVisible_Impl(bool bVis)1484 void SfxWorkWindow::MakeVisible_Impl( bool bVis )
1485 {
1486 if ( bVis )
1487 nOrigMode = SfxVisibilityFlags::Standard;
1488 else
1489 nOrigMode = SfxVisibilityFlags::Invisible;
1490
1491 if ( nOrigMode != nUpdateMode)
1492 nUpdateMode = nOrigMode;
1493 }
1494
IsVisible_Impl() const1495 bool SfxWorkWindow::IsVisible_Impl() const
1496 {
1497 return nOrigMode != SfxVisibilityFlags::Invisible;
1498 }
1499
1500
HidePopups_Impl(bool bHide,sal_uInt16 nId)1501 void SfxWorkWindow::HidePopups_Impl(bool bHide, sal_uInt16 nId )
1502 {
1503 if (comphelper::LibreOfficeKit::isActive() && bHide)
1504 return;
1505
1506 for (const std::unique_ptr<SfxChildWin_Impl>& i : aChildWins)
1507 {
1508 SfxChildWindow *pCW = i->pWin;
1509 if (pCW && pCW->GetAlignment() == SfxChildAlignment::NOALIGNMENT && pCW->GetType() != nId)
1510 {
1511 vcl::Window *pWin = pCW->GetWindow();
1512 SfxChild_Impl *pChild = FindChild_Impl(pWin);
1513 if (!pChild)
1514 {
1515 SAL_WARN("sfx.appl", "missing SfxChild_Impl child!");
1516 continue;
1517 }
1518 if (bHide)
1519 {
1520 pChild->nVisible &= ~SfxChildVisibility::ACTIVE;
1521 pCW->Hide();
1522 }
1523 else if ( !comphelper::LibreOfficeKit::isActive() ||
1524 SfxChildVisibility::ACTIVE != (pChild->nVisible & SfxChildVisibility::ACTIVE) )
1525 {
1526 pChild->nVisible |= SfxChildVisibility::ACTIVE;
1527 if ( SfxChildVisibility::VISIBLE == (pChild->nVisible & SfxChildVisibility::VISIBLE) )
1528 pCW->Show( ShowFlags::NoFocusChange | ShowFlags::NoActivate );
1529 }
1530 }
1531 }
1532 }
1533
1534
ConfigChild_Impl(SfxChildIdentifier eChild,SfxDockingConfig eConfig,sal_uInt16 nId)1535 void SfxWorkWindow::ConfigChild_Impl(SfxChildIdentifier eChild,
1536 SfxDockingConfig eConfig, sal_uInt16 nId)
1537 {
1538 SfxDockingWindow* pDockWin=nullptr;
1539 sal_uInt16 nPos = USHRT_MAX;
1540 vcl::Window *pWin=nullptr;
1541 SfxChildWin_Impl *pCW = nullptr;
1542
1543 // configure direct childwindow
1544 for (const std::unique_ptr<SfxChildWin_Impl>& i : aChildWins)
1545 {
1546 pCW = i.get();
1547 SfxChildWindow *pChild = pCW->pWin;
1548 if ( pChild && (pChild->GetType() == nId ))
1549 {
1550 if (SfxDockingWindow* pSfxDockingWindow = dynamic_cast<SfxDockingWindow*>(pChild->GetWindow()))
1551 {
1552 // it's a DockingWindow
1553 pDockWin = pSfxDockingWindow;
1554 }
1555 else
1556 {
1557 // FloatingWindow or ModelessDialog
1558 pWin = pChild->GetWindow();
1559 }
1560 break;
1561 }
1562 }
1563
1564 if ( pDockWin )
1565 {
1566 if ( eChild == SfxChildIdentifier::DOCKINGWINDOW || pDockWin->GetAlignment() == SfxChildAlignment::NOALIGNMENT )
1567 {
1568 if ( eChild == SfxChildIdentifier::SPLITWINDOW && eConfig == SfxDockingConfig::TOGGLEFLOATMODE)
1569 {
1570 // DockingWindow was dragged out of a SplitWindow
1571 pCW->pCli = RegisterChild_Impl(*pDockWin, pDockWin->GetAlignment());
1572 pCW->pCli->nVisible = SfxChildVisibility::VISIBLE;
1573 }
1574
1575 pWin = pDockWin;
1576 }
1577 else
1578 {
1579 SfxSplitWindow *pSplitWin = GetSplitWindow_Impl(pDockWin->GetAlignment());
1580
1581 // configure DockingWindow inside a SplitWindow
1582 if ( eConfig == SfxDockingConfig::TOGGLEFLOATMODE)
1583 {
1584 // DockingWindow was dragged into a SplitWindow
1585 pCW->pCli = nullptr;
1586 ReleaseChild_Impl(*pDockWin);
1587 }
1588
1589 pWin = pSplitWin->GetSplitWindow();
1590 if ( pSplitWin->GetWindowCount() == 1 )
1591 static_cast<SplitWindow*>(pWin)->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
1592 }
1593 }
1594
1595 DBG_ASSERT( pCW, "Unknown window!" );
1596
1597 if ( !bSorted )
1598 // windows may have been registered and released without an update until now
1599 Sort_Impl();
1600
1601 decltype(aSortedList)::size_type n;
1602 for ( n=0; n<aSortedList.size(); ++n )
1603 {
1604 SfxChild_Impl *pChild = aChildren[aSortedList[n]].get();
1605 if ( pChild && pChild->pWin == pWin )
1606 break;
1607 }
1608
1609 if ( n < aSortedList.size() )
1610 // sometimes called while toggeling float mode
1611 nPos = aSortedList[n];
1612
1613 switch ( eConfig )
1614 {
1615 case SfxDockingConfig::SETDOCKINGRECTS :
1616 {
1617 if (nPos == USHRT_MAX || !pDockWin)
1618 return;
1619
1620 tools::Rectangle aOuterRect( GetTopRect_Impl() );
1621 aOuterRect.SetPos( pWorkWin->OutputToScreenPixel( aOuterRect.TopLeft() ));
1622 tools::Rectangle aInnerRect( aOuterRect );
1623
1624 // The current affected window is included in the calculation of
1625 // the inner rectangle!
1626 for (sal_uInt16 i : aSortedList)
1627 {
1628 SfxChild_Impl* pCli = aChildren[i].get();
1629
1630 if ( pCli && pCli->nVisible == SfxChildVisibility::VISIBLE && pCli->pWin )
1631 {
1632 switch ( pCli->eAlign )
1633 {
1634 case SfxChildAlignment::TOP:
1635 // Object-Toolboxes come always last
1636 aInnerRect.AdjustTop(pCli->aSize.Height() );
1637 break;
1638
1639 case SfxChildAlignment::HIGHESTTOP:
1640 // Always performed first
1641 aInnerRect.AdjustTop(pCli->aSize.Height() );
1642 break;
1643
1644 case SfxChildAlignment::LOWESTTOP:
1645 // Is only counted if it is the current window
1646 if ( i == nPos )
1647 aInnerRect.AdjustTop(pCli->aSize.Height() );
1648 break;
1649
1650 case SfxChildAlignment::BOTTOM:
1651 // Object-Toolboxes come always last
1652 aInnerRect.AdjustBottom( -(pCli->aSize.Height()) );
1653 break;
1654
1655 case SfxChildAlignment::LOWESTBOTTOM:
1656 // Always performed first
1657 aInnerRect.AdjustBottom( -(pCli->aSize.Height()) );
1658 break;
1659
1660 case SfxChildAlignment::HIGHESTBOTTOM:
1661 // Is only counted if it is the current window
1662 if ( i == nPos )
1663 aInnerRect.AdjustBottom( -(pCli->aSize.Height()) );
1664 break;
1665
1666 case SfxChildAlignment::LEFT:
1667 // Toolboxes come always last
1668 aInnerRect.AdjustLeft(pCli->aSize.Width() );
1669 break;
1670
1671 case SfxChildAlignment::FIRSTLEFT:
1672 // Always performed first
1673 aInnerRect.AdjustLeft(pCli->aSize.Width() );
1674 break;
1675
1676 case SfxChildAlignment::LASTLEFT:
1677 // Is only counted if it is the current window
1678 if (i == nPos)
1679 aInnerRect.AdjustLeft(pCli->aSize.Width() );
1680 break;
1681
1682 case SfxChildAlignment::RIGHT:
1683 // Toolboxes come always last
1684 aInnerRect.AdjustRight( -(pCli->aSize.Width()) );
1685 break;
1686
1687 case SfxChildAlignment::FIRSTRIGHT:
1688 // Is only counted if it is the current window
1689 if (i == nPos)
1690 aInnerRect.AdjustRight( -(pCli->aSize.Width()) );
1691 break;
1692
1693 case SfxChildAlignment::LASTRIGHT:
1694 // Always performed first
1695 aInnerRect.AdjustRight( -(pCli->aSize.Width()) );
1696 break;
1697
1698 default:
1699 break;
1700 }
1701 }
1702 }
1703
1704 pDockWin->SetDockingRects(aOuterRect, aInnerRect);
1705 break;
1706 }
1707
1708 case SfxDockingConfig::ALIGNDOCKINGWINDOW :
1709 case SfxDockingConfig::TOGGLEFLOATMODE:
1710 {
1711 if ( nPos == USHRT_MAX && !pCW )
1712 return;
1713
1714 SfxChildAlignment eAlign = SfxChildAlignment::NOALIGNMENT;
1715 SfxChild_Impl *pCli = ( nPos != USHRT_MAX ) ? aChildren[nPos].get() : nullptr;
1716 if ( pCli && pDockWin )
1717 {
1718 eAlign = pDockWin->GetAlignment();
1719 if ( eChild == SfxChildIdentifier::DOCKINGWINDOW || eAlign == SfxChildAlignment::NOALIGNMENT)
1720 {
1721 // configuration inside the SplitWindow, no change for the SplitWindows' configuration
1722 pCli->bResize = true;
1723 pCli->aSize = pDockWin->GetSizePixel();
1724 }
1725 }
1726
1727 if ( pCli )
1728 {
1729 if( pCli->eAlign != eAlign )
1730 {
1731 bSorted = false;
1732 pCli->eAlign = eAlign;
1733 }
1734
1735 ArrangeChildren_Impl();
1736 ShowChildren_Impl();
1737 }
1738
1739 if ( pCW && pCW->pWin )
1740 {
1741 // store changed configuration
1742 SfxChildWindowFlags nFlags = pCW->aInfo.nFlags;
1743 pCW->aInfo = pCW->pWin->GetInfo();
1744 pCW->aInfo.nFlags |= nFlags;
1745 SaveStatus_Impl( pCW->pWin, pCW->aInfo);
1746 }
1747
1748 break;
1749 }
1750 }
1751 }
1752
1753
SetChildWindowVisible_Impl(sal_uInt32 lId,bool bEnabled,SfxVisibilityFlags nMode)1754 void SfxWorkWindow::SetChildWindowVisible_Impl( sal_uInt32 lId, bool bEnabled, SfxVisibilityFlags nMode )
1755 {
1756 sal_uInt16 nInter = static_cast<sal_uInt16>( lId >> 16 );
1757 sal_uInt16 nId = static_cast<sal_uInt16>( lId & 0xFFFF );
1758
1759 SfxChildWin_Impl *pCW=nullptr;
1760
1761 if ( !pCW )
1762 {
1763 // If no Parent or the Parent us still unknown, then search here
1764 sal_uInt16 nCount = aChildWins.size();
1765 for (sal_uInt16 n=0; n<nCount; n++)
1766 if (aChildWins[n]->nSaveId == nId)
1767 {
1768 pCW = aChildWins[n].get();
1769 break;
1770 }
1771 }
1772
1773 if ( !pCW )
1774 {
1775 // If new, then initialize, add this here depending on the flag or
1776 // the Parent
1777 pCW = new SfxChildWin_Impl( lId );
1778 pCW->nId = nId;
1779 InitializeChild_Impl( pCW );
1780 aChildWins.push_back( std::unique_ptr<SfxChildWin_Impl>(pCW) );
1781 }
1782
1783 pCW->nId = nId;
1784 if ( nInter )
1785 pCW->nInterfaceId = nInter;
1786 pCW->nVisibility = nMode;
1787 pCW->bEnable = bEnabled;
1788 }
1789
1790
1791 // The on/off status of a ChildWindow is switched
1792
ToggleChildWindow_Impl(sal_uInt16 nId,bool bSetFocus)1793 void SfxWorkWindow::ToggleChildWindow_Impl(sal_uInt16 nId, bool bSetFocus)
1794 {
1795 sal_uInt16 nCount = aChildWins.size();
1796 sal_uInt16 n;
1797 for (n=0; n<nCount; n++)
1798 if (aChildWins[n]->nId == nId)
1799 break;
1800
1801 if ( n<nCount )
1802 {
1803 // The Window is already known
1804 SfxChildWin_Impl *pCW = aChildWins[n].get();
1805 SfxChildWindow *pChild = pCW->pWin;
1806
1807 bool bCreationAllowed( true );
1808 if ( !bInternalDockingAllowed )
1809 {
1810 // Special case for all non-floatable child windows. We have
1811 // to prevent the creation here!
1812 bCreationAllowed = !( pCW->aInfo.nFlags & SfxChildWindowFlags::FORCEDOCK );
1813 }
1814
1815 if ( bCreationAllowed )
1816 {
1817 if ( pCW->bCreate )
1818 {
1819 if ( pChild )
1820 {
1821 if ( pChild->QueryClose() )
1822 {
1823 pCW->bCreate = false;
1824 // The Window should be switched off
1825 pChild->SetVisible_Impl( false );
1826 RemoveChildWin_Impl( pCW );
1827 }
1828 }
1829 else
1830 {
1831 // no actual Window exists, yet => just remember the "switched off" state
1832 pCW->bCreate = false;
1833 }
1834 }
1835 else
1836 {
1837 pCW->bCreate = true;
1838 if ( pChild )
1839 {
1840 ShowChildWindow_Impl( nId, true, bSetFocus );
1841 }
1842 else
1843 {
1844 // create actual Window
1845 CreateChildWin_Impl( pCW, bSetFocus );
1846 if ( !pCW->pWin )
1847 // no success
1848 pCW->bCreate = false;
1849 }
1850 }
1851 }
1852
1853 ArrangeChildren_Impl();
1854 ShowChildren_Impl();
1855
1856 if ( pCW->bCreate && bCreationAllowed )
1857 {
1858 if ( !pCW->pCli )
1859 {
1860 SfxDockingWindow *pDock =
1861 static_cast<SfxDockingWindow*>( pCW->pWin->GetWindow() );
1862 if ( pDock->IsAutoHide_Impl() )
1863 pDock->AutoShow_Impl();
1864 }
1865 }
1866
1867 return;
1868 }
1869
1870 #ifdef DBG_UTIL
1871 nCount = aChildWins.size();
1872 for (n=0; n<nCount; n++)
1873 if (aChildWins[n]->nSaveId == nId)
1874 break;
1875
1876 if ( n < nCount )
1877 {
1878 OSL_FAIL("The ChildWindow is not in context!");
1879 }
1880 else
1881 {
1882 OSL_FAIL("The ChildWindow is not registered!");
1883 }
1884 #endif
1885 }
1886
1887
HasChildWindow_Impl(sal_uInt16 nId)1888 bool SfxWorkWindow::HasChildWindow_Impl(sal_uInt16 nId)
1889 {
1890 sal_uInt16 nCount = aChildWins.size();
1891 sal_uInt16 n;
1892 for (n=0; n<nCount; n++)
1893 if (aChildWins[n]->nSaveId == nId)
1894 break;
1895
1896 if (n<nCount)
1897 {
1898 SfxChildWin_Impl *pCW = aChildWins[n].get();
1899 SfxChildWindow *pChild = pCW->pWin;
1900 return ( pChild && pCW->bCreate );
1901 }
1902
1903 return false;
1904 }
1905
IsFloating(sal_uInt16 nId)1906 bool SfxWorkWindow::IsFloating( sal_uInt16 nId )
1907 {
1908 SfxChildWin_Impl *pCW=nullptr;
1909
1910 if ( !pCW )
1911 {
1912 // If no Parent or the Parent us still unknown, then search here
1913 sal_uInt16 nCount = aChildWins.size();
1914 for (sal_uInt16 n=0; n<nCount; n++)
1915 if (aChildWins[n]->nSaveId == nId)
1916 {
1917 pCW = aChildWins[n].get();
1918 break;
1919 }
1920 }
1921
1922 if ( !pCW )
1923 {
1924 // If new, then initialize, add this here depending on the flag or
1925 // the Parent
1926 pCW = new SfxChildWin_Impl( nId );
1927 pCW->bEnable = false;
1928 pCW->nId = 0;
1929 pCW->nVisibility = SfxVisibilityFlags::Invisible;
1930 InitializeChild_Impl( pCW );
1931 aChildWins.push_back( std::unique_ptr<SfxChildWin_Impl>(pCW) );
1932 }
1933
1934 SfxChildAlignment eAlign;
1935 if ( pCW->aInfo.GetExtraData_Impl( &eAlign ) )
1936 return( eAlign == SfxChildAlignment::NOALIGNMENT );
1937 else
1938 return true;
1939 }
1940
1941
KnowsChildWindow_Impl(sal_uInt16 nId)1942 bool SfxWorkWindow::KnowsChildWindow_Impl(sal_uInt16 nId)
1943 {
1944 SfxChildWin_Impl *pCW=nullptr;
1945 sal_uInt16 nCount = aChildWins.size();
1946 sal_uInt16 n;
1947 for (n=0; n<nCount; n++)
1948 {
1949 pCW = aChildWins[n].get();
1950 if ( pCW->nSaveId == nId)
1951 break;
1952 }
1953
1954 if (n<nCount)
1955 {
1956 if ( !(pCW->aInfo.nFlags & SfxChildWindowFlags::ALWAYSAVAILABLE) && !IsVisible_Impl( pCW->nVisibility ) )
1957 return false;
1958 return pCW->bEnable;
1959 }
1960 else
1961 return false;
1962 }
1963
1964
SetChildWindow_Impl(sal_uInt16 nId,bool bOn,bool bSetFocus)1965 void SfxWorkWindow::SetChildWindow_Impl(sal_uInt16 nId, bool bOn, bool bSetFocus)
1966 {
1967 SfxChildWin_Impl *pCW=nullptr;
1968 SfxWorkWindow *pWork = nullptr;
1969
1970 if ( !pCW )
1971 {
1972 // If no Parent or the Parent us still unknown, then search here
1973 sal_uInt16 nCount = aChildWins.size();
1974 for (sal_uInt16 n=0; n<nCount; n++)
1975 if (aChildWins[n]->nSaveId == nId)
1976 {
1977 pCW = aChildWins[n].get();
1978 pWork = this;
1979 break;
1980 }
1981 }
1982
1983 if ( !pCW )
1984 {
1985 // If new, then initialize, add this here depending on the flag or
1986 // the Parent
1987 pCW = new SfxChildWin_Impl( nId );
1988 InitializeChild_Impl( pCW );
1989 if ( !pWork || pCW->aInfo.nFlags & SfxChildWindowFlags::TASK )
1990 pWork = this;
1991 pWork->aChildWins.push_back( std::unique_ptr<SfxChildWin_Impl>(pCW) );
1992 }
1993
1994 if ( pCW->bCreate != bOn )
1995 pWork->ToggleChildWindow_Impl(nId,bSetFocus);
1996 }
1997
1998
ShowChildWindow_Impl(sal_uInt16 nId,bool bVisible,bool bSetFocus)1999 void SfxWorkWindow::ShowChildWindow_Impl(sal_uInt16 nId, bool bVisible, bool bSetFocus)
2000 {
2001 sal_uInt16 nCount = aChildWins.size();
2002 SfxChildWin_Impl* pCW=nullptr;
2003 sal_uInt16 n;
2004 for (n=0; n<nCount; n++)
2005 {
2006 pCW = aChildWins[n].get();
2007 if (pCW->nId == nId)
2008 break;
2009 }
2010
2011 if ( n<nCount )
2012 {
2013 SfxChildWindow *pChildWin = pCW->pWin;
2014 if ( pChildWin )
2015 {
2016 if ( bVisible )
2017 {
2018 if ( pCW->pCli )
2019 {
2020 pCW->pCli->bSetFocus = bSetFocus;
2021 pCW->pCli->nVisible = SfxChildVisibility::VISIBLE;
2022 pChildWin->Show( bSetFocus && pChildWin->WantsFocus() ? ShowFlags::NONE : ShowFlags::NoFocusChange | ShowFlags::NoActivate );
2023 }
2024 else
2025 static_cast<SfxDockingWindow*>(pChildWin->GetWindow())->Reappear_Impl();
2026
2027 }
2028 else
2029 {
2030 if ( pCW->pCli )
2031 {
2032 pCW->pCli->nVisible = SfxChildVisibility::VISIBLE ^ SfxChildVisibility::NOT_HIDDEN;
2033 pCW->pWin->Hide();
2034 }
2035 else
2036 static_cast<SfxDockingWindow*>(pChildWin->GetWindow())->Disappear_Impl();
2037
2038 }
2039
2040 ArrangeChildren_Impl();
2041 ShowChildren_Impl();
2042 }
2043 else if ( bVisible )
2044 {
2045 SetChildWindow_Impl( nId, true, bSetFocus );
2046 pChildWin = pCW->pWin;
2047 }
2048
2049 if ( pChildWin )
2050 {
2051 pChildWin->SetVisible_Impl( bVisible );
2052 SfxChildWindowFlags nFlags = pCW->aInfo.nFlags;
2053 pCW->aInfo = pChildWin->GetInfo();
2054 pCW->aInfo.nFlags |= nFlags;
2055 if ( !pCW->bCreate )
2056 SaveStatus_Impl( pChildWin, pCW->aInfo );
2057 }
2058
2059 return;
2060 }
2061
2062 #ifdef DBG_UTIL
2063 nCount = aChildWins.size();
2064 for (n=0; n<nCount; n++)
2065 if (aChildWins[n]->nSaveId == nId)
2066 break;
2067
2068 if ( n<nCount )
2069 {
2070 OSL_FAIL("The ChildWindow is not in context!");
2071 }
2072 else
2073 {
2074 OSL_FAIL("The ChildWindow is not registered");
2075 }
2076 #endif
2077 }
2078
2079
GetChildWindow_Impl(sal_uInt16 nId)2080 SfxChildWindow* SfxWorkWindow::GetChildWindow_Impl(sal_uInt16 nId)
2081 {
2082 sal_uInt16 nCount = aChildWins.size();
2083 sal_uInt16 n;
2084 for (n=0; n<nCount; n++)
2085 if (aChildWins[n]->nSaveId == nId)
2086 break;
2087
2088 if (n<nCount)
2089 return aChildWins[n]->pWin;
2090 return nullptr;
2091 }
2092
2093
ResetChildWindows_Impl()2094 void SfxWorkWindow::ResetChildWindows_Impl()
2095 {
2096 for (std::unique_ptr<SfxChildWin_Impl>& pChildWin : aChildWins)
2097 {
2098 pChildWin->nId = 0;
2099 pChildWin->bEnable = false;
2100 }
2101 }
2102
2103 // returns the size of the area (client area) of the
2104 // parent windows, in which the ChildWindow can be fitted.
2105
GetTopRect_Impl() const2106 tools::Rectangle SfxWorkWindow::GetTopRect_Impl() const
2107 {
2108 return pMasterFrame->GetTopOuterRectPixel_Impl();
2109 }
2110
2111
2112 // Virtual method to find out if there is room for a ChildWindow in the
2113 // client area of the parent.
2114
RequestTopToolSpacePixel_Impl(SvBorder aBorder)2115 bool SfxWorkWindow::RequestTopToolSpacePixel_Impl( SvBorder aBorder )
2116 {
2117 return !(!IsDockingAllowed() ||
2118 aClientArea.GetWidth() < aBorder.Left() + aBorder.Right() ||
2119 aClientArea.GetHeight() < aBorder.Top() + aBorder.Bottom());
2120 }
2121
SaveStatus_Impl(SfxChildWindow * pChild,const SfxChildWinInfo & rInfo)2122 void SfxWorkWindow::SaveStatus_Impl(SfxChildWindow *pChild, const SfxChildWinInfo &rInfo)
2123 {
2124 // The Status of the Presentation mode is not saved
2125 if ( IsDockingAllowed() && bInternalDockingAllowed )
2126 pChild->SaveStatus(rInfo);
2127 }
2128
InitializeChild_Impl(SfxChildWin_Impl * pCW)2129 void SfxWorkWindow::InitializeChild_Impl(SfxChildWin_Impl *pCW)
2130 {
2131 SfxDispatcher *pDisp = pBindings->GetDispatcher_Impl();
2132 SfxViewFrame *pViewFrame = pDisp ? pDisp->GetFrame() :nullptr;
2133 SfxModule *pMod = pViewFrame ? SfxModule::GetActiveModule(pViewFrame) :nullptr;
2134
2135 OUString sModule;
2136 if (pViewFrame)
2137 {
2138 try
2139 {
2140 uno::Reference< frame::XModuleManager2 > xModuleManager(
2141 frame::ModuleManager::create(::comphelper::getProcessComponentContext()));
2142 sModule = xModuleManager->identify(pViewFrame->GetFrame().GetFrameInterface());
2143 SvtModuleOptions::EFactory eFac = SvtModuleOptions::ClassifyFactoryByServiceName(sModule);
2144 sModule = SvtModuleOptions::GetFactoryShortName(eFac);
2145 }
2146 catch (...)
2147 {
2148 }
2149 }
2150
2151 SfxChildWinFactory* pFact=nullptr;
2152 SfxApplication *pApp = SfxGetpApp();
2153 {
2154 SfxChildWinFactArr_Impl &rFactories = pApp->GetChildWinFactories_Impl();
2155 for ( size_t nFactory = 0; nFactory < rFactories.size(); ++nFactory )
2156 {
2157 pFact = &rFactories[nFactory];
2158 if ( pFact->nId == pCW->nSaveId )
2159 {
2160 pCW->aInfo = pFact->aInfo;
2161 pCW->aInfo.aModule = sModule;
2162 SfxChildWindow::InitializeChildWinFactory_Impl(
2163 pCW->nSaveId, pCW->aInfo);
2164 pCW->bCreate = pCW->aInfo.bVisible;
2165 SfxChildWindowFlags nFlags = pFact->aInfo.nFlags;
2166 if ( nFlags & SfxChildWindowFlags::TASK )
2167 pCW->aInfo.nFlags |= SfxChildWindowFlags::TASK;
2168 if ( nFlags & SfxChildWindowFlags::CANTGETFOCUS )
2169 pCW->aInfo.nFlags |= SfxChildWindowFlags::CANTGETFOCUS;
2170 if ( nFlags & SfxChildWindowFlags::FORCEDOCK )
2171 pCW->aInfo.nFlags |= SfxChildWindowFlags::FORCEDOCK;
2172 pFact->aInfo = pCW->aInfo;
2173 return;
2174 }
2175 }
2176 }
2177
2178 if ( !pMod )
2179 return;
2180
2181 SfxChildWinFactArr_Impl *pFactories = pMod->GetChildWinFactories_Impl();
2182 if ( !pFactories )
2183 return;
2184
2185 SfxChildWinFactArr_Impl &rFactories = *pFactories;
2186 for ( size_t nFactory = 0; nFactory < rFactories.size(); ++nFactory )
2187 {
2188 pFact = &rFactories[nFactory];
2189 if ( pFact->nId == pCW->nSaveId )
2190 {
2191 pCW->aInfo = pFact->aInfo;
2192 pCW->aInfo.aModule = sModule;
2193 SfxChildWindow::InitializeChildWinFactory_Impl(
2194 pCW->nSaveId, pCW->aInfo);
2195 pCW->bCreate = pCW->aInfo.bVisible;
2196 SfxChildWindowFlags nFlags = pFact->aInfo.nFlags;
2197 if ( nFlags & SfxChildWindowFlags::TASK )
2198 pCW->aInfo.nFlags |= SfxChildWindowFlags::TASK;
2199 if ( nFlags & SfxChildWindowFlags::CANTGETFOCUS )
2200 pCW->aInfo.nFlags |= SfxChildWindowFlags::CANTGETFOCUS;
2201 if ( nFlags & SfxChildWindowFlags::FORCEDOCK )
2202 pCW->aInfo.nFlags |= SfxChildWindowFlags::FORCEDOCK;
2203 if ( nFlags & SfxChildWindowFlags::ALWAYSAVAILABLE )
2204 pCW->aInfo.nFlags |= SfxChildWindowFlags::ALWAYSAVAILABLE;
2205 pFact->aInfo = pCW->aInfo;
2206 return;
2207 }
2208 }
2209 }
2210
GetSplitWindow_Impl(SfxChildAlignment eAlign)2211 SfxSplitWindow* SfxWorkWindow::GetSplitWindow_Impl( SfxChildAlignment eAlign )
2212 {
2213 switch ( eAlign )
2214 {
2215 case SfxChildAlignment::TOP:
2216 return pSplit[2];
2217
2218 case SfxChildAlignment::BOTTOM:
2219 return pSplit[3];
2220
2221 case SfxChildAlignment::LEFT:
2222 return pSplit[0];
2223
2224 case SfxChildAlignment::RIGHT:
2225 return pSplit[1];
2226
2227 default:
2228 return nullptr;
2229 }
2230 }
2231
MakeChildrenVisible_Impl(bool bVis)2232 void SfxWorkWindow::MakeChildrenVisible_Impl( bool bVis )
2233 {
2234 bAllChildrenVisible = bVis;
2235 if ( bVis )
2236 {
2237 if ( !bSorted )
2238 Sort_Impl();
2239 for (sal_uInt16 n : aSortedList)
2240 {
2241 SfxChild_Impl* pCli = aChildren[n].get();
2242 if ( (pCli->eAlign == SfxChildAlignment::NOALIGNMENT) || (IsDockingAllowed() && bInternalDockingAllowed) )
2243 pCli->nVisible |= SfxChildVisibility::ACTIVE;
2244 }
2245 }
2246 else
2247 {
2248 if ( !bSorted )
2249 Sort_Impl();
2250 for (sal_uInt16 n : aSortedList)
2251 {
2252 SfxChild_Impl* pCli = aChildren[n].get();
2253 pCli->nVisible &= ~SfxChildVisibility::ACTIVE;
2254 }
2255 }
2256 }
2257
IsAutoHideMode(const SfxSplitWindow * pSplitWin)2258 bool SfxWorkWindow::IsAutoHideMode( const SfxSplitWindow *pSplitWin )
2259 {
2260 for (const VclPtr<SfxSplitWindow> & pWin : pSplit)
2261 {
2262 if ( pWin.get() != pSplitWin && pWin->IsAutoHide( true ) )
2263 return true;
2264 }
2265 return false;
2266 }
2267
2268
EndAutoShow_Impl(Point aPos)2269 void SfxWorkWindow::EndAutoShow_Impl( Point aPos )
2270 {
2271 for (VclPtr<SfxSplitWindow> & p : pSplit)
2272 {
2273 if ( p && p->IsAutoHide(false) )
2274 {
2275 Point aLocalPos = p->ScreenToOutputPixel( aPos );
2276 tools::Rectangle aRect( Point(), p->GetSizePixel() );
2277 if ( !aRect.IsInside( aLocalPos ) )
2278 p->FadeOut();
2279 }
2280 }
2281 }
2282
ArrangeAutoHideWindows(SfxSplitWindow * pActSplitWin)2283 void SfxWorkWindow::ArrangeAutoHideWindows( SfxSplitWindow *pActSplitWin )
2284 {
2285 if ( m_nLock )
2286 return;
2287
2288 tools::Rectangle aArea( aUpperClientArea );
2289 for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX; n++ )
2290 {
2291 // Either dummy window or window in the auto-show-mode are processed
2292 // (not pinned, FadeIn).
2293 // Only the abandoned window may be invisible, because perhaps its
2294 // size is just being calculated before it is displayed.
2295 VclPtr<SfxSplitWindow> const & pSplitWin = pSplit[n];
2296 bool bDummyWindow = !pSplitWin->IsFadeIn();
2297 vcl::Window *pDummy = pSplitWin->GetSplitWindow();
2298 vcl::Window *pWin = bDummyWindow ? pDummy : pSplitWin;
2299 if ( (pSplitWin->IsPinned() && !bDummyWindow) || (!pWin->IsVisible() && pActSplitWin != pSplitWin) )
2300 continue;
2301
2302 // Width and position of the dummy window as a starting point
2303 Size aSize = pDummy->GetSizePixel();
2304 Point aPos = pDummy->GetPosPixel();
2305
2306 switch ( n )
2307 {
2308 case 0 :
2309 {
2310 // Left SplitWindow
2311 // Get the width of the Window yourself, if no DummyWindow
2312 if ( !bDummyWindow )
2313 aSize.setWidth( pSplitWin->GetSizePixel().Width() );
2314
2315 // If a Window is visible to the left, then the free region
2316 // starts to the right from it, for example at the Client area
2317 long nLeft = aPos.X() + aSize.Width();
2318 if ( nLeft > aArea.Left() )
2319 aArea.SetLeft( nLeft );
2320 break;
2321 }
2322 case 1 :
2323 {
2324 // Right SplitWindow
2325 // Position to correct the difference of the widths
2326 aPos.AdjustX(aSize.Width() );
2327
2328 // Get the width of the Window yourself, if no DummyWindow
2329 if ( !bDummyWindow )
2330 aSize.setWidth( pSplitWin->GetSizePixel().Width() );
2331
2332 aPos.AdjustX( -(aSize.Width()) );
2333
2334 // If already a window is opened at the left side, then the
2335 // right is not allowed to overlap this one.
2336 if ( aPos.X() < aArea.Left() )
2337 {
2338 aPos.setX( aArea.Left() );
2339 aSize.setWidth( aArea.GetWidth() );
2340 }
2341
2342 // If a Window is visible to the right, then the free region
2343 // starts to the left from it, for example at the Client area
2344 long nRight = aPos.X();
2345 if ( !aArea.IsWidthEmpty() && nRight < aArea.Right() )
2346 aArea.SetRight( nRight );
2347 break;
2348 }
2349 case 2 :
2350 {
2351 // Top SplitWindow
2352 // Get the height of the Window yourself, if no DummyWindow
2353 if ( !bDummyWindow )
2354 aSize.setHeight( pSplitWin->GetSizePixel().Height() );
2355
2356
2357 // Adjust width with regard to if a Window is already open
2358 // to the left or right
2359 aPos.setX( aArea.Left() );
2360 aSize.setWidth( aArea.GetWidth() );
2361
2362 // If a Window is visible at the top, then the free region
2363 // starts beneath it, for example at the Client area
2364 long nTop = aPos.Y() + aSize.Height();
2365 if ( nTop > aArea.Top() )
2366 aArea.SetTop( nTop );
2367 break;
2368 }
2369 case 3 :
2370 {
2371 // The bottom SplitWindow
2372 // Position to correct the difference of the heights
2373 aPos.AdjustY(aSize.Height() );
2374
2375 // Get the height of the Window yourself, if no DummyWindow
2376 if ( !bDummyWindow )
2377 aSize.setHeight( pSplitWin->GetSizePixel().Height() );
2378
2379 aPos.AdjustY( -(aSize.Height()) );
2380
2381 // Adjust width with regard to if a Window is already open
2382 // to the left or right.
2383 aPos.setX( aArea.Left() );
2384 aSize.setWidth( aArea.GetWidth() );
2385
2386 // If already a window is opened at the top, then the
2387 // bottom one is not allowed to overlap this one.
2388 if ( aPos.Y() < aArea.Top() )
2389 {
2390 aPos.setY( aArea.Top() );
2391 aSize.setHeight( aArea.GetHeight() );
2392 }
2393
2394 break;
2395 }
2396 }
2397
2398 if ( !bDummyWindow )
2399 // the FadeIn-Window is a Floating window, which coordinates are
2400 // set in Screen coordinates.
2401 pSplitWin->SetPosSizePixel( pWorkWin->OutputToScreenPixel(aPos), aSize );
2402 else
2403 // the docked DummyWindow
2404 pDummy->SetPosSizePixel( aPos, aSize );
2405 }
2406 }
2407
GetFreeArea(bool bAutoHide) const2408 tools::Rectangle SfxWorkWindow::GetFreeArea( bool bAutoHide ) const
2409 {
2410 if ( bAutoHide )
2411 {
2412 tools::Rectangle aArea( aClientArea );
2413 for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX; n++ )
2414 {
2415 if ( pSplit[n]->IsPinned() || !pSplit[n]->IsVisible() )
2416 continue;
2417
2418 Size aSize = pSplit[n]->GetSizePixel();
2419 switch ( n )
2420 {
2421 case 0 :
2422 aArea.AdjustLeft(aSize.Width() );
2423 break;
2424 case 1 :
2425 aArea.AdjustRight( -(aSize.Width()) );
2426 break;
2427 case 2 :
2428 aArea.AdjustTop(aSize.Height() );
2429 break;
2430 case 3 :
2431 aArea.AdjustBottom( -(aSize.Height()) );
2432 break;
2433 }
2434 }
2435
2436 return aArea;
2437 }
2438 else
2439 return aClientArea;
2440 }
2441
SetActiveChild_Impl(vcl::Window * pChild)2442 void SfxWorkWindow::SetActiveChild_Impl( vcl::Window *pChild )
2443 {
2444 pActiveChild = pChild;
2445 }
2446
DataChanged_Impl()2447 void SfxWorkWindow::DataChanged_Impl()
2448 {
2449 sal_uInt16 n;
2450 sal_uInt16 nCount = aChildWins.size();
2451 for (n=0; n<nCount; n++)
2452 {
2453 SfxChildWin_Impl*pCW = aChildWins[n].get();
2454 if (pCW && pCW->pWin)
2455 {
2456 // TODO does this really have any meaning ?
2457 if (pCW->pWin->GetWindow())
2458 pCW->pWin->GetWindow()->UpdateSettings(Application::GetSettings());
2459 }
2460 }
2461
2462 ArrangeChildren_Impl();
2463 }
2464
2465 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2466