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