Version 7.1.7.1, tag libreoffice-7.1.7.1
[LibreOffice.git] / sfx2 / source / appl / workwin.cxx
blob217ae75436bfcd7472848cbd095aeda7e1316da4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <config_features.h>
21 #include <config_feature_desktop.h>
22 #include <comphelper/lok.hxx>
23 #include <comphelper/processfactory.hxx>
24 #include <osl/diagnose.h>
26 #include <sfx2/docfile.hxx>
27 #include <sfx2/objface.hxx>
28 #include <sfx2/objsh.hxx>
29 #include <sfx2/app.hxx>
30 #include <workwin.hxx>
31 #include <sfx2/viewfrm.hxx>
32 #include <sfx2/module.hxx>
33 #include <sfx2/dispatch.hxx>
34 #include <sfx2/dockwin.hxx>
35 #include <sfx2/viewsh.hxx>
36 #include <splitwin.hxx>
37 #include <childwinimpl.hxx>
38 #include <sfx2/sfxsids.hrc>
39 #include <sfx2/toolbarids.hxx>
40 #include <vcl/taskpanelist.hxx>
41 #include <vcl/svapp.hxx>
42 #include <svl/eitem.hxx>
43 #include <tools/svborder.hxx>
44 #include <tools/debug.hxx>
45 #include <unotools/moduleoptions.hxx>
46 #include <com/sun/star/ui/XUIElement.hpp>
47 #include <com/sun/star/frame/LayoutManagerEvents.hpp>
48 #include <com/sun/star/frame/ModuleManager.hpp>
49 #include <com/sun/star/frame/XLayoutManager.hpp>
50 #include <com/sun/star/frame/XLayoutManagerEventBroadcaster.hpp>
51 #include <com/sun/star/beans/XPropertySet.hpp>
52 #include <com/sun/star/lang/DisposedException.hpp>
53 #include <type_traits>
54 #include <unordered_map>
55 #include <sfx2/notebookbar/SfxNotebookBar.hxx>
57 using namespace ::com::sun::star;
58 using namespace ::com::sun::star::uno;
60 namespace {
62 struct ResIdToResName
64 ToolbarId eId;
65 const char* pName;
70 const ResIdToResName pToolBarResToName[] =
72 { ToolbarId::FullScreenToolbox, "fullscreenbar" },
73 { ToolbarId::EnvToolbox, "standardbar", },
74 { ToolbarId::SvxTbx_Form_Navigation, "formsnavigationbar" },
75 { ToolbarId::SvxTbx_Form_Filter, "formsfilterbar" },
76 { ToolbarId::SvxTbx_Text_Control_Attributes, "formtextobjectbar" },
77 { ToolbarId::SvxTbx_Controls, "formcontrols" },
78 { ToolbarId::SvxTbx_FormDesign, "formdesign" },
79 { ToolbarId::Math_Toolbox, "toolbar" }, //math
80 { ToolbarId::Text_Toolbox_Sc, "textobjectbar" }, //calc
81 { ToolbarId::Draw_Objectbar, "drawobjectbar" },
82 { ToolbarId::Graphic_Objectbar, "graphicobjectbar" },
83 { ToolbarId::Objectbar_Format, "formatobjectbar" },
84 { ToolbarId::Objectbar_Preview, "previewbar" },
85 { ToolbarId::Objectbar_Tools, "toolbar" }, //calc
86 { ToolbarId::Bezier_Toolbox_Sd, "bezierobjectbar" }, //draw/impress
87 { ToolbarId::Gluepoints_Toolbox, "gluepointsobjectbar" },
88 { ToolbarId::Draw_Graf_Toolbox, "graphicobjectbar" },
89 { ToolbarId::Draw_Obj_Toolbox, "drawingobjectbar" }, //impress
90 { ToolbarId::Draw_Text_Toolbox_Sd, "textobjectbar" }, //impress
91 { ToolbarId::Draw_Toolbox_Sd, "toolbar" }, //impress
92 { ToolbarId::Draw_Options_Toolbox, "optionsbar" },
93 { ToolbarId::Draw_CommonTask_Toolbox, "commontaskbar" },
94 { ToolbarId::Graphic_Obj_Toolbox, "drawingobjectbar" }, //draw
95 { ToolbarId::Outline_Toolbox, "outlinetoolbar" }, //impress
96 { ToolbarId::Slide_Toolbox, "slideviewtoolbar" },
97 { ToolbarId::Slide_Obj_Toolbox, "slideviewobjectbar" },
98 { ToolbarId::Bezier_Toolbox_Sw, "bezierobjectbar" },
99 { ToolbarId::Draw_Toolbox_Sw, "drawingobjectbar" },
100 { ToolbarId::Draw_Text_Toolbox_Sw, "drawtextobjectbar" },
101 { ToolbarId::Frame_Toolbox, "frameobjectbar" },
102 { ToolbarId::Grafik_Toolbox, "graphicobjectbar" },
103 { ToolbarId::Num_Toolbox, "numobjectbar" },
104 { ToolbarId::Ole_Toolbox, "oleobjectbar" },
105 { ToolbarId::Table_Toolbox, "tableobjectbar" },
106 { ToolbarId::Text_Toolbox_Sw, "textobjectbar" },
107 { ToolbarId::PView_Toolbox, "previewobjectbar" }, //writer
108 { ToolbarId::Webtools_Toolbox, "toolbar" }, //web
109 { ToolbarId::Webtext_Toolbox, "textobjectbar" },
110 { ToolbarId::Tools_Toolbox, "toolbar" }, //writer
111 { ToolbarId::Webframe_Toolbox, "frameobjectbar" }, //web
112 { ToolbarId::Webgraphic_Toolbox, "graphicobjectbar" },
113 { ToolbarId::Webole_Toolbox, "oleobjectbar" },
114 { ToolbarId::Basicide_Objectbar, "macrobar" },
115 { ToolbarId::Svx_Fontwork_Bar, "fontworkobjectbar" }, //global
116 { ToolbarId::Svx_Extrusion_Bar, "extrusionobjectbar" },
117 { ToolbarId::FormLayer_Toolbox, "formsobjectbar" },
118 { ToolbarId::Module_Toolbox, "viewerbar" }, //writer (plugin)
119 { ToolbarId::Objectbar_App, "viewerbar" }, //calc (plugin)
120 { ToolbarId::Draw_Viewer_Toolbox, "viewerbar" }, //impress(plugin)
121 { ToolbarId::Draw_Media_Toolbox, "mediaobjectbar" }, //draw/impress
122 { ToolbarId::Media_Objectbar, "mediaobjectbar" }, //calc
123 { ToolbarId::Media_Toolbox, "mediaobjectbar" }, //writer
124 { ToolbarId::None, "" }
127 // Sort the Children according their alignment
128 // The order corresponds to the enum SfxChildAlignment (->CHILDWIN.HXX).
130 constexpr OUStringLiteral g_aLayoutManagerPropName = u"LayoutManager";
132 // Help to make changes to the alignment compatible!
133 LayoutManagerListener::LayoutManagerListener(
134 SfxWorkWindow* pWrkWin ) :
135 m_bHasFrame( false ),
136 m_pWrkWin( pWrkWin )
140 LayoutManagerListener::~LayoutManagerListener()
144 void LayoutManagerListener::setFrame( const css::uno::Reference< css::frame::XFrame >& xFrame )
146 SolarMutexGuard aGuard;
147 if ( !m_pWrkWin || m_bHasFrame )
148 return;
150 m_xFrame = xFrame;
151 m_bHasFrame = true;
153 if ( !xFrame.is() )
154 return;
156 css::uno::Reference< css::beans::XPropertySet > xPropSet( xFrame, UNO_QUERY );
157 css::uno::Reference< css::frame::XLayoutManagerEventBroadcaster > xLayoutManager;
158 if ( !xPropSet.is() )
159 return;
163 Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
164 aValue >>= xLayoutManager;
166 if ( xLayoutManager.is() )
167 xLayoutManager->addLayoutManagerEventListener(
168 css::uno::Reference< css::frame::XLayoutManagerListener >(
169 static_cast< OWeakObject* >( this ), css::uno::UNO_QUERY ));
171 xPropSet.set( xLayoutManager, UNO_QUERY );
172 if ( xPropSet.is() )
174 aValue = xPropSet->getPropertyValue( "LockCount" );
175 aValue >>= m_pWrkWin->m_nLock;
178 catch ( css::lang::DisposedException& )
181 catch ( const css::uno::RuntimeException& )
183 throw;
185 catch ( css::uno::Exception& )
191 // XComponent
193 void SAL_CALL LayoutManagerListener::addEventListener(
194 const css::uno::Reference< css::lang::XEventListener >& )
196 // do nothing, only internal class
199 void SAL_CALL LayoutManagerListener::removeEventListener(
200 const css::uno::Reference< css::lang::XEventListener >& )
202 // do nothing, only internal class
205 void SAL_CALL LayoutManagerListener::dispose()
207 SolarMutexGuard aGuard;
209 // reset member
210 m_pWrkWin = nullptr;
212 css::uno::Reference< css::frame::XFrame > xFrame( m_xFrame.get(), css::uno::UNO_QUERY );
213 if ( !xFrame.is() )
214 return;
216 m_xFrame.clear();
217 m_bHasFrame = false;
219 css::uno::Reference< css::beans::XPropertySet > xPropSet( xFrame, css::uno::UNO_QUERY );
220 css::uno::Reference< css::frame::XLayoutManagerEventBroadcaster > xLayoutManager;
221 if ( !xPropSet.is() )
222 return;
226 css::uno::Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
227 aValue >>= xLayoutManager;
229 // remove as listener from layout manager
230 if ( xLayoutManager.is() )
231 xLayoutManager->removeLayoutManagerEventListener(
232 css::uno::Reference< css::frame::XLayoutManagerListener >(
233 static_cast< OWeakObject* >( this ), css::uno::UNO_QUERY ));
235 catch ( css::lang::DisposedException& )
238 catch ( const css::uno::RuntimeException& )
240 throw;
242 catch ( css::uno::Exception& )
248 // XEventListener
250 void SAL_CALL LayoutManagerListener::disposing(
251 const css::lang::EventObject& )
253 SolarMutexGuard aGuard;
254 m_pWrkWin = nullptr;
255 m_bHasFrame = false;
256 m_xFrame.clear();
260 // XLayoutManagerEventListener
262 void SAL_CALL LayoutManagerListener::layoutEvent(
263 const css::lang::EventObject&,
264 ::sal_Int16 eLayoutEvent,
265 const css::uno::Any& )
267 SolarMutexGuard aGuard;
268 if ( !m_pWrkWin )
269 return;
271 if ( eLayoutEvent == css::frame::LayoutManagerEvents::VISIBLE )
273 m_pWrkWin->MakeVisible_Impl( true );
274 m_pWrkWin->ShowChildren_Impl();
275 m_pWrkWin->ArrangeChildren_Impl();
277 else if ( eLayoutEvent == css::frame::LayoutManagerEvents::INVISIBLE )
279 m_pWrkWin->MakeVisible_Impl( false );
280 m_pWrkWin->HideChildren_Impl();
281 m_pWrkWin->ArrangeChildren_Impl();
283 else if ( eLayoutEvent == css::frame::LayoutManagerEvents::LOCK )
285 m_pWrkWin->Lock_Impl( true );
287 else if ( eLayoutEvent == css::frame::LayoutManagerEvents::UNLOCK )
289 m_pWrkWin->Lock_Impl( false );
293 namespace
295 struct ToolbarIdHash
297 size_t operator()(ToolbarId t) const
299 typedef std::underlying_type<ToolbarId>::type underlying_type;
300 return std::hash<underlying_type>()(static_cast<underlying_type>(t));
304 class FilledToolBarResIdToResourceURLMap
306 private:
307 typedef std::unordered_map<ToolbarId, OUString, ToolbarIdHash> ToolBarResIdToResourceURLMap;
308 ToolBarResIdToResourceURLMap m_aResIdToResourceURLMap;
309 public:
310 FilledToolBarResIdToResourceURLMap()
312 sal_Int32 nIndex( 0 );
313 while (pToolBarResToName[nIndex].eId != ToolbarId::None)
315 OUString aResourceURL( OUString::createFromAscii( pToolBarResToName[nIndex].pName ));
316 m_aResIdToResourceURLMap.emplace(pToolBarResToName[nIndex].eId, aResourceURL);
317 ++nIndex;
321 OUString findURL(ToolbarId eId) const
323 ToolBarResIdToResourceURLMap::const_iterator aIter = m_aResIdToResourceURLMap.find(eId);
324 if ( aIter != m_aResIdToResourceURLMap.end() )
325 return aIter->second;
326 return OUString();
330 class theFilledToolBarResIdToResourceURLMap
331 : public rtl::Static<FilledToolBarResIdToResourceURLMap,
332 theFilledToolBarResIdToResourceURLMap>
337 static OUString GetResourceURLFromToolbarId(ToolbarId eId)
339 return theFilledToolBarResIdToResourceURLMap::get().findURL(eId);
342 static sal_uInt16 TbxMatch( sal_uInt16 nPos )
344 switch ( nPos )
346 case SFX_OBJECTBAR_APPLICATION :
347 return 0;
348 case SFX_OBJECTBAR_OPTIONS:
349 return 1;
350 case SFX_OBJECTBAR_MACRO:
351 return 2;
352 case SFX_OBJECTBAR_OBJECT:
353 return 3;
354 case SFX_OBJECTBAR_TOOLS:
355 return 4;
356 case SFX_OBJECTBAR_FULLSCREEN:
357 case SFX_OBJECTBAR_COMMONTASK:
358 case SFX_OBJECTBAR_RECORDING:
359 return nPos+1;
360 default:
361 return nPos;
365 static sal_uInt16 ChildAlignValue(SfxChildAlignment eAlign)
367 sal_uInt16 ret = 17;
369 switch (eAlign)
371 case SfxChildAlignment::HIGHESTTOP:
372 ret = 1;
373 break;
374 case SfxChildAlignment::LOWESTBOTTOM:
375 ret = 2;
376 break;
377 case SfxChildAlignment::FIRSTLEFT:
378 ret = 3;
379 break;
380 case SfxChildAlignment::LASTRIGHT:
381 ret = 4;
382 break;
383 case SfxChildAlignment::LEFT:
384 ret = 5;
385 break;
386 case SfxChildAlignment::RIGHT:
387 ret = 6;
388 break;
389 case SfxChildAlignment::FIRSTRIGHT:
390 ret = 7;
391 break;
392 case SfxChildAlignment::LASTLEFT:
393 ret = 8;
394 break;
395 case SfxChildAlignment::TOP:
396 ret = 9;
397 break;
398 case SfxChildAlignment::BOTTOM:
399 ret = 10;
400 break;
401 case SfxChildAlignment::TOOLBOXTOP:
402 ret = 11;
403 break;
404 case SfxChildAlignment::TOOLBOXBOTTOM:
405 ret = 12;
406 break;
407 case SfxChildAlignment::LOWESTTOP:
408 ret = 13;
409 break;
410 case SfxChildAlignment::HIGHESTBOTTOM:
411 ret = 14;
412 break;
413 case SfxChildAlignment::TOOLBOXLEFT:
414 ret = 15;
415 break;
416 case SfxChildAlignment::TOOLBOXRIGHT:
417 ret = 16;
418 break;
419 case SfxChildAlignment::NOALIGNMENT:
420 break; // -Wall not handled...
423 return ret;
426 void SfxWorkWindow::Sort_Impl()
428 aSortedList.clear();
429 for (size_t i = 0; i < aChildren.size(); ++i)
431 SfxChild_Impl *pCli = aChildren[i].get();
432 if (pCli)
434 decltype(aSortedList)::size_type k;
435 for (k=0; k<aSortedList.size(); k++)
436 if (ChildAlignValue( aChildren[aSortedList[k]]->eAlign ) >
437 ChildAlignValue(pCli->eAlign))
438 break;
439 aSortedList.insert( aSortedList.begin() + k, i );
443 bSorted = true;
446 constexpr OUStringLiteral g_aStatusBarResName( u"private:resource/statusbar/statusbar" );
447 constexpr OUStringLiteral g_aTbxTypeName( u"private:resource/toolbar/" );
448 constexpr OUStringLiteral g_aProgressBarResName( u"private:resource/progressbar/progressbar" );
450 // constructor for workwin of a Frame
452 SfxWorkWindow::SfxWorkWindow( vcl::Window *pWin, SfxFrame *pFrm, SfxFrame* pMaster ) :
453 pBindings(&pFrm->GetCurrentViewFrame()->GetBindings()),
454 pWorkWin (pWin),
455 pActiveChild( nullptr ),
456 nUpdateMode(SfxVisibilityFlags::Standard),
457 nChildren( 0 ),
458 nOrigMode( SfxVisibilityFlags::Invisible ),
459 bSorted( true ),
460 bDockingAllowed(true),
461 bInternalDockingAllowed(true),
462 bAllChildrenVisible(true),
463 #if !defined(ANDROID) || HAVE_FEATURE_ANDROID_LOK
464 bIsFullScreen( false ),
465 #else // Fennec-based Android Viewer
466 bIsFullScreen( true ),
467 #endif
468 #if HAVE_FEATURE_DESKTOP
469 bShowStatusBar( true ),
470 #else
471 bShowStatusBar( sal_False ),
472 #endif
473 m_nLock( 0 ),
474 pMasterFrame( pMaster ),
475 pFrame( pFrm )
477 DBG_ASSERT (pBindings, "No Bindings!");
479 pBindings->SetWorkWindow_Impl( std::unique_ptr<SfxWorkWindow>(this) );
481 // For the ObjectBars an integral place in the Childlist is reserved,
482 // so that they always come in a defined order.
483 for (int i=0; i<SFX_OBJECTBAR_MAX; ++i)
484 aChildren.push_back( nullptr );
486 // create and initialize layout manager listener
487 Reference< css::frame::XFrame > xFrame = GetFrameInterface();
488 LayoutManagerListener* pLayoutManagerListener = new LayoutManagerListener( this );
489 m_xLayoutManagerListener.set( static_cast< cppu::OWeakObject* >( pLayoutManagerListener ),
490 css::uno::UNO_QUERY );
491 pLayoutManagerListener->setFrame( xFrame );
493 SfxShell* pConfigShell = pFrm->GetCurrentViewFrame();
494 if ( pConfigShell && pConfigShell->GetObjectShell() )
496 bShowStatusBar = ( !pConfigShell->GetObjectShell()->IsInPlaceActive() );
497 bDockingAllowed = true;
498 bInternalDockingAllowed = true;
501 // The required split windows (one for each side) can be created
502 for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX; n++ )
504 // The SplitWindows excludes direct ChildWindows of the WorkWindows
505 // and receives the docked window.
507 SfxChildAlignment eAlign =
508 ( n == SFX_SPLITWINDOWS_LEFT ? SfxChildAlignment::LEFT :
509 n == SFX_SPLITWINDOWS_RIGHT ? SfxChildAlignment::RIGHT :
510 n == SFX_SPLITWINDOWS_TOP ? SfxChildAlignment::TOP :
511 SfxChildAlignment::BOTTOM );
512 VclPtr<SfxSplitWindow> pSplitWin = VclPtr<SfxSplitWindow>::Create(pWorkWin, eAlign, this, true );
513 pSplit[n] = pSplitWin;
516 nOrigMode = SfxVisibilityFlags::Standard;
517 nUpdateMode = SfxVisibilityFlags::Standard;
521 // Destructor
523 SfxWorkWindow::~SfxWorkWindow()
526 // Delete SplitWindows
527 for (VclPtr<SfxSplitWindow> & p : pSplit)
529 if (p->GetWindowCount())
530 ReleaseChild_Impl(*p);
531 p.disposeAndClear();
534 // Delete help structure for Child-Windows
535 DBG_ASSERT( aChildren.empty(), "dangling children" );
537 if ( m_xLayoutManagerListener.is() )
538 m_xLayoutManagerListener->dispose();
541 void SfxWorkWindow::Lock_Impl( bool bLock )
543 if ( bLock )
544 m_nLock++;
545 else
546 --m_nLock;
547 if ( m_nLock<0 )
549 OSL_FAIL("Lock count underflow!");
550 assert(m_nLock >= 0);
551 m_nLock = 0;
554 if ( !m_nLock )
555 ArrangeChildren_Impl();
559 // Helper method to release the child lists. Should the destructor not be
560 // called after this, instead work continues, then space for the object bars
561 // and split windows has to be reserved in the same way as in the constructor
562 // of SfxWorkWindow.
564 void SfxWorkWindow::DeleteControllers_Impl()
567 // Lock SplitWindows (which means suppressing the Resize-Reaction of the
568 // DockingWindows)
569 for (size_t n=0; n<SFX_SPLITWINDOWS_MAX; n++ )
571 VclPtr<SfxSplitWindow> const &p = pSplit[n];
572 if (p->GetWindowCount())
573 p->Lock();
576 // Delete Child-Windows
577 while(!aChildWins.empty())
579 std::unique_ptr<SfxChildWin_Impl> pCW = std::move(*aChildWins.begin());
580 aChildWins.erase(aChildWins.begin());
581 SfxChildWindow *pChild = pCW->pWin;
582 if (pChild)
584 if (comphelper::LibreOfficeKit::isActive())
586 vcl::Window* pWindow = pChild->GetWindow();
587 if (pWindow)
589 pWindow->ReleaseLOKNotifier();
592 pChild->Hide();
594 // If the child window is a direct child window and not in a
595 // SplitWindow, cancel it at the workwindow.
596 // After TH a cancellation on the SplitWindow is not necessary
597 // since this window is also destroyed (see below).
598 if (pCW->pCli)
600 if (pChild->GetController())
601 ReleaseChild_Impl(*pChild->GetController());
602 else
603 ReleaseChild_Impl(*pChild->GetWindow());
606 pCW->pWin = nullptr;
607 pWorkWin->GetSystemWindow()->GetTaskPaneList()->RemoveWindow( pChild->GetWindow() );
608 pChild->Destroy();
611 // ATTENTION: The array itself is cleared after this loop!!
612 // Therefore we have to set every array entry to zero as it could be
613 // accessed by calling pChild->Destroy().
614 // Window::NotifyAllChildren() calls SfxWorkWindow::DataChanged_Impl for
615 // 8-bit displays (WM_QUERYPALETTECHANGED message due to focus change)!!
618 Reference< css::frame::XFrame > xFrame = GetFrameInterface();
619 Reference< css::beans::XPropertySet > xPropSet( xFrame, UNO_QUERY );
620 Reference< css::frame::XLayoutManager > xLayoutManager;
621 if ( xPropSet.is() )
625 Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
626 aValue >>= xLayoutManager;
628 catch ( Exception& )
633 if ( xLayoutManager.is() )
635 xLayoutManager->reset();
637 // Delete StatusBar
638 ResetStatusBar_Impl();
640 // Delete ObjectBars (this is done last, so that aChildren does not
641 // receive dead Pointers)
642 for (SfxObjectBar_Impl & i : aObjBarList)
644 // Not every position must be occupied
645 ToolbarId eId = i.eId;
646 if (eId != ToolbarId::None)
647 i.eId = ToolbarId::None;
651 // ObjectBars are all released at once, since they occupy a
652 // fixed contiguous area in the array pChild
653 aChildren.clear();
654 bSorted = false;
656 nChildren = 0;
660 // for placing the child window.
662 void SfxWorkWindow::ArrangeChildren_Impl( bool bForce )
664 if ( pFrame->IsClosing_Impl() || ( m_nLock && !bForce ))
665 return;
667 SfxInPlaceClient *pClient = nullptr;
668 SfxViewFrame *pF = pFrame->GetCurrentViewFrame();
669 if ( pF && pF->GetViewShell() )
670 pClient = pF->GetViewShell()->GetIPClient();
672 if ( pClient )
673 return;
675 aClientArea = GetTopRect_Impl();
676 if ( aClientArea.IsEmpty() )
677 return;
679 SvBorder aBorder;
680 if ( nChildren && IsVisible_Impl() )
681 aBorder = Arrange_Impl();
682 // If the current application document contains an IPClient, then the
683 // object through SetTopToolFramePixel has to be assigned the available
684 // space. The object will then point to its UITools and sets the app border
685 // (-> SfxInPlaceEnv_Impl:: ArrangeChildren_Impl ()). Otherwise the
686 // app border is set here directly to possibly overwrite the Border that
687 // was set by an object from another document. The object does not set
688 // the SetAppBorder when it removes its UI tools so that no-dithering
689 // ObjectBar arises.
690 // (->SfxInPlaceEnv_Impl::ArrangeChildren_Impl())
692 pMasterFrame->SetToolSpaceBorderPixel_Impl( aBorder );
694 ArrangeAutoHideWindows( nullptr );
697 void SfxWorkWindow::FlushPendingChildSizes()
699 // tdf#116865, if any windows are being resized, i.e. their
700 // resize timer is active, then calling GetSizePixel on
701 // them forces the timer to fire and sets the final
702 // size to which they are getting resized towards.
703 for (size_t i = 0; i < aChildren.size(); ++i)
705 SfxChild_Impl *pCli = aChildren[i].get();
706 if (!pCli || !pCli->pWin)
707 continue;
708 (void)pCli->pWin->GetSizePixel();
712 SvBorder SfxWorkWindow::Arrange_Impl()
714 /* [Description]
716 This method organizes all visible child windows so that the docked window
717 sorted in order from the outside to the inside are placed after one
718 another. If a visible window does not fit anymore into the free
719 ClientArea, it is set to "not visible".
722 //tdf#116865 trigger pending sizing timers now so we arrange
723 //with the final size of the client area.
725 //Otherwise calling GetSizePixel in the following loop will trigger the
726 //timers, causing reentry into Arrange_Impl again where the inner
727 //Arrange_Impl arranges with the final size, and then returns to this outer
728 //Arrange_Impl which would rearrange with the old client area size
729 FlushPendingChildSizes();
730 aClientArea = GetTopRect_Impl();
731 aUpperClientArea = aClientArea;
733 SvBorder aBorder;
734 if ( !nChildren )
735 return aBorder;
737 if (!bSorted)
738 Sort_Impl();
740 Point aPos;
741 Size aSize;
742 tools::Rectangle aTmp( aClientArea );
744 for (sal_uInt16 n : aSortedList)
746 SfxChild_Impl* pCli = aChildren[n].get();
747 if ( !pCli->pWin )
748 continue;
750 // First, we assume that there is room for the window.
751 pCli->nVisible |= SfxChildVisibility::FITS_IN;
753 // Skip invisible windows
754 if (pCli->nVisible != SfxChildVisibility::VISIBLE)
755 continue;
757 if ( pCli->bResize )
758 aSize = pCli->aSize;
759 else
760 aSize = pCli->pWin->GetSizePixel();
762 SvBorder aTemp = aBorder;
763 bool bAllowHiding = true;
764 switch ( pCli->eAlign )
766 case SfxChildAlignment::HIGHESTTOP:
767 case SfxChildAlignment::TOP:
768 case SfxChildAlignment::TOOLBOXTOP:
769 case SfxChildAlignment::LOWESTTOP:
770 aSize.setWidth( aTmp.GetWidth() );
771 if ( pCli->pWin->GetType() == WindowType::SPLITWINDOW )
772 aSize = static_cast<SplitWindow *>(pCli->pWin.get())->CalcLayoutSizePixel( aSize );
773 bAllowHiding = false;
774 aBorder.Top() += aSize.Height();
775 aPos = aTmp.TopLeft();
776 aTmp.AdjustTop(aSize.Height() );
777 if ( pCli->eAlign == SfxChildAlignment::HIGHESTTOP )
778 aUpperClientArea.AdjustTop(aSize.Height() );
779 break;
781 case SfxChildAlignment::LOWESTBOTTOM:
782 case SfxChildAlignment::BOTTOM:
783 case SfxChildAlignment::TOOLBOXBOTTOM:
784 case SfxChildAlignment::HIGHESTBOTTOM:
785 aSize.setWidth( aTmp.GetWidth() );
786 if ( pCli->pWin->GetType() == WindowType::SPLITWINDOW )
787 aSize = static_cast<SplitWindow *>(pCli->pWin.get())->CalcLayoutSizePixel( aSize );
788 aBorder.Bottom() += aSize.Height();
789 aPos = aTmp.BottomLeft();
790 aPos.AdjustY( -(aSize.Height()-1) );
791 aTmp.AdjustBottom( -(aSize.Height()) );
792 if ( pCli->eAlign == SfxChildAlignment::LOWESTBOTTOM )
793 aUpperClientArea.AdjustBottom( -(aSize.Height()) );
794 break;
796 case SfxChildAlignment::FIRSTLEFT:
797 case SfxChildAlignment::LEFT:
798 case SfxChildAlignment::LASTLEFT:
799 case SfxChildAlignment::TOOLBOXLEFT:
800 aSize.setHeight( aTmp.GetHeight() );
801 if ( pCli->pWin->GetType() == WindowType::SPLITWINDOW )
802 aSize = static_cast<SplitWindow *>(pCli->pWin.get())->CalcLayoutSizePixel( aSize );
803 bAllowHiding = false;
804 aBorder.Left() += aSize.Width();
805 aPos = aTmp.TopLeft();
806 aTmp.AdjustLeft(aSize.Width() );
807 if ( pCli->eAlign != SfxChildAlignment::TOOLBOXLEFT )
808 aUpperClientArea.AdjustLeft(aSize.Width() );
809 break;
811 case SfxChildAlignment::FIRSTRIGHT:
812 case SfxChildAlignment::RIGHT:
813 case SfxChildAlignment::LASTRIGHT:
814 case SfxChildAlignment::TOOLBOXRIGHT:
815 aSize.setHeight( aTmp.GetHeight() );
816 if ( pCli->pWin->GetType() == WindowType::SPLITWINDOW )
817 aSize = static_cast<SplitWindow *>(pCli->pWin.get())->CalcLayoutSizePixel( aSize );
818 aBorder.Right() += aSize.Width();
819 aPos = aTmp.TopRight();
820 aPos.AdjustX( -(aSize.Width()-1) );
821 aTmp.AdjustRight( -(aSize.Width()) );
822 if ( pCli->eAlign != SfxChildAlignment::TOOLBOXRIGHT )
823 aUpperClientArea.AdjustRight( -(aSize.Width()) );
824 break;
826 default:
827 pCli->aSize = pCli->pWin->GetSizePixel();
828 pCli->bResize = false;
829 continue;
832 pCli->pWin->SetPosSizePixel( aPos, aSize );
833 pCli->bResize = false;
834 pCli->aSize = aSize;
835 if( bAllowHiding && !RequestTopToolSpacePixel_Impl( aBorder ) )
837 pCli->nVisible ^= SfxChildVisibility::FITS_IN;
838 aBorder = aTemp;
842 if ( aClientArea.GetWidth() >= aBorder.Left() + aBorder.Right() )
844 aClientArea.AdjustLeft(aBorder.Left() );
845 aClientArea.AdjustRight( -(aBorder.Right()) );
847 else
849 aBorder.Left() = aClientArea.Left();
850 aBorder.Right() = aClientArea.Right();
851 aClientArea.SetRight( aTmp.Left() );
852 aClientArea.SetLeft( aTmp.Left() );
855 if ( aClientArea.GetHeight() >= aBorder.Top() + aBorder.Bottom() )
857 aClientArea.AdjustTop(aBorder.Top() );
858 aClientArea.AdjustBottom( -(aBorder.Bottom()) );
860 else
862 aBorder.Top() = aClientArea.Top();
863 aBorder.Bottom() = aClientArea.Bottom();
864 aClientArea.SetTop(aTmp.Top());
865 aClientArea.SetBottom(aTmp.Top());
868 return IsDockingAllowed() ? aBorder : SvBorder();
871 bool SfxWorkWindow::PrepareClose_Impl()
873 for (const std::unique_ptr<SfxChildWin_Impl> &pCW : aChildWins)
875 SfxChildWindow *pChild = pCW->pWin;
876 if ( pChild && !pChild->QueryClose() )
877 return false;
880 return true;
883 SfxChild_Impl* SfxWorkWindow::RegisterChild_Impl( vcl::Window& rWindow,
884 SfxChildAlignment eAlign )
886 DBG_ASSERT( aChildren.size() < 255, "too many children" );
887 DBG_ASSERT( SfxChildAlignValid(eAlign), "invalid align" );
888 DBG_ASSERT( !FindChild_Impl(&rWindow), "child registered more than once" );
891 if ( rWindow.GetParent() != pWorkWin )
892 rWindow.SetParent( pWorkWin );
894 auto pChild = std::make_unique<SfxChild_Impl>(rWindow, rWindow.GetSizePixel(),
895 eAlign, rWindow.IsVisible());
897 aChildren.push_back(std::move(pChild));
898 bSorted = false;
899 nChildren++;
900 return aChildren.back().get();
903 SfxChild_Impl* SfxWorkWindow::RegisterChild_Impl(std::shared_ptr<SfxDialogController>& rController,
904 SfxChildAlignment eAlign )
906 DBG_ASSERT( aChildren.size() < 255, "too many children" );
907 DBG_ASSERT( SfxChildAlignValid(eAlign), "invalid align" );
909 auto pChild = std::make_unique<SfxChild_Impl>(rController, eAlign);
911 aChildren.push_back(std::move(pChild));
912 bSorted = false;
913 nChildren++;
914 return aChildren.back().get();
917 void SfxWorkWindow::ReleaseChild_Impl( vcl::Window& rWindow )
920 SfxChild_Impl *pChild = nullptr;
921 decltype(aChildren)::size_type nPos;
922 for ( nPos = 0; nPos < aChildren.size(); ++nPos )
924 pChild = aChildren[nPos].get();
925 if ( pChild && pChild->pWin == &rWindow )
927 bSorted = false;
928 nChildren--;
929 aChildren.erase(aChildren.begin() + nPos);
930 return;
933 OSL_FAIL( "releasing unregistered child" );
936 void SfxWorkWindow::ReleaseChild_Impl(SfxDialogController& rController)
939 SfxChild_Impl *pChild = nullptr;
940 decltype(aChildren)::size_type nPos;
941 for ( nPos = 0; nPos < aChildren.size(); ++nPos )
943 pChild = aChildren[nPos].get();
944 if (pChild && pChild->xController.get() == &rController)
946 bSorted = false;
947 nChildren--;
948 aChildren.erase(aChildren.begin() + nPos);
949 return;
952 OSL_FAIL( "releasing unregistered child" );
955 SfxChild_Impl* SfxWorkWindow::FindChild_Impl( const vcl::Window* rWindow ) const
958 sal_uInt16 nCount = aChildren.size();
959 for ( sal_uInt16 nPos = 0; nPos < nCount; ++nPos )
961 SfxChild_Impl *pChild = aChildren[nPos].get();
962 if ( pChild && pChild->pWin == rWindow )
963 return pChild;
966 return nullptr;
969 void SfxWorkWindow::ShowChildren_Impl()
971 bool bInvisible = ( !IsVisible_Impl() || ( !pWorkWin->IsReallyVisible() && !pWorkWin->IsReallyShown() ));
973 for (std::unique_ptr<SfxChild_Impl>& pCli : aChildren)
975 if (!pCli)
976 continue;
977 SfxChildWin_Impl* pCW = nullptr;
978 if (pCli->pWin || pCli->xController)
980 // We have to find the SfxChildWin_Impl to retrieve the
981 // SFX_CHILDWIN flags that can influence visibility.
982 for (const std::unique_ptr<SfxChildWin_Impl>& pCWin : aChildWins)
984 SfxChild_Impl* pChild = pCWin->pCli;
985 if ( pChild == pCli.get() )
987 pCW = pCWin.get();
988 break;
992 bool bVisible( !bInvisible );
993 if ( pCW )
995 // Check flag SFX_CHILDWIN_NEVERHIDE that forces us to show
996 // the child window even in situations where no child window is
997 // visible.
998 SfxChildWindowFlags nFlags = pCW->aInfo.nFlags;
999 bVisible = !bInvisible || ( nFlags & SfxChildWindowFlags::NEVERHIDE );
1002 if ( SfxChildVisibility::VISIBLE == (pCli->nVisible & SfxChildVisibility::VISIBLE) && bVisible )
1004 ShowFlags nFlags = pCli->bSetFocus ? ShowFlags::NONE : ShowFlags::NoFocusChange | ShowFlags::NoActivate;
1005 if (pCli->xController)
1007 if (!pCli->xController->getDialog()->get_visible())
1009 auto xController = pCli->xController;
1010 weld::DialogController::runAsync(xController,
1011 [=](sal_Int32 /*nResult*/){ xController->Close(); });
1014 else
1015 pCli->pWin->Show(true, nFlags);
1016 pCli->bSetFocus = false;
1018 else
1020 if (pCli->xController)
1022 if (pCli->xController->getDialog()->get_visible())
1023 pCli->xController->response(RET_CLOSE);
1025 else
1026 pCli->pWin->Hide();
1033 void SfxWorkWindow::HideChildren_Impl()
1035 for ( sal_uInt16 nPos = aChildren.size(); nPos > 0; --nPos )
1037 SfxChild_Impl *pChild = aChildren[nPos-1].get();
1038 if (!pChild)
1039 continue;
1040 if (pChild->xController)
1041 pChild->xController->response(RET_CLOSE);
1042 else if (pChild->pWin)
1043 pChild->pWin->Hide();
1047 void SfxWorkWindow::ResetObjectBars_Impl()
1049 for ( auto & n: aObjBarList )
1050 n.bDestroy = true;
1052 for ( auto & n: aChildWins )
1053 n->nId = 0;
1056 void SfxWorkWindow::SetObjectBar_Impl(sal_uInt16 nPos, SfxVisibilityFlags nFlags, ToolbarId eId)
1058 DBG_ASSERT( nPos < SFX_OBJECTBAR_MAX, "object bar position overflow" );
1060 SfxObjectBar_Impl aObjBar;
1061 aObjBar.eId = eId;
1062 aObjBar.nMode = nFlags;
1064 for (SfxObjectBar_Impl & rBar : aObjBarList)
1066 if ( rBar.eId == aObjBar.eId )
1068 rBar = aObjBar;
1069 return;
1073 aObjBarList.push_back( aObjBar );
1076 bool SfxWorkWindow::IsVisible_Impl( SfxVisibilityFlags nMode ) const
1078 switch( nUpdateMode )
1080 case SfxVisibilityFlags::Standard:
1081 return true;
1082 case SfxVisibilityFlags::Invisible:
1083 return false;
1084 case SfxVisibilityFlags::Client:
1085 case SfxVisibilityFlags::Server:
1086 return bool(nMode & nUpdateMode);
1087 default:
1088 return (nMode & nOrigMode ) ||
1089 nOrigMode == SfxVisibilityFlags::Standard;
1093 void SfxWorkWindow::UpdateObjectBars_Impl()
1095 if ( pFrame->IsClosing_Impl() )
1096 return;
1098 UpdateObjectBars_Impl2();
1101 ArrangeChildren_Impl( false );
1103 ShowChildren_Impl();
1106 ShowChildren_Impl();
1109 Reference< css::task::XStatusIndicator > SfxWorkWindow::GetStatusIndicator()
1111 Reference< css::beans::XPropertySet > xPropSet( GetFrameInterface(), UNO_QUERY );
1112 Reference< css::frame::XLayoutManager > xLayoutManager;
1113 Reference< css::task::XStatusIndicator > xStatusIndicator;
1115 if ( xPropSet.is() )
1117 Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
1118 aValue >>= xLayoutManager;
1119 if ( xLayoutManager.is() )
1121 xLayoutManager->createElement( g_aProgressBarResName );
1122 xLayoutManager->showElement( g_aProgressBarResName );
1124 Reference< css::ui::XUIElement > xProgressBar =
1125 xLayoutManager->getElement( g_aProgressBarResName );
1126 if ( xProgressBar.is() )
1128 xStatusIndicator.set( xProgressBar->getRealInterface(), UNO_QUERY );
1133 return xStatusIndicator;
1137 bool SfxWorkWindow::IsPluginMode( SfxObjectShell const * pObjShell )
1139 if ( pObjShell && pObjShell->GetMedium() )
1141 const SfxBoolItem* pViewOnlyItem = SfxItemSet::GetItem<SfxBoolItem>(pObjShell->GetMedium()->GetItemSet(), SID_VIEWONLY, false);
1142 if ( pViewOnlyItem && pViewOnlyItem->GetValue() )
1143 return true;
1146 return false;
1150 css::uno::Reference< css::frame::XFrame > SfxWorkWindow::GetFrameInterface()
1152 css::uno::Reference< css::frame::XFrame > xFrame;
1154 SfxDispatcher* pDispatcher( GetBindings().GetDispatcher() );
1155 if ( pDispatcher )
1157 SfxViewFrame* pViewFrame = pDispatcher->GetFrame();
1158 if ( pViewFrame )
1159 xFrame = pViewFrame->GetFrame().GetFrameInterface();
1162 return xFrame;
1166 void SfxWorkWindow::UpdateObjectBars_Impl2()
1168 // Lock SplitWindows (which means suppressing the Resize-Reaction of the
1169 // DockingWindows)
1170 for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX; n++ )
1172 VclPtr<SfxSplitWindow> const & p = pSplit[n];
1173 if (p->GetWindowCount())
1174 p->Lock();
1177 Reference< css::beans::XPropertySet > xPropSet( GetFrameInterface(), UNO_QUERY );
1178 Reference< css::frame::XLayoutManager > xLayoutManager;
1180 if ( xPropSet.is() )
1182 Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
1183 aValue >>= xLayoutManager;
1186 if ( !xLayoutManager.is() )
1187 return;
1189 bool bPluginMode( false );
1190 SfxDispatcher* pDispatcher( GetBindings().GetDispatcher() );
1192 if ( pDispatcher )
1194 SfxViewFrame* pViewFrame = pDispatcher->GetFrame();
1195 if ( pViewFrame )
1196 bPluginMode = IsPluginMode( pViewFrame->GetObjectShell() );
1199 // Iterate over all Toolboxes
1200 xLayoutManager->lock();
1201 for ( auto const & n: aObjBarList )
1203 ToolbarId eId = n.eId;
1204 bool bDestroy = n.bDestroy;
1206 // Determine the valid mode for the ToolBox
1207 SfxVisibilityFlags nTbxMode = n.nMode;
1208 bool bFullScreenTbx( nTbxMode & SfxVisibilityFlags::FullScreen );
1209 nTbxMode &= ~SfxVisibilityFlags::FullScreen;
1210 nTbxMode &= ~SfxVisibilityFlags::Viewer;
1212 // Is a ToolBox required in this context ?
1213 bool bModesMatching = (nUpdateMode != SfxVisibilityFlags::Invisible) && ((nTbxMode & nUpdateMode) == nUpdateMode);
1214 if ( bDestroy || sfx2::SfxNotebookBar::IsActive())
1216 OUString aTbxId = g_aTbxTypeName + GetResourceURLFromToolbarId(eId);
1217 xLayoutManager->destroyElement( aTbxId );
1219 else if ( eId != ToolbarId::None && ( ( bModesMatching && !bIsFullScreen ) ||
1220 ( bIsFullScreen && bFullScreenTbx ) ) )
1222 OUString aTbxId = g_aTbxTypeName + GetResourceURLFromToolbarId(eId);
1223 if ( !IsDockingAllowed() && !xLayoutManager->isElementFloating( aTbxId ))
1224 xLayoutManager->destroyElement( aTbxId );
1225 else
1227 xLayoutManager->requestElement( aTbxId );
1228 if ( bPluginMode )
1229 xLayoutManager->lockWindow( aTbxId );
1232 else if ( eId != ToolbarId::None )
1234 // Delete the Toolbox at this Position if possible
1235 OUString aTbxId = g_aTbxTypeName + GetResourceURLFromToolbarId(eId);
1236 xLayoutManager->destroyElement( aTbxId );
1240 UpdateStatusBar_Impl();
1242 // unlocking automatically forces Layout
1243 xLayoutManager->unlock();
1245 UpdateChildWindows_Impl();
1247 // Unlock the SplitWindows again
1248 for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX; n++ )
1250 VclPtr<SfxSplitWindow> const & p = pSplit[n];
1251 if (p->GetWindowCount())
1252 p->Lock(false);
1256 void SfxWorkWindow::UpdateChildWindows_Impl()
1258 // tdf#100870, tdf#101320: don't use range-based for loop when
1259 // container is modified
1260 for ( size_t n=0; n<aChildWins.size(); n++ )
1262 // any current or in the context available Childwindows
1263 SfxChildWin_Impl *pCW = aChildWins[n].get();
1264 SfxChildWindow *pChildWin = pCW->pWin;
1265 bool bCreate = false;
1266 if ( pCW->nId && (pCW->aInfo.nFlags & SfxChildWindowFlags::ALWAYSAVAILABLE || IsVisible_Impl( pCW->nVisibility ) ) )
1268 // In the context is an appropriate ChildWindow allowed;
1269 // it is also turned on?
1270 if ( pChildWin == nullptr && pCW->bCreate )
1272 // Internal docking is only used for embedding into another
1273 // container. We force the floating state of all floatable
1274 // child windows.
1275 if ( !bInternalDockingAllowed )
1277 // Special case for all non-floatable child windows. We have
1278 // to prevent the creation here!
1279 bCreate = !( pCW->aInfo.nFlags & SfxChildWindowFlags::FORCEDOCK );
1281 else if ( !IsDockingAllowed() || bIsFullScreen ) // || !bInternalDocking )
1283 // In Presentation mode or FullScreen only FloatingWindows
1284 SfxChildAlignment eAlign;
1285 if ( pCW->aInfo.GetExtraData_Impl( &eAlign ) )
1286 bCreate = ( eAlign == SfxChildAlignment::NOALIGNMENT );
1288 else
1289 bCreate = true;
1291 if (pCW->aInfo.nFlags & SfxChildWindowFlags::NEVERCLONE)
1292 pCW->bCreate = bCreate = false; // Don't create and remember that we haven't created.
1294 // Currently, no window here, but it is enabled; windows
1295 // Create window and if possible theContext
1296 if ( bCreate )
1297 CreateChildWin_Impl( pCW, false );
1299 if ( !bAllChildrenVisible && pCW->pCli )
1300 pCW->pCli->nVisible &= ~SfxChildVisibility::ACTIVE;
1302 else if ( pChildWin )
1304 // Window already exists, it should also be visible?
1305 if ( ( !bIsFullScreen || pChildWin->GetAlignment() == SfxChildAlignment::NOALIGNMENT ) && bAllChildrenVisible )
1307 // Update Mode is compatible; definitely enable it
1308 bCreate = true;
1309 if ( pCW->pCli )
1311 // The window is a direct Child
1312 if ((IsDockingAllowed() && bInternalDockingAllowed)
1313 || pCW->pCli->eAlign == SfxChildAlignment::NOALIGNMENT)
1314 pCW->pCli->nVisible |= SfxChildVisibility::NOT_HIDDEN;
1316 else
1318 if ( pCW->bCreate && IsDockingAllowed() && bInternalDockingAllowed )
1319 // The window ia within a SplitWindow
1320 static_cast<SfxDockingWindow*>(pChildWin->GetWindow())->Reappear_Impl();
1323 if ( pCW->nInterfaceId != pChildWin->GetContextId() )
1324 pChildWin->CreateContext( pCW->nInterfaceId, GetBindings() );
1329 if ( pChildWin && !bCreate )
1331 if ( !pChildWin->QueryClose() || pChildWin->IsHideNotDelete() || Application::IsUICaptured() )
1333 if ( pCW->pCli )
1335 if ( pCW->pCli->nVisible & SfxChildVisibility::NOT_HIDDEN )
1336 pCW->pCli->nVisible ^= SfxChildVisibility::NOT_HIDDEN;
1338 else
1339 static_cast<SfxDockingWindow*>(pChildWin->GetWindow())->Disappear_Impl();
1341 else
1342 RemoveChildWin_Impl( pCW );
1347 void SfxWorkWindow::CreateChildWin_Impl( SfxChildWin_Impl *pCW, bool bSetFocus )
1349 pCW->aInfo.bVisible = true;
1351 SfxChildWindow *pChildWin = SfxChildWindow::CreateChildWindow( pCW->nId, pWorkWin, &GetBindings(), pCW->aInfo).release();
1352 if (!pChildWin)
1353 return;
1355 if ( bSetFocus )
1356 bSetFocus = pChildWin->WantsFocus();
1357 pChildWin->SetWorkWindow_Impl( this );
1359 // At least the extra string is changed during the evaluation,
1360 // also get it anewed
1361 SfxChildWinInfo aInfo = pChildWin->GetInfo();
1362 pCW->aInfo.aExtraString = aInfo.aExtraString;
1363 pCW->aInfo.bVisible = aInfo.bVisible;
1364 pCW->aInfo.nFlags |= aInfo.nFlags;
1366 // The creation was successful
1367 GetBindings().Invalidate(pCW->nId);
1369 sal_uInt16 nPos = pChildWin->GetPosition();
1370 if (nPos != CHILDWIN_NOPOS)
1372 DBG_ASSERT(nPos < SFX_OBJECTBAR_MAX, "Illegal objectbar position!");
1373 if ( aChildren[TbxMatch(nPos)] )// &&
1375 // ChildWindow replaces ObjectBar
1376 aChildren[TbxMatch(nPos)]->nVisible ^= SfxChildVisibility::NOT_HIDDEN;
1380 // make childwin keyboard accessible
1381 pWorkWin->GetSystemWindow()->GetTaskPaneList()->AddWindow( pChildWin->GetWindow() );
1383 pCW->pWin = pChildWin;
1385 if ( pChildWin->GetAlignment() == SfxChildAlignment::NOALIGNMENT || pChildWin->GetWindow()->GetParent() == pWorkWin)
1387 // The window is not docked or docked outside of one split windows
1388 // and must therefore be registered explicitly as a Child
1389 if (pChildWin->GetController())
1390 pCW->pCli = RegisterChild_Impl(pChildWin->GetController(), pChildWin->GetAlignment());
1391 else
1392 pCW->pCli = RegisterChild_Impl(*(pChildWin->GetWindow()), pChildWin->GetAlignment());
1393 pCW->pCli->nVisible = SfxChildVisibility::VISIBLE;
1394 if ( pChildWin->GetAlignment() != SfxChildAlignment::NOALIGNMENT && bIsFullScreen )
1395 pCW->pCli->nVisible ^= SfxChildVisibility::ACTIVE;
1396 pCW->pCli->bSetFocus = bSetFocus;
1398 else
1400 // A docked window which parent is not a WorkingWindow, must lie
1401 // in a SplitWindow and thus not be explicitly registered.
1402 // This happens already in the initialization of SfxDockingWindows!
1405 if ( pCW->nInterfaceId != pChildWin->GetContextId() )
1406 pChildWin->CreateContext( pCW->nInterfaceId, GetBindings() );
1408 // Save the information in the INI file
1409 SaveStatus_Impl(pChildWin, pCW->aInfo);
1412 void SfxWorkWindow::RemoveChildWin_Impl( SfxChildWin_Impl *pCW )
1414 sal_uInt16 nId = pCW->nSaveId;
1415 SfxChildWindow *pChildWin = pCW->pWin;
1417 // Save the information in the INI file
1418 SfxChildWindowFlags nFlags = pCW->aInfo.nFlags;
1419 pCW->aInfo = pChildWin->GetInfo();
1420 pCW->aInfo.nFlags |= nFlags;
1421 SaveStatus_Impl(pChildWin, pCW->aInfo);
1423 pChildWin->Hide();
1425 if ( pCW->pCli )
1427 // Child window is a direct child window and must therefore unregister
1428 // itself from the WorkWindow
1429 pCW->pCli = nullptr;
1430 if (pChildWin->GetController())
1431 ReleaseChild_Impl(*pChildWin->GetController());
1432 else
1433 ReleaseChild_Impl(*pChildWin->GetWindow());
1435 else
1437 // ChildWindow is within a SplitWindow and unregister itself in
1438 // the destructor.
1441 pWorkWin->GetSystemWindow()->GetTaskPaneList()->RemoveWindow( pChildWin->GetWindow() );
1442 pCW->pWin = nullptr;
1443 pChildWin->Destroy();
1445 GetBindings().Invalidate( nId );
1448 void SfxWorkWindow::ResetStatusBar_Impl()
1450 aStatBar.eId = StatusBarId::None;
1453 void SfxWorkWindow::SetStatusBar_Impl(StatusBarId eId)
1455 if (eId != StatusBarId::None && bShowStatusBar && IsVisible_Impl())
1456 aStatBar.eId = eId;
1459 void SfxWorkWindow::UpdateStatusBar_Impl()
1461 Reference< css::beans::XPropertySet > xPropSet( GetFrameInterface(), UNO_QUERY );
1462 Reference< css::frame::XLayoutManager > xLayoutManager;
1464 Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
1465 aValue >>= xLayoutManager;
1467 // No status bar, if no ID is required or when in FullScreenView or
1468 // if disabled
1469 if (aStatBar.eId != StatusBarId::None && IsDockingAllowed() && bInternalDockingAllowed && bShowStatusBar &&
1470 !bIsFullScreen)
1472 // Id has changed, thus create a suitable Statusbarmanager, this takes
1473 // over the current status bar;
1474 if ( xLayoutManager.is() )
1475 xLayoutManager->requestElement( g_aStatusBarResName );
1477 else
1479 // Destroy the current StatusBar
1480 // The Manager only creates the Status bar, does not destroy it.
1481 if ( xLayoutManager.is() )
1482 xLayoutManager->destroyElement( g_aStatusBarResName );
1486 void SfxWorkWindow::MakeVisible_Impl( bool bVis )
1488 if ( bVis )
1489 nOrigMode = SfxVisibilityFlags::Standard;
1490 else
1491 nOrigMode = SfxVisibilityFlags::Invisible;
1493 if ( nOrigMode != nUpdateMode)
1494 nUpdateMode = nOrigMode;
1497 bool SfxWorkWindow::IsVisible_Impl() const
1499 return nOrigMode != SfxVisibilityFlags::Invisible;
1503 void SfxWorkWindow::HidePopups_Impl(bool bHide, sal_uInt16 nId )
1505 if (comphelper::LibreOfficeKit::isActive() && bHide)
1506 return;
1508 for (const std::unique_ptr<SfxChildWin_Impl>& i : aChildWins)
1510 SfxChildWindow *pCW = i->pWin;
1511 if (pCW && pCW->GetAlignment() == SfxChildAlignment::NOALIGNMENT && pCW->GetType() != nId)
1513 vcl::Window *pWin = pCW->GetWindow();
1514 SfxChild_Impl *pChild = FindChild_Impl(pWin);
1515 if (!pChild)
1517 SAL_WARN("sfx.appl", "missing SfxChild_Impl child!");
1518 continue;
1520 if (bHide)
1522 pChild->nVisible &= ~SfxChildVisibility::ACTIVE;
1523 pCW->Hide();
1525 else if ( !comphelper::LibreOfficeKit::isActive() ||
1526 SfxChildVisibility::ACTIVE != (pChild->nVisible & SfxChildVisibility::ACTIVE) )
1528 pChild->nVisible |= SfxChildVisibility::ACTIVE;
1529 if ( SfxChildVisibility::VISIBLE == (pChild->nVisible & SfxChildVisibility::VISIBLE) )
1530 pCW->Show( ShowFlags::NoFocusChange | ShowFlags::NoActivate );
1537 void SfxWorkWindow::ConfigChild_Impl(SfxChildIdentifier eChild,
1538 SfxDockingConfig eConfig, sal_uInt16 nId)
1540 SfxDockingWindow* pDockWin=nullptr;
1541 sal_uInt16 nPos = USHRT_MAX;
1542 vcl::Window *pWin=nullptr;
1543 SfxChildWin_Impl *pCW = nullptr;
1545 // configure direct childwindow
1546 for (const std::unique_ptr<SfxChildWin_Impl>& i : aChildWins)
1548 pCW = i.get();
1549 SfxChildWindow *pChild = pCW->pWin;
1550 if ( pChild && (pChild->GetType() == nId ))
1552 if (SfxDockingWindow* pSfxDockingWindow = dynamic_cast<SfxDockingWindow*>(pChild->GetWindow()))
1554 // it's a DockingWindow
1555 pDockWin = pSfxDockingWindow;
1557 else
1559 // FloatingWindow or ModelessDialog
1560 pWin = pChild->GetWindow();
1562 break;
1566 if ( pDockWin )
1568 if ( eChild == SfxChildIdentifier::DOCKINGWINDOW || pDockWin->GetAlignment() == SfxChildAlignment::NOALIGNMENT )
1570 if ( eChild == SfxChildIdentifier::SPLITWINDOW && eConfig == SfxDockingConfig::TOGGLEFLOATMODE)
1572 // DockingWindow was dragged out of a SplitWindow
1573 pCW->pCli = RegisterChild_Impl(*pDockWin, pDockWin->GetAlignment());
1574 pCW->pCli->nVisible = SfxChildVisibility::VISIBLE;
1577 pWin = pDockWin;
1579 else
1581 SfxSplitWindow *pSplitWin = GetSplitWindow_Impl(pDockWin->GetAlignment());
1583 // configure DockingWindow inside a SplitWindow
1584 if ( eConfig == SfxDockingConfig::TOGGLEFLOATMODE)
1586 // DockingWindow was dragged into a SplitWindow
1587 pCW->pCli = nullptr;
1588 ReleaseChild_Impl(*pDockWin);
1591 pWin = pSplitWin->GetSplitWindow();
1592 if ( pSplitWin->GetWindowCount() == 1 )
1593 static_cast<SplitWindow*>(pWin)->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
1597 DBG_ASSERT( pCW, "Unknown window!" );
1599 if ( !bSorted )
1600 // windows may have been registered and released without an update until now
1601 Sort_Impl();
1603 decltype(aSortedList)::size_type n;
1604 for ( n=0; n<aSortedList.size(); ++n )
1606 SfxChild_Impl *pChild = aChildren[aSortedList[n]].get();
1607 if ( pChild && pChild->pWin == pWin )
1608 break;
1611 if ( n < aSortedList.size() )
1612 // sometimes called while toggling float mode
1613 nPos = aSortedList[n];
1615 switch ( eConfig )
1617 case SfxDockingConfig::SETDOCKINGRECTS :
1619 if (nPos == USHRT_MAX || !pDockWin)
1620 return;
1622 tools::Rectangle aOuterRect( GetTopRect_Impl() );
1623 aOuterRect.SetPos( pWorkWin->OutputToScreenPixel( aOuterRect.TopLeft() ));
1624 tools::Rectangle aInnerRect( aOuterRect );
1626 // The current affected window is included in the calculation of
1627 // the inner rectangle!
1628 for (sal_uInt16 i : aSortedList)
1630 SfxChild_Impl* pCli = aChildren[i].get();
1632 if ( pCli && pCli->nVisible == SfxChildVisibility::VISIBLE && pCli->pWin )
1634 switch ( pCli->eAlign )
1636 case SfxChildAlignment::TOP:
1637 // Object-Toolboxes come always last
1638 aInnerRect.AdjustTop(pCli->aSize.Height() );
1639 break;
1641 case SfxChildAlignment::HIGHESTTOP:
1642 // Always performed first
1643 aInnerRect.AdjustTop(pCli->aSize.Height() );
1644 break;
1646 case SfxChildAlignment::LOWESTTOP:
1647 // Is only counted if it is the current window
1648 if ( i == nPos )
1649 aInnerRect.AdjustTop(pCli->aSize.Height() );
1650 break;
1652 case SfxChildAlignment::BOTTOM:
1653 // Object-Toolboxes come always last
1654 aInnerRect.AdjustBottom( -(pCli->aSize.Height()) );
1655 break;
1657 case SfxChildAlignment::LOWESTBOTTOM:
1658 // Always performed first
1659 aInnerRect.AdjustBottom( -(pCli->aSize.Height()) );
1660 break;
1662 case SfxChildAlignment::HIGHESTBOTTOM:
1663 // Is only counted if it is the current window
1664 if ( i == nPos )
1665 aInnerRect.AdjustBottom( -(pCli->aSize.Height()) );
1666 break;
1668 case SfxChildAlignment::LEFT:
1669 // Toolboxes come always last
1670 aInnerRect.AdjustLeft(pCli->aSize.Width() );
1671 break;
1673 case SfxChildAlignment::FIRSTLEFT:
1674 // Always performed first
1675 aInnerRect.AdjustLeft(pCli->aSize.Width() );
1676 break;
1678 case SfxChildAlignment::LASTLEFT:
1679 // Is only counted if it is the current window
1680 if (i == nPos)
1681 aInnerRect.AdjustLeft(pCli->aSize.Width() );
1682 break;
1684 case SfxChildAlignment::RIGHT:
1685 // Toolboxes come always last
1686 aInnerRect.AdjustRight( -(pCli->aSize.Width()) );
1687 break;
1689 case SfxChildAlignment::FIRSTRIGHT:
1690 // Is only counted if it is the current window
1691 if (i == nPos)
1692 aInnerRect.AdjustRight( -(pCli->aSize.Width()) );
1693 break;
1695 case SfxChildAlignment::LASTRIGHT:
1696 // Always performed first
1697 aInnerRect.AdjustRight( -(pCli->aSize.Width()) );
1698 break;
1700 default:
1701 break;
1706 pDockWin->SetDockingRects(aOuterRect, aInnerRect);
1707 break;
1710 case SfxDockingConfig::ALIGNDOCKINGWINDOW :
1711 case SfxDockingConfig::TOGGLEFLOATMODE:
1713 if ( nPos == USHRT_MAX && !pCW )
1714 return;
1716 SfxChildAlignment eAlign = SfxChildAlignment::NOALIGNMENT;
1717 SfxChild_Impl *pCli = ( nPos != USHRT_MAX ) ? aChildren[nPos].get() : nullptr;
1718 if ( pCli && pDockWin )
1720 eAlign = pDockWin->GetAlignment();
1721 if ( eChild == SfxChildIdentifier::DOCKINGWINDOW || eAlign == SfxChildAlignment::NOALIGNMENT)
1723 // configuration inside the SplitWindow, no change for the SplitWindows' configuration
1724 pCli->bResize = true;
1725 pCli->aSize = pDockWin->GetSizePixel();
1729 if ( pCli )
1731 if( pCli->eAlign != eAlign )
1733 bSorted = false;
1734 pCli->eAlign = eAlign;
1737 ArrangeChildren_Impl();
1738 ShowChildren_Impl();
1741 if ( pCW && pCW->pWin )
1743 // store changed configuration
1744 SfxChildWindowFlags nFlags = pCW->aInfo.nFlags;
1745 pCW->aInfo = pCW->pWin->GetInfo();
1746 pCW->aInfo.nFlags |= nFlags;
1747 SaveStatus_Impl( pCW->pWin, pCW->aInfo);
1750 break;
1756 void SfxWorkWindow::SetChildWindowVisible_Impl( sal_uInt32 lId, bool bEnabled, SfxVisibilityFlags nMode )
1758 sal_uInt16 nInter = static_cast<sal_uInt16>( lId >> 16 );
1759 sal_uInt16 nId = static_cast<sal_uInt16>( lId & 0xFFFF );
1761 SfxChildWin_Impl *pCW=nullptr;
1763 if ( !pCW )
1765 // If no Parent or the Parent us still unknown, then search here
1766 sal_uInt16 nCount = aChildWins.size();
1767 for (sal_uInt16 n=0; n<nCount; n++)
1768 if (aChildWins[n]->nSaveId == nId)
1770 pCW = aChildWins[n].get();
1771 break;
1775 if ( !pCW )
1777 // If new, then initialize, add this here depending on the flag or
1778 // the Parent
1779 pCW = new SfxChildWin_Impl( lId );
1780 pCW->nId = nId;
1781 InitializeChild_Impl( pCW );
1782 aChildWins.push_back( std::unique_ptr<SfxChildWin_Impl>(pCW) );
1785 pCW->nId = nId;
1786 if ( nInter )
1787 pCW->nInterfaceId = nInter;
1788 pCW->nVisibility = nMode;
1789 pCW->bEnable = bEnabled;
1793 // The on/off status of a ChildWindow is switched
1795 void SfxWorkWindow::ToggleChildWindow_Impl(sal_uInt16 nId, bool bSetFocus)
1797 sal_uInt16 nCount = aChildWins.size();
1798 sal_uInt16 n;
1799 for (n=0; n<nCount; n++)
1800 if (aChildWins[n]->nId == nId)
1801 break;
1803 if ( n<nCount )
1805 // The Window is already known
1806 SfxChildWin_Impl *pCW = aChildWins[n].get();
1807 SfxChildWindow *pChild = pCW->pWin;
1809 bool bCreationAllowed( true );
1810 if ( !bInternalDockingAllowed )
1812 // Special case for all non-floatable child windows. We have
1813 // to prevent the creation here!
1814 bCreationAllowed = !( pCW->aInfo.nFlags & SfxChildWindowFlags::FORCEDOCK );
1817 if ( bCreationAllowed )
1819 if ( pCW->bCreate )
1821 if ( pChild )
1823 if ( pChild->QueryClose() )
1825 pCW->bCreate = false;
1826 // The Window should be switched off
1827 pChild->SetVisible_Impl( false );
1828 RemoveChildWin_Impl( pCW );
1831 else
1833 // no actual Window exists, yet => just remember the "switched off" state
1834 pCW->bCreate = false;
1837 else
1839 pCW->bCreate = true;
1840 if ( pChild )
1842 ShowChildWindow_Impl( nId, true, bSetFocus );
1844 else
1846 // create actual Window
1847 CreateChildWin_Impl( pCW, bSetFocus );
1848 if ( !pCW->pWin )
1849 // no success
1850 pCW->bCreate = false;
1855 ArrangeChildren_Impl();
1856 ShowChildren_Impl();
1858 if ( pCW->bCreate && bCreationAllowed )
1860 if ( !pCW->pCli )
1862 SfxDockingWindow *pDock =
1863 static_cast<SfxDockingWindow*>( pCW->pWin->GetWindow() );
1864 if ( pDock->IsAutoHide_Impl() )
1865 pDock->AutoShow_Impl();
1869 return;
1872 #ifdef DBG_UTIL
1873 nCount = aChildWins.size();
1874 for (n=0; n<nCount; n++)
1875 if (aChildWins[n]->nSaveId == nId)
1876 break;
1878 if ( n < nCount )
1880 OSL_FAIL("The ChildWindow is not in context!");
1882 else
1884 OSL_FAIL("The ChildWindow is not registered!");
1886 #endif
1890 bool SfxWorkWindow::HasChildWindow_Impl(sal_uInt16 nId)
1892 sal_uInt16 nCount = aChildWins.size();
1893 sal_uInt16 n;
1894 for (n=0; n<nCount; n++)
1895 if (aChildWins[n]->nSaveId == nId)
1896 break;
1898 if (n<nCount)
1900 SfxChildWin_Impl *pCW = aChildWins[n].get();
1901 SfxChildWindow *pChild = pCW->pWin;
1902 return ( pChild && pCW->bCreate );
1905 return false;
1908 bool SfxWorkWindow::IsFloating( sal_uInt16 nId )
1910 SfxChildWin_Impl *pCW=nullptr;
1912 if ( !pCW )
1914 // If no Parent or the Parent us still unknown, then search here
1915 sal_uInt16 nCount = aChildWins.size();
1916 for (sal_uInt16 n=0; n<nCount; n++)
1917 if (aChildWins[n]->nSaveId == nId)
1919 pCW = aChildWins[n].get();
1920 break;
1924 if ( !pCW )
1926 // If new, then initialize, add this here depending on the flag or
1927 // the Parent
1928 pCW = new SfxChildWin_Impl( nId );
1929 pCW->bEnable = false;
1930 pCW->nId = 0;
1931 pCW->nVisibility = SfxVisibilityFlags::Invisible;
1932 InitializeChild_Impl( pCW );
1933 aChildWins.push_back( std::unique_ptr<SfxChildWin_Impl>(pCW) );
1936 SfxChildAlignment eAlign;
1937 if ( pCW->aInfo.GetExtraData_Impl( &eAlign ) )
1938 return( eAlign == SfxChildAlignment::NOALIGNMENT );
1939 else
1940 return true;
1944 bool SfxWorkWindow::KnowsChildWindow_Impl(sal_uInt16 nId)
1946 SfxChildWin_Impl *pCW=nullptr;
1947 sal_uInt16 nCount = aChildWins.size();
1948 sal_uInt16 n;
1949 for (n=0; n<nCount; n++)
1951 pCW = aChildWins[n].get();
1952 if ( pCW->nSaveId == nId)
1953 break;
1956 if (n<nCount)
1958 if ( !(pCW->aInfo.nFlags & SfxChildWindowFlags::ALWAYSAVAILABLE) && !IsVisible_Impl( pCW->nVisibility ) )
1959 return false;
1960 return pCW->bEnable;
1962 else
1963 return false;
1967 void SfxWorkWindow::SetChildWindow_Impl(sal_uInt16 nId, bool bOn, bool bSetFocus)
1969 SfxChildWin_Impl *pCW=nullptr;
1970 SfxWorkWindow *pWork = nullptr;
1972 if ( !pCW )
1974 // If no Parent or the Parent us still unknown, then search here
1975 sal_uInt16 nCount = aChildWins.size();
1976 for (sal_uInt16 n=0; n<nCount; n++)
1977 if (aChildWins[n]->nSaveId == nId)
1979 pCW = aChildWins[n].get();
1980 pWork = this;
1981 break;
1985 if ( !pCW )
1987 // If new, then initialize, add this here depending on the flag or
1988 // the Parent
1989 pCW = new SfxChildWin_Impl( nId );
1990 InitializeChild_Impl( pCW );
1991 if ( !pWork || pCW->aInfo.nFlags & SfxChildWindowFlags::TASK )
1992 pWork = this;
1993 pWork->aChildWins.push_back( std::unique_ptr<SfxChildWin_Impl>(pCW) );
1996 if ( pCW->bCreate != bOn )
1997 pWork->ToggleChildWindow_Impl(nId,bSetFocus);
2001 void SfxWorkWindow::ShowChildWindow_Impl(sal_uInt16 nId, bool bVisible, bool bSetFocus)
2003 sal_uInt16 nCount = aChildWins.size();
2004 SfxChildWin_Impl* pCW=nullptr;
2005 sal_uInt16 n;
2006 for (n=0; n<nCount; n++)
2008 pCW = aChildWins[n].get();
2009 if (pCW->nId == nId)
2010 break;
2013 if ( n<nCount )
2015 SfxChildWindow *pChildWin = pCW->pWin;
2016 if ( pChildWin )
2018 if ( bVisible )
2020 if ( pCW->pCli )
2022 pCW->pCli->bSetFocus = bSetFocus;
2023 pCW->pCli->nVisible = SfxChildVisibility::VISIBLE;
2024 pChildWin->Show( bSetFocus && pChildWin->WantsFocus() ? ShowFlags::NONE : ShowFlags::NoFocusChange | ShowFlags::NoActivate );
2026 else
2027 static_cast<SfxDockingWindow*>(pChildWin->GetWindow())->Reappear_Impl();
2030 else
2032 if ( pCW->pCli )
2034 pCW->pCli->nVisible = SfxChildVisibility::VISIBLE ^ SfxChildVisibility::NOT_HIDDEN;
2035 pCW->pWin->Hide();
2037 else
2038 static_cast<SfxDockingWindow*>(pChildWin->GetWindow())->Disappear_Impl();
2042 ArrangeChildren_Impl();
2043 ShowChildren_Impl();
2045 else if ( bVisible )
2047 SetChildWindow_Impl( nId, true, bSetFocus );
2048 pChildWin = pCW->pWin;
2051 if ( pChildWin )
2053 pChildWin->SetVisible_Impl( bVisible );
2054 SfxChildWindowFlags nFlags = pCW->aInfo.nFlags;
2055 pCW->aInfo = pChildWin->GetInfo();
2056 pCW->aInfo.nFlags |= nFlags;
2057 if ( !pCW->bCreate )
2058 SaveStatus_Impl( pChildWin, pCW->aInfo );
2061 return;
2064 #ifdef DBG_UTIL
2065 nCount = aChildWins.size();
2066 for (n=0; n<nCount; n++)
2067 if (aChildWins[n]->nSaveId == nId)
2068 break;
2070 if ( n<nCount )
2072 OSL_FAIL("The ChildWindow is not in context!");
2074 else
2076 OSL_FAIL("The ChildWindow is not registered");
2078 #endif
2082 SfxChildWindow* SfxWorkWindow::GetChildWindow_Impl(sal_uInt16 nId)
2084 sal_uInt16 nCount = aChildWins.size();
2085 sal_uInt16 n;
2086 for (n=0; n<nCount; n++)
2087 if (aChildWins[n]->nSaveId == nId)
2088 break;
2090 if (n<nCount)
2091 return aChildWins[n]->pWin;
2092 return nullptr;
2096 void SfxWorkWindow::ResetChildWindows_Impl()
2098 for (std::unique_ptr<SfxChildWin_Impl>& pChildWin : aChildWins)
2100 pChildWin->nId = 0;
2101 pChildWin->bEnable = false;
2105 // returns the size of the area (client area) of the
2106 // parent windows, in which the ChildWindow can be fitted.
2108 tools::Rectangle SfxWorkWindow::GetTopRect_Impl() const
2110 return pMasterFrame->GetTopOuterRectPixel_Impl();
2114 // Virtual method to find out if there is room for a ChildWindow in the
2115 // client area of the parent.
2117 bool SfxWorkWindow::RequestTopToolSpacePixel_Impl( SvBorder aBorder )
2119 return !(!IsDockingAllowed() ||
2120 aClientArea.GetWidth() < aBorder.Left() + aBorder.Right() ||
2121 aClientArea.GetHeight() < aBorder.Top() + aBorder.Bottom());
2124 void SfxWorkWindow::SaveStatus_Impl(SfxChildWindow *pChild, const SfxChildWinInfo &rInfo)
2126 // The Status of the Presentation mode is not saved
2127 if ( IsDockingAllowed() && bInternalDockingAllowed )
2128 pChild->SaveStatus(rInfo);
2131 void SfxWorkWindow::InitializeChild_Impl(SfxChildWin_Impl *pCW)
2133 SfxDispatcher *pDisp = pBindings->GetDispatcher_Impl();
2134 SfxViewFrame *pViewFrame = pDisp ? pDisp->GetFrame() :nullptr;
2135 SfxModule *pMod = pViewFrame ? SfxModule::GetActiveModule(pViewFrame) :nullptr;
2137 OUString sModule;
2138 if (pViewFrame)
2142 uno::Reference< frame::XModuleManager2 > xModuleManager(
2143 frame::ModuleManager::create(::comphelper::getProcessComponentContext()));
2144 sModule = xModuleManager->identify(pViewFrame->GetFrame().GetFrameInterface());
2145 SvtModuleOptions::EFactory eFac = SvtModuleOptions::ClassifyFactoryByServiceName(sModule);
2146 sModule = SvtModuleOptions::GetFactoryShortName(eFac);
2148 catch (...)
2153 SfxChildWinFactory* pFact=nullptr;
2154 SfxApplication *pApp = SfxGetpApp();
2156 SfxChildWinFactArr_Impl &rFactories = pApp->GetChildWinFactories_Impl();
2157 for ( size_t nFactory = 0; nFactory < rFactories.size(); ++nFactory )
2159 pFact = &rFactories[nFactory];
2160 if ( pFact->nId == pCW->nSaveId )
2162 pCW->aInfo = pFact->aInfo;
2163 pCW->aInfo.aModule = sModule;
2164 SfxChildWindow::InitializeChildWinFactory_Impl(
2165 pCW->nSaveId, pCW->aInfo);
2166 pCW->bCreate = pCW->aInfo.bVisible;
2167 SfxChildWindowFlags nFlags = pFact->aInfo.nFlags;
2168 if ( nFlags & SfxChildWindowFlags::TASK )
2169 pCW->aInfo.nFlags |= SfxChildWindowFlags::TASK;
2170 if ( nFlags & SfxChildWindowFlags::CANTGETFOCUS )
2171 pCW->aInfo.nFlags |= SfxChildWindowFlags::CANTGETFOCUS;
2172 if ( nFlags & SfxChildWindowFlags::FORCEDOCK )
2173 pCW->aInfo.nFlags |= SfxChildWindowFlags::FORCEDOCK;
2174 pFact->aInfo = pCW->aInfo;
2175 return;
2180 if ( !pMod )
2181 return;
2183 SfxChildWinFactArr_Impl *pFactories = pMod->GetChildWinFactories_Impl();
2184 if ( !pFactories )
2185 return;
2187 SfxChildWinFactArr_Impl &rFactories = *pFactories;
2188 for ( size_t nFactory = 0; nFactory < rFactories.size(); ++nFactory )
2190 pFact = &rFactories[nFactory];
2191 if ( pFact->nId == pCW->nSaveId )
2193 pCW->aInfo = pFact->aInfo;
2194 pCW->aInfo.aModule = sModule;
2195 SfxChildWindow::InitializeChildWinFactory_Impl(
2196 pCW->nSaveId, pCW->aInfo);
2197 pCW->bCreate = pCW->aInfo.bVisible;
2198 SfxChildWindowFlags nFlags = pFact->aInfo.nFlags;
2199 if ( nFlags & SfxChildWindowFlags::TASK )
2200 pCW->aInfo.nFlags |= SfxChildWindowFlags::TASK;
2201 if ( nFlags & SfxChildWindowFlags::CANTGETFOCUS )
2202 pCW->aInfo.nFlags |= SfxChildWindowFlags::CANTGETFOCUS;
2203 if ( nFlags & SfxChildWindowFlags::FORCEDOCK )
2204 pCW->aInfo.nFlags |= SfxChildWindowFlags::FORCEDOCK;
2205 if ( nFlags & SfxChildWindowFlags::ALWAYSAVAILABLE )
2206 pCW->aInfo.nFlags |= SfxChildWindowFlags::ALWAYSAVAILABLE;
2207 pFact->aInfo = pCW->aInfo;
2208 return;
2213 SfxSplitWindow* SfxWorkWindow::GetSplitWindow_Impl( SfxChildAlignment eAlign )
2215 switch ( eAlign )
2217 case SfxChildAlignment::TOP:
2218 return pSplit[2];
2220 case SfxChildAlignment::BOTTOM:
2221 return pSplit[3];
2223 case SfxChildAlignment::LEFT:
2224 return pSplit[0];
2226 case SfxChildAlignment::RIGHT:
2227 return pSplit[1];
2229 default:
2230 return nullptr;
2234 void SfxWorkWindow::MakeChildrenVisible_Impl( bool bVis )
2236 bAllChildrenVisible = bVis;
2237 if ( bVis )
2239 if ( !bSorted )
2240 Sort_Impl();
2241 for (sal_uInt16 n : aSortedList)
2243 SfxChild_Impl* pCli = aChildren[n].get();
2244 if ( (pCli->eAlign == SfxChildAlignment::NOALIGNMENT) || (IsDockingAllowed() && bInternalDockingAllowed) )
2245 pCli->nVisible |= SfxChildVisibility::ACTIVE;
2248 else
2250 if ( !bSorted )
2251 Sort_Impl();
2252 for (sal_uInt16 n : aSortedList)
2254 SfxChild_Impl* pCli = aChildren[n].get();
2255 pCli->nVisible &= ~SfxChildVisibility::ACTIVE;
2260 bool SfxWorkWindow::IsAutoHideMode( const SfxSplitWindow *pSplitWin )
2262 for (const VclPtr<SfxSplitWindow> & pWin : pSplit)
2264 if ( pWin.get() != pSplitWin && pWin->IsAutoHide( true ) )
2265 return true;
2267 return false;
2271 void SfxWorkWindow::EndAutoShow_Impl( Point aPos )
2273 for (VclPtr<SfxSplitWindow> & p : pSplit)
2275 if ( p && p->IsAutoHide(false) )
2277 Point aLocalPos = p->ScreenToOutputPixel( aPos );
2278 tools::Rectangle aRect( Point(), p->GetSizePixel() );
2279 if ( !aRect.IsInside( aLocalPos ) )
2280 p->FadeOut();
2285 void SfxWorkWindow::ArrangeAutoHideWindows( SfxSplitWindow *pActSplitWin )
2287 if ( m_nLock )
2288 return;
2290 tools::Rectangle aArea( aUpperClientArea );
2291 for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX; n++ )
2293 // Either dummy window or window in the auto-show-mode are processed
2294 // (not pinned, FadeIn).
2295 // Only the abandoned window may be invisible, because perhaps its
2296 // size is just being calculated before it is displayed.
2297 VclPtr<SfxSplitWindow> const & pSplitWin = pSplit[n];
2298 bool bDummyWindow = !pSplitWin->IsFadeIn();
2299 vcl::Window *pDummy = pSplitWin->GetSplitWindow();
2300 vcl::Window *pWin = bDummyWindow ? pDummy : pSplitWin;
2301 if ( (pSplitWin->IsPinned() && !bDummyWindow) || (!pWin->IsVisible() && pActSplitWin != pSplitWin) )
2302 continue;
2304 // Width and position of the dummy window as a starting point
2305 Size aSize = pDummy->GetSizePixel();
2306 Point aPos = pDummy->GetPosPixel();
2308 switch ( n )
2310 case 0 :
2312 // Left SplitWindow
2313 // Get the width of the Window yourself, if no DummyWindow
2314 if ( !bDummyWindow )
2315 aSize.setWidth( pSplitWin->GetSizePixel().Width() );
2317 // If a Window is visible to the left, then the free region
2318 // starts to the right from it, for example at the Client area
2319 tools::Long nLeft = aPos.X() + aSize.Width();
2320 if ( nLeft > aArea.Left() )
2321 aArea.SetLeft( nLeft );
2322 break;
2324 case 1 :
2326 // Right SplitWindow
2327 // Position to correct the difference of the widths
2328 aPos.AdjustX(aSize.Width() );
2330 // Get the width of the Window yourself, if no DummyWindow
2331 if ( !bDummyWindow )
2332 aSize.setWidth( pSplitWin->GetSizePixel().Width() );
2334 aPos.AdjustX( -(aSize.Width()) );
2336 // If already a window is opened at the left side, then the
2337 // right is not allowed to overlap this one.
2338 if ( aPos.X() < aArea.Left() )
2340 aPos.setX( aArea.Left() );
2341 aSize.setWidth( aArea.GetWidth() );
2344 // If a Window is visible to the right, then the free region
2345 // starts to the left from it, for example at the Client area
2346 tools::Long nRight = aPos.X();
2347 if ( !aArea.IsWidthEmpty() && nRight < aArea.Right() )
2348 aArea.SetRight( nRight );
2349 break;
2351 case 2 :
2353 // Top SplitWindow
2354 // Get the height of the Window yourself, if no DummyWindow
2355 if ( !bDummyWindow )
2356 aSize.setHeight( pSplitWin->GetSizePixel().Height() );
2359 // Adjust width with regard to if a Window is already open
2360 // to the left or right
2361 aPos.setX( aArea.Left() );
2362 aSize.setWidth( aArea.GetWidth() );
2364 // If a Window is visible at the top, then the free region
2365 // starts beneath it, for example at the Client area
2366 tools::Long nTop = aPos.Y() + aSize.Height();
2367 if ( nTop > aArea.Top() )
2368 aArea.SetTop( nTop );
2369 break;
2371 case 3 :
2373 // The bottom SplitWindow
2374 // Position to correct the difference of the heights
2375 aPos.AdjustY(aSize.Height() );
2377 // Get the height of the Window yourself, if no DummyWindow
2378 if ( !bDummyWindow )
2379 aSize.setHeight( pSplitWin->GetSizePixel().Height() );
2381 aPos.AdjustY( -(aSize.Height()) );
2383 // Adjust width with regard to if a Window is already open
2384 // to the left or right.
2385 aPos.setX( aArea.Left() );
2386 aSize.setWidth( aArea.GetWidth() );
2388 // If already a window is opened at the top, then the
2389 // bottom one is not allowed to overlap this one.
2390 if ( aPos.Y() < aArea.Top() )
2392 aPos.setY( aArea.Top() );
2393 aSize.setHeight( aArea.GetHeight() );
2396 break;
2400 if ( !bDummyWindow )
2401 // the FadeIn-Window is a Floating window, which coordinates are
2402 // set in Screen coordinates.
2403 pSplitWin->SetPosSizePixel( pWorkWin->OutputToScreenPixel(aPos), aSize );
2404 else
2405 // the docked DummyWindow
2406 pDummy->SetPosSizePixel( aPos, aSize );
2410 tools::Rectangle SfxWorkWindow::GetFreeArea( bool bAutoHide ) const
2412 if ( bAutoHide )
2414 tools::Rectangle aArea( aClientArea );
2415 for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX; n++ )
2417 if ( pSplit[n]->IsPinned() || !pSplit[n]->IsVisible() )
2418 continue;
2420 Size aSize = pSplit[n]->GetSizePixel();
2421 switch ( n )
2423 case 0 :
2424 aArea.AdjustLeft(aSize.Width() );
2425 break;
2426 case 1 :
2427 aArea.AdjustRight( -(aSize.Width()) );
2428 break;
2429 case 2 :
2430 aArea.AdjustTop(aSize.Height() );
2431 break;
2432 case 3 :
2433 aArea.AdjustBottom( -(aSize.Height()) );
2434 break;
2438 return aArea;
2440 else
2441 return aClientArea;
2444 void SfxWorkWindow::SetActiveChild_Impl( vcl::Window *pChild )
2446 pActiveChild = pChild;
2449 void SfxWorkWindow::DataChanged_Impl()
2451 ArrangeChildren_Impl();
2454 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */