LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / sfx2 / source / appl / workwin.cxx
blob4e44acf04908ceef6ec361cc72d0b800a0eb142a
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 <sfx2/sfxsids.hrc>
38 #include <sfx2/toolbarids.hxx>
39 #include <vcl/taskpanelist.hxx>
40 #include <vcl/svapp.hxx>
41 #include <svl/eitem.hxx>
42 #include <tools/svborder.hxx>
43 #include <tools/debug.hxx>
44 #include <unotools/moduleoptions.hxx>
45 #include <com/sun/star/ui/XUIElement.hpp>
46 #include <com/sun/star/frame/LayoutManagerEvents.hpp>
47 #include <com/sun/star/frame/ModuleManager.hpp>
48 #include <com/sun/star/frame/XLayoutManager.hpp>
49 #include <com/sun/star/frame/XLayoutManagerEventBroadcaster.hpp>
50 #include <com/sun/star/beans/XPropertySet.hpp>
51 #include <com/sun/star/lang/DisposedException.hpp>
52 #include <type_traits>
53 #include <unordered_map>
54 #include <sfx2/notebookbar/SfxNotebookBar.hxx>
56 using namespace ::com::sun::star;
57 using namespace ::com::sun::star::uno;
59 namespace {
61 struct ResIdToResName
63 ToolbarId eId;
64 const char* pName;
69 const ResIdToResName pToolBarResToName[] =
71 { ToolbarId::FullScreenToolbox, "fullscreenbar" },
72 { ToolbarId::EnvToolbox, "standardbar", },
73 { ToolbarId::SvxTbx_Form_Navigation, "formsnavigationbar" },
74 { ToolbarId::SvxTbx_Form_Filter, "formsfilterbar" },
75 { ToolbarId::SvxTbx_Text_Control_Attributes, "formtextobjectbar" },
76 { ToolbarId::SvxTbx_Controls, "formcontrols" },
77 { ToolbarId::SvxTbx_FormDesign, "formdesign" },
78 { ToolbarId::Math_Toolbox, "toolbar" }, //math
79 { ToolbarId::Text_Toolbox_Sc, "textobjectbar" }, //calc
80 { ToolbarId::Draw_Objectbar, "drawobjectbar" },
81 { ToolbarId::Graphic_Objectbar, "graphicobjectbar" },
82 { ToolbarId::Objectbar_Format, "formatobjectbar" },
83 { ToolbarId::Objectbar_Preview, "previewbar" },
84 { ToolbarId::Objectbar_Tools, "toolbar" }, //calc
85 { ToolbarId::Bezier_Toolbox_Sd, "bezierobjectbar" }, //draw/impress
86 { ToolbarId::Gluepoints_Toolbox, "gluepointsobjectbar" },
87 { ToolbarId::Draw_Graf_Toolbox, "graphicobjectbar" },
88 { ToolbarId::Draw_Obj_Toolbox, "drawingobjectbar" }, //impress
89 { ToolbarId::Draw_Text_Toolbox_Sd, "textobjectbar" }, //impress
90 { ToolbarId::Draw_Toolbox_Sd, "toolbar" }, //impress
91 { ToolbarId::Draw_Options_Toolbox, "optionsbar" },
92 { ToolbarId::Draw_CommonTask_Toolbox, "commontaskbar" },
93 { ToolbarId::Graphic_Obj_Toolbox, "drawingobjectbar" }, //draw
94 { ToolbarId::Outline_Toolbox, "outlinetoolbar" }, //impress
95 { ToolbarId::Slide_Toolbox, "slideviewtoolbar" },
96 { ToolbarId::Slide_Obj_Toolbox, "slideviewobjectbar" },
97 { ToolbarId::Bezier_Toolbox_Sw, "bezierobjectbar" },
98 { ToolbarId::Draw_Toolbox_Sw, "drawingobjectbar" },
99 { ToolbarId::Draw_Text_Toolbox_Sw, "drawtextobjectbar" },
100 { ToolbarId::Frame_Toolbox, "frameobjectbar" },
101 { ToolbarId::Grafik_Toolbox, "graphicobjectbar" },
102 { ToolbarId::Num_Toolbox, "numobjectbar" },
103 { ToolbarId::Ole_Toolbox, "oleobjectbar" },
104 { ToolbarId::Table_Toolbox, "tableobjectbar" },
105 { ToolbarId::Text_Toolbox_Sw, "textobjectbar" },
106 { ToolbarId::PView_Toolbox, "previewobjectbar" }, //writer
107 { ToolbarId::Webtools_Toolbox, "toolbar" }, //web
108 { ToolbarId::Webtext_Toolbox, "textobjectbar" },
109 { ToolbarId::Tools_Toolbox, "toolbar" }, //writer
110 { ToolbarId::Webframe_Toolbox, "frameobjectbar" }, //web
111 { ToolbarId::Webgraphic_Toolbox, "graphicobjectbar" },
112 { ToolbarId::Webole_Toolbox, "oleobjectbar" },
113 { ToolbarId::Basicide_Objectbar, "macrobar" },
114 { ToolbarId::Svx_Fontwork_Bar, "fontworkobjectbar" }, //global
115 { ToolbarId::Svx_Extrusion_Bar, "extrusionobjectbar" },
116 { ToolbarId::FormLayer_Toolbox, "formsobjectbar" },
117 { ToolbarId::Module_Toolbox, "viewerbar" }, //writer (plugin)
118 { ToolbarId::Objectbar_App, "viewerbar" }, //calc (plugin)
119 { ToolbarId::Draw_Viewer_Toolbox, "viewerbar" }, //impress(plugin)
120 { ToolbarId::Draw_Media_Toolbox, "mediaobjectbar" }, //draw/impress
121 { ToolbarId::Media_Objectbar, "mediaobjectbar" }, //calc
122 { ToolbarId::Media_Toolbox, "mediaobjectbar" }, //writer
123 { ToolbarId::None, "" }
126 // Sort the Children according their alignment
127 // The order corresponds to the enum SfxChildAlignment (->CHILDWIN.HXX).
129 constexpr OUStringLiteral g_aLayoutManagerPropName = u"LayoutManager";
131 // Help to make changes to the alignment compatible!
132 LayoutManagerListener::LayoutManagerListener(
133 SfxWorkWindow* pWrkWin ) :
134 m_bHasFrame( false ),
135 m_pWrkWin( pWrkWin )
139 LayoutManagerListener::~LayoutManagerListener()
143 void LayoutManagerListener::setFrame( const css::uno::Reference< css::frame::XFrame >& xFrame )
145 SolarMutexGuard aGuard;
146 if ( !m_pWrkWin || m_bHasFrame )
147 return;
149 m_xFrame = xFrame;
150 m_bHasFrame = true;
152 if ( !xFrame.is() )
153 return;
155 css::uno::Reference< css::beans::XPropertySet > xPropSet( xFrame, UNO_QUERY );
156 css::uno::Reference< css::frame::XLayoutManagerEventBroadcaster > xLayoutManager;
157 if ( !xPropSet.is() )
158 return;
162 Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
163 aValue >>= xLayoutManager;
165 if ( xLayoutManager.is() )
166 xLayoutManager->addLayoutManagerEventListener(
167 css::uno::Reference< css::frame::XLayoutManagerListener >(this) );
169 xPropSet.set( xLayoutManager, UNO_QUERY );
170 if ( xPropSet.is() )
172 aValue = xPropSet->getPropertyValue( "LockCount" );
173 aValue >>= m_pWrkWin->m_nLock;
176 catch ( css::lang::DisposedException& )
179 catch ( const css::uno::RuntimeException& )
181 throw;
183 catch ( css::uno::Exception& )
189 // XComponent
191 void SAL_CALL LayoutManagerListener::addEventListener(
192 const css::uno::Reference< css::lang::XEventListener >& )
194 // do nothing, only internal class
197 void SAL_CALL LayoutManagerListener::removeEventListener(
198 const css::uno::Reference< css::lang::XEventListener >& )
200 // do nothing, only internal class
203 void SAL_CALL LayoutManagerListener::dispose()
205 SolarMutexGuard aGuard;
207 // reset member
208 m_pWrkWin = nullptr;
210 css::uno::Reference< css::frame::XFrame > xFrame( m_xFrame.get(), css::uno::UNO_QUERY );
211 if ( !xFrame.is() )
212 return;
214 m_xFrame.clear();
215 m_bHasFrame = false;
217 css::uno::Reference< css::beans::XPropertySet > xPropSet( xFrame, css::uno::UNO_QUERY );
218 css::uno::Reference< css::frame::XLayoutManagerEventBroadcaster > xLayoutManager;
219 if ( !xPropSet.is() )
220 return;
224 css::uno::Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
225 aValue >>= xLayoutManager;
227 // remove as listener from layout manager
228 if ( xLayoutManager.is() )
229 xLayoutManager->removeLayoutManagerEventListener(
230 css::uno::Reference< css::frame::XLayoutManagerListener >(this) );
232 catch ( css::lang::DisposedException& )
235 catch ( const css::uno::RuntimeException& )
237 throw;
239 catch ( css::uno::Exception& )
245 // XEventListener
247 void SAL_CALL LayoutManagerListener::disposing(
248 const css::lang::EventObject& )
250 SolarMutexGuard aGuard;
251 m_pWrkWin = nullptr;
252 m_bHasFrame = false;
253 m_xFrame.clear();
257 // XLayoutManagerEventListener
259 void SAL_CALL LayoutManagerListener::layoutEvent(
260 const css::lang::EventObject&,
261 ::sal_Int16 eLayoutEvent,
262 const css::uno::Any& )
264 SolarMutexGuard aGuard;
265 if ( !m_pWrkWin )
266 return;
268 if ( eLayoutEvent == css::frame::LayoutManagerEvents::VISIBLE )
270 m_pWrkWin->MakeVisible_Impl( true );
271 m_pWrkWin->ShowChildren_Impl();
272 m_pWrkWin->ArrangeChildren_Impl();
274 else if ( eLayoutEvent == css::frame::LayoutManagerEvents::INVISIBLE )
276 m_pWrkWin->MakeVisible_Impl( false );
277 m_pWrkWin->HideChildren_Impl();
278 m_pWrkWin->ArrangeChildren_Impl();
280 else if ( eLayoutEvent == css::frame::LayoutManagerEvents::LOCK )
282 m_pWrkWin->Lock_Impl( true );
284 else if ( eLayoutEvent == css::frame::LayoutManagerEvents::UNLOCK )
286 m_pWrkWin->Lock_Impl( false );
290 namespace
292 struct ToolbarIdHash
294 size_t operator()(ToolbarId t) const
296 typedef std::underlying_type<ToolbarId>::type underlying_type;
297 return std::hash<underlying_type>()(static_cast<underlying_type>(t));
301 class FilledToolBarResIdToResourceURLMap
303 private:
304 typedef std::unordered_map<ToolbarId, OUString, ToolbarIdHash> ToolBarResIdToResourceURLMap;
305 ToolBarResIdToResourceURLMap m_aResIdToResourceURLMap;
306 public:
307 FilledToolBarResIdToResourceURLMap()
309 sal_Int32 nIndex( 0 );
310 while (pToolBarResToName[nIndex].eId != ToolbarId::None)
312 OUString aResourceURL( OUString::createFromAscii( pToolBarResToName[nIndex].pName ));
313 m_aResIdToResourceURLMap.emplace(pToolBarResToName[nIndex].eId, aResourceURL);
314 ++nIndex;
318 OUString findURL(ToolbarId eId) const
320 ToolBarResIdToResourceURLMap::const_iterator aIter = m_aResIdToResourceURLMap.find(eId);
321 if ( aIter != m_aResIdToResourceURLMap.end() )
322 return aIter->second;
323 return OUString();
328 static OUString GetResourceURLFromToolbarId(ToolbarId eId)
330 static FilledToolBarResIdToResourceURLMap theFilledToolBarResIdToResourceURLMap;
331 return theFilledToolBarResIdToResourceURLMap.findURL(eId);
334 static sal_uInt16 TbxMatch( sal_uInt16 nPos )
336 switch ( nPos )
338 case SFX_OBJECTBAR_APPLICATION :
339 return 0;
340 case SFX_OBJECTBAR_OPTIONS:
341 return 1;
342 case SFX_OBJECTBAR_MACRO:
343 return 2;
344 case SFX_OBJECTBAR_OBJECT:
345 return 3;
346 case SFX_OBJECTBAR_TOOLS:
347 return 4;
348 case SFX_OBJECTBAR_FULLSCREEN:
349 case SFX_OBJECTBAR_COMMONTASK:
350 case SFX_OBJECTBAR_RECORDING:
351 return nPos+1;
352 default:
353 return nPos;
357 static sal_uInt16 ChildAlignValue(SfxChildAlignment eAlign)
359 sal_uInt16 ret = 17;
361 switch (eAlign)
363 case SfxChildAlignment::HIGHESTTOP:
364 ret = 1;
365 break;
366 case SfxChildAlignment::LOWESTBOTTOM:
367 ret = 2;
368 break;
369 case SfxChildAlignment::FIRSTLEFT:
370 ret = 3;
371 break;
372 case SfxChildAlignment::LASTRIGHT:
373 ret = 4;
374 break;
375 case SfxChildAlignment::LEFT:
376 ret = 5;
377 break;
378 case SfxChildAlignment::RIGHT:
379 ret = 6;
380 break;
381 case SfxChildAlignment::FIRSTRIGHT:
382 ret = 7;
383 break;
384 case SfxChildAlignment::LASTLEFT:
385 ret = 8;
386 break;
387 case SfxChildAlignment::TOP:
388 ret = 9;
389 break;
390 case SfxChildAlignment::BOTTOM:
391 ret = 10;
392 break;
393 case SfxChildAlignment::TOOLBOXTOP:
394 ret = 11;
395 break;
396 case SfxChildAlignment::TOOLBOXBOTTOM:
397 ret = 12;
398 break;
399 case SfxChildAlignment::LOWESTTOP:
400 ret = 13;
401 break;
402 case SfxChildAlignment::HIGHESTBOTTOM:
403 ret = 14;
404 break;
405 case SfxChildAlignment::TOOLBOXLEFT:
406 ret = 15;
407 break;
408 case SfxChildAlignment::TOOLBOXRIGHT:
409 ret = 16;
410 break;
411 case SfxChildAlignment::NOALIGNMENT:
412 break; // -Wall not handled...
415 return ret;
418 void SfxWorkWindow::Sort_Impl()
420 aSortedList.clear();
421 for (size_t i = 0; i < aChildren.size(); ++i)
423 SfxChild_Impl *pCli = aChildren[i].get();
424 if (pCli)
426 decltype(aSortedList)::size_type k;
427 for (k=0; k<aSortedList.size(); k++)
428 if (ChildAlignValue( aChildren[aSortedList[k]]->eAlign ) >
429 ChildAlignValue(pCli->eAlign))
430 break;
431 aSortedList.insert( aSortedList.begin() + k, i );
435 bSorted = true;
438 constexpr OUStringLiteral g_aStatusBarResName( u"private:resource/statusbar/statusbar" );
439 constexpr OUStringLiteral g_aTbxTypeName( u"private:resource/toolbar/" );
440 constexpr OUStringLiteral g_aProgressBarResName( u"private:resource/progressbar/progressbar" );
442 // constructor for workwin of a Frame
444 SfxWorkWindow::SfxWorkWindow( vcl::Window *pWin, SfxFrame *pFrm, SfxFrame* pMaster ) :
445 pBindings(&pFrm->GetCurrentViewFrame()->GetBindings()),
446 pWorkWin (pWin),
447 pActiveChild( nullptr ),
448 nUpdateMode(SfxVisibilityFlags::Standard),
449 nChildren( 0 ),
450 nOrigMode( SfxVisibilityFlags::Invisible ),
451 bSorted( true ),
452 bDockingAllowed(true),
453 bInternalDockingAllowed(true),
454 bAllChildrenVisible(true),
455 #if !defined(ANDROID) || HAVE_FEATURE_ANDROID_LOK
456 bIsFullScreen( false ),
457 #else // Fennec-based Android Viewer
458 bIsFullScreen( true ),
459 #endif
460 #if HAVE_FEATURE_DESKTOP
461 bShowStatusBar( true ),
462 #else
463 bShowStatusBar( sal_False ),
464 #endif
465 m_nLock( 0 ),
466 pMasterFrame( pMaster ),
467 pFrame( pFrm )
469 DBG_ASSERT (pBindings, "No Bindings!");
471 pBindings->SetWorkWindow_Impl( std::unique_ptr<SfxWorkWindow>(this) );
473 // For the ObjectBars an integral place in the Childlist is reserved,
474 // so that they always come in a defined order.
475 for (int i=0; i<SFX_OBJECTBAR_MAX; ++i)
476 aChildren.push_back( nullptr );
478 // create and initialize layout manager listener
479 Reference< css::frame::XFrame > xFrame = GetFrameInterface();
480 rtl::Reference<LayoutManagerListener> pLayoutManagerListener = new LayoutManagerListener( this );
481 m_xLayoutManagerListener = pLayoutManagerListener;
482 pLayoutManagerListener->setFrame( xFrame );
484 SfxShell* pConfigShell = pFrm->GetCurrentViewFrame();
485 if ( pConfigShell && pConfigShell->GetObjectShell() )
487 bShowStatusBar = ( !pConfigShell->GetObjectShell()->IsInPlaceActive() );
488 bDockingAllowed = true;
489 bInternalDockingAllowed = true;
492 // The required split windows (one for each side) can be created
493 for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX; n++ )
495 // The SplitWindows excludes direct ChildWindows of the WorkWindows
496 // and receives the docked window.
498 SfxChildAlignment eAlign =
499 ( n == SFX_SPLITWINDOWS_LEFT ? SfxChildAlignment::LEFT :
500 n == SFX_SPLITWINDOWS_RIGHT ? SfxChildAlignment::RIGHT :
501 n == SFX_SPLITWINDOWS_TOP ? SfxChildAlignment::TOP :
502 SfxChildAlignment::BOTTOM );
503 VclPtr<SfxSplitWindow> pSplitWin = VclPtr<SfxSplitWindow>::Create(pWorkWin, eAlign, this, true );
504 pSplit[n] = pSplitWin;
507 nOrigMode = SfxVisibilityFlags::Standard;
508 nUpdateMode = SfxVisibilityFlags::Standard;
512 // Destructor
514 SfxWorkWindow::~SfxWorkWindow()
517 // Delete SplitWindows
518 for (VclPtr<SfxSplitWindow> & p : pSplit)
520 if (p->GetWindowCount())
521 ReleaseChild_Impl(*p);
522 p.disposeAndClear();
525 // Delete help structure for Child-Windows
526 DBG_ASSERT( aChildren.empty(), "dangling children" );
528 if ( m_xLayoutManagerListener.is() )
529 m_xLayoutManagerListener->dispose();
532 void SfxWorkWindow::Lock_Impl( bool bLock )
534 if ( bLock )
535 m_nLock++;
536 else
537 --m_nLock;
538 if ( m_nLock<0 )
540 OSL_FAIL("Lock count underflow!");
541 assert(m_nLock >= 0);
542 m_nLock = 0;
545 if ( !m_nLock )
546 ArrangeChildren_Impl();
550 // Helper method to release the child lists. Should the destructor not be
551 // called after this, instead work continues, then space for the object bars
552 // and split windows has to be reserved in the same way as in the constructor
553 // of SfxWorkWindow.
555 void SfxWorkWindow::DeleteControllers_Impl()
558 // Lock SplitWindows (which means suppressing the Resize-Reaction of the
559 // DockingWindows)
560 for (size_t n=0; n<SFX_SPLITWINDOWS_MAX; n++ )
562 VclPtr<SfxSplitWindow> const &p = pSplit[n];
563 if (p->GetWindowCount())
564 p->Lock();
567 // Delete Child-Windows
568 while(!aChildWins.empty())
570 std::unique_ptr<SfxChildWin_Impl> pCW = std::move(*aChildWins.begin());
571 aChildWins.erase(aChildWins.begin());
572 SfxChildWindow *pChild = pCW->pWin;
573 if (pChild)
575 if (comphelper::LibreOfficeKit::isActive())
577 vcl::Window* pWindow = pChild->GetWindow();
578 if (pWindow)
580 pWindow->ReleaseLOKNotifier();
583 pChild->Hide();
585 // If the child window is a direct child window and not in a
586 // SplitWindow, cancel it at the workwindow.
587 // After TH a cancellation on the SplitWindow is not necessary
588 // since this window is also destroyed (see below).
589 if (pCW->pCli)
591 if (pChild->GetController())
592 ReleaseChild_Impl(*pChild->GetController());
593 else
594 ReleaseChild_Impl(*pChild->GetWindow());
597 pCW->pWin = nullptr;
598 pWorkWin->GetSystemWindow()->GetTaskPaneList()->RemoveWindow( pChild->GetWindow() );
599 pChild->Destroy();
602 // ATTENTION: The array itself is cleared after this loop!!
603 // Therefore we have to set every array entry to zero as it could be
604 // accessed by calling pChild->Destroy().
605 // Window::NotifyAllChildren() calls SfxWorkWindow::DataChanged_Impl for
606 // 8-bit displays (WM_QUERYPALETTECHANGED message due to focus change)!!
609 Reference< css::frame::XFrame > xFrame = GetFrameInterface();
610 Reference< css::beans::XPropertySet > xPropSet( xFrame, UNO_QUERY );
611 Reference< css::frame::XLayoutManager > xLayoutManager;
612 if ( xPropSet.is() )
616 Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
617 aValue >>= xLayoutManager;
619 catch ( Exception& )
624 if ( xLayoutManager.is() )
626 xLayoutManager->reset();
628 // Delete StatusBar
629 ResetStatusBar_Impl();
631 // Delete ObjectBars (this is done last, so that aChildren does not
632 // receive dead Pointers)
633 for (SfxObjectBar_Impl & i : aObjBarList)
635 // Not every position must be occupied
636 ToolbarId eId = i.eId;
637 if (eId != ToolbarId::None)
638 i.eId = ToolbarId::None;
642 // ObjectBars are all released at once, since they occupy a
643 // fixed contiguous area in the array pChild
644 aChildren.clear();
645 bSorted = false;
647 nChildren = 0;
651 // for placing the child window.
653 void SfxWorkWindow::ArrangeChildren_Impl( bool bForce )
655 if ( pFrame->IsClosing_Impl() || ( m_nLock && !bForce ))
656 return;
658 SfxInPlaceClient *pClient = nullptr;
659 SfxViewFrame *pF = pFrame->GetCurrentViewFrame();
660 if ( pF && pF->GetViewShell() )
661 pClient = pF->GetViewShell()->GetIPClient();
663 if ( pClient )
664 return;
666 aClientArea = GetTopRect_Impl();
667 if ( aClientArea.IsEmpty() )
668 return;
670 SvBorder aBorder;
671 if ( nChildren && IsVisible_Impl() )
672 aBorder = Arrange_Impl();
673 // If the current application document contains an IPClient, then the
674 // object through SetTopToolFramePixel has to be assigned the available
675 // space. The object will then point to its UITools and sets the app border
676 // (-> SfxInPlaceEnv_Impl:: ArrangeChildren_Impl ()). Otherwise the
677 // app border is set here directly to possibly overwrite the Border that
678 // was set by an object from another document. The object does not set
679 // the SetAppBorder when it removes its UI tools so that no-dithering
680 // ObjectBar arises.
681 // (->SfxInPlaceEnv_Impl::ArrangeChildren_Impl())
683 pMasterFrame->SetToolSpaceBorderPixel_Impl( aBorder );
685 ArrangeAutoHideWindows( nullptr );
688 void SfxWorkWindow::FlushPendingChildSizes()
690 // tdf#116865, if any windows are being resized, i.e. their
691 // resize timer is active, then calling GetSizePixel on
692 // them forces the timer to fire and sets the final
693 // size to which they are getting resized towards.
694 for (size_t i = 0; i < aChildren.size(); ++i)
696 SfxChild_Impl *pCli = aChildren[i].get();
697 if (!pCli || !pCli->pWin)
698 continue;
699 (void)pCli->pWin->GetSizePixel();
703 SvBorder SfxWorkWindow::Arrange_Impl()
705 /* [Description]
707 This method organizes all visible child windows so that the docked window
708 sorted in order from the outside to the inside are placed after one
709 another. If a visible window does not fit anymore into the free
710 ClientArea, it is set to "not visible".
713 //tdf#116865 trigger pending sizing timers now so we arrange
714 //with the final size of the client area.
716 //Otherwise calling GetSizePixel in the following loop will trigger the
717 //timers, causing reentry into Arrange_Impl again where the inner
718 //Arrange_Impl arranges with the final size, and then returns to this outer
719 //Arrange_Impl which would rearrange with the old client area size
720 FlushPendingChildSizes();
721 aClientArea = GetTopRect_Impl();
722 aUpperClientArea = aClientArea;
724 SvBorder aBorder;
725 if ( !nChildren )
726 return aBorder;
728 if (!bSorted)
729 Sort_Impl();
731 Point aPos;
732 Size aSize;
733 tools::Rectangle aTmp( aClientArea );
735 for (sal_uInt16 n : aSortedList)
737 SfxChild_Impl* pCli = aChildren[n].get();
738 if ( !pCli->pWin )
739 continue;
741 // First, we assume that there is room for the window.
742 pCli->nVisible |= SfxChildVisibility::FITS_IN;
744 // Skip invisible windows
745 if (pCli->nVisible != SfxChildVisibility::VISIBLE)
746 continue;
748 if ( pCli->bResize )
749 aSize = pCli->aSize;
750 else
751 aSize = pCli->pWin->GetSizePixel();
753 SvBorder aTemp = aBorder;
754 bool bAllowHiding = true;
755 switch ( pCli->eAlign )
757 case SfxChildAlignment::HIGHESTTOP:
758 case SfxChildAlignment::TOP:
759 case SfxChildAlignment::TOOLBOXTOP:
760 case SfxChildAlignment::LOWESTTOP:
761 aSize.setWidth( aTmp.GetWidth() );
762 if ( pCli->pWin->GetType() == WindowType::SPLITWINDOW )
763 aSize = static_cast<SplitWindow *>(pCli->pWin.get())->CalcLayoutSizePixel( aSize );
764 bAllowHiding = false;
765 aBorder.Top() += aSize.Height();
766 aPos = aTmp.TopLeft();
767 aTmp.AdjustTop(aSize.Height() );
768 if ( pCli->eAlign == SfxChildAlignment::HIGHESTTOP )
769 aUpperClientArea.AdjustTop(aSize.Height() );
770 break;
772 case SfxChildAlignment::LOWESTBOTTOM:
773 case SfxChildAlignment::BOTTOM:
774 case SfxChildAlignment::TOOLBOXBOTTOM:
775 case SfxChildAlignment::HIGHESTBOTTOM:
776 aSize.setWidth( aTmp.GetWidth() );
777 if ( pCli->pWin->GetType() == WindowType::SPLITWINDOW )
778 aSize = static_cast<SplitWindow *>(pCli->pWin.get())->CalcLayoutSizePixel( aSize );
779 aBorder.Bottom() += aSize.Height();
780 aPos = aTmp.BottomLeft();
781 aPos.AdjustY( -(aSize.Height()-1) );
782 aTmp.AdjustBottom( -(aSize.Height()) );
783 if ( pCli->eAlign == SfxChildAlignment::LOWESTBOTTOM )
784 aUpperClientArea.AdjustBottom( -(aSize.Height()) );
785 break;
787 case SfxChildAlignment::FIRSTLEFT:
788 case SfxChildAlignment::LEFT:
789 case SfxChildAlignment::LASTLEFT:
790 case SfxChildAlignment::TOOLBOXLEFT:
791 aSize.setHeight( aTmp.GetHeight() );
792 if ( pCli->pWin->GetType() == WindowType::SPLITWINDOW )
793 aSize = static_cast<SplitWindow *>(pCli->pWin.get())->CalcLayoutSizePixel( aSize );
794 bAllowHiding = false;
795 aBorder.Left() += aSize.Width();
796 aPos = aTmp.TopLeft();
797 aTmp.AdjustLeft(aSize.Width() );
798 if ( pCli->eAlign != SfxChildAlignment::TOOLBOXLEFT )
799 aUpperClientArea.AdjustLeft(aSize.Width() );
800 break;
802 case SfxChildAlignment::FIRSTRIGHT:
803 case SfxChildAlignment::RIGHT:
804 case SfxChildAlignment::LASTRIGHT:
805 case SfxChildAlignment::TOOLBOXRIGHT:
806 aSize.setHeight( aTmp.GetHeight() );
807 if ( pCli->pWin->GetType() == WindowType::SPLITWINDOW )
808 aSize = static_cast<SplitWindow *>(pCli->pWin.get())->CalcLayoutSizePixel( aSize );
809 aBorder.Right() += aSize.Width();
810 aPos = aTmp.TopRight();
811 aPos.AdjustX( -(aSize.Width()-1) );
812 aTmp.AdjustRight( -(aSize.Width()) );
813 if ( pCli->eAlign != SfxChildAlignment::TOOLBOXRIGHT )
814 aUpperClientArea.AdjustRight( -(aSize.Width()) );
815 break;
817 default:
818 pCli->aSize = pCli->pWin->GetSizePixel();
819 pCli->bResize = false;
820 continue;
823 pCli->pWin->SetPosSizePixel( aPos, aSize );
824 pCli->bResize = false;
825 pCli->aSize = aSize;
826 if( bAllowHiding && !RequestTopToolSpacePixel_Impl( aBorder ) )
828 pCli->nVisible ^= SfxChildVisibility::FITS_IN;
829 aBorder = aTemp;
833 if ( aClientArea.GetWidth() >= aBorder.Left() + aBorder.Right() )
835 aClientArea.AdjustLeft(aBorder.Left() );
836 aClientArea.AdjustRight( -(aBorder.Right()) );
838 else
840 aBorder.Left() = aClientArea.Left();
841 aBorder.Right() = aClientArea.Right();
842 aClientArea.SetRight( aTmp.Left() );
843 aClientArea.SetLeft( aTmp.Left() );
846 if ( aClientArea.GetHeight() >= aBorder.Top() + aBorder.Bottom() )
848 aClientArea.AdjustTop(aBorder.Top() );
849 aClientArea.AdjustBottom( -(aBorder.Bottom()) );
851 else
853 aBorder.Top() = aClientArea.Top();
854 aBorder.Bottom() = aClientArea.Bottom();
855 aClientArea.SetTop(aTmp.Top());
856 aClientArea.SetBottom(aTmp.Top());
859 return IsDockingAllowed() ? aBorder : SvBorder();
862 bool SfxWorkWindow::PrepareClose_Impl()
864 for (const std::unique_ptr<SfxChildWin_Impl> &pCW : aChildWins)
866 SfxChildWindow *pChild = pCW->pWin;
867 if ( pChild && !pChild->QueryClose() )
868 return false;
871 return true;
874 SfxChild_Impl* SfxWorkWindow::RegisterChild_Impl( vcl::Window& rWindow,
875 SfxChildAlignment eAlign )
877 DBG_ASSERT( aChildren.size() < 255, "too many children" );
878 DBG_ASSERT( SfxChildAlignValid(eAlign), "invalid align" );
879 DBG_ASSERT( !FindChild_Impl(&rWindow), "child registered more than once" );
882 if ( rWindow.GetParent() != pWorkWin )
883 rWindow.SetParent( pWorkWin );
885 auto pChild = std::make_unique<SfxChild_Impl>(rWindow, rWindow.GetSizePixel(),
886 eAlign, rWindow.IsVisible());
888 aChildren.push_back(std::move(pChild));
889 bSorted = false;
890 nChildren++;
891 return aChildren.back().get();
894 SfxChild_Impl* SfxWorkWindow::RegisterChild_Impl(std::shared_ptr<SfxDialogController>& rController,
895 SfxChildAlignment eAlign )
897 DBG_ASSERT( aChildren.size() < 255, "too many children" );
898 DBG_ASSERT( SfxChildAlignValid(eAlign), "invalid align" );
900 auto pChild = std::make_unique<SfxChild_Impl>(rController, eAlign);
902 aChildren.push_back(std::move(pChild));
903 bSorted = false;
904 nChildren++;
905 return aChildren.back().get();
908 void SfxWorkWindow::ReleaseChild_Impl( vcl::Window& rWindow )
911 SfxChild_Impl *pChild = nullptr;
912 decltype(aChildren)::size_type nPos;
913 for ( nPos = 0; nPos < aChildren.size(); ++nPos )
915 pChild = aChildren[nPos].get();
916 if ( pChild && pChild->pWin == &rWindow )
918 bSorted = false;
919 nChildren--;
920 aChildren.erase(aChildren.begin() + nPos);
921 return;
924 OSL_FAIL( "releasing unregistered child" );
927 void SfxWorkWindow::ReleaseChild_Impl(const SfxDialogController& rController)
930 SfxChild_Impl *pChild = nullptr;
931 decltype(aChildren)::size_type nPos;
932 for ( nPos = 0; nPos < aChildren.size(); ++nPos )
934 pChild = aChildren[nPos].get();
935 if (pChild && pChild->xController.get() == &rController)
937 bSorted = false;
938 nChildren--;
939 aChildren.erase(aChildren.begin() + nPos);
940 return;
943 OSL_FAIL( "releasing unregistered child" );
946 SfxChild_Impl* SfxWorkWindow::FindChild_Impl( const vcl::Window* rWindow ) const
949 sal_uInt16 nCount = aChildren.size();
950 for ( sal_uInt16 nPos = 0; nPos < nCount; ++nPos )
952 SfxChild_Impl *pChild = aChildren[nPos].get();
953 if ( pChild && pChild->pWin == rWindow )
954 return pChild;
957 return nullptr;
960 void SfxWorkWindow::ShowChildren_Impl()
962 bool bInvisible = ( !IsVisible_Impl() || ( !pWorkWin->IsReallyVisible() && !pWorkWin->IsReallyShown() ));
964 for (std::unique_ptr<SfxChild_Impl>& pCli : aChildren)
966 if (!pCli)
967 continue;
968 SfxChildWin_Impl* pCW = nullptr;
969 if (pCli->pWin || pCli->xController)
971 // We have to find the SfxChildWin_Impl to retrieve the
972 // SFX_CHILDWIN flags that can influence visibility.
973 for (const std::unique_ptr<SfxChildWin_Impl>& pCWin : aChildWins)
975 SfxChild_Impl* pChild = pCWin->pCli;
976 if ( pChild == pCli.get() )
978 pCW = pCWin.get();
979 break;
983 bool bVisible( !bInvisible );
984 if ( pCW )
986 // Check flag SFX_CHILDWIN_NEVERHIDE that forces us to show
987 // the child window even in situations where no child window is
988 // visible.
989 SfxChildWindowFlags nFlags = pCW->aInfo.nFlags;
990 bVisible = !bInvisible || ( nFlags & SfxChildWindowFlags::NEVERHIDE );
993 if ( SfxChildVisibility::VISIBLE == (pCli->nVisible & SfxChildVisibility::VISIBLE) && bVisible )
995 ShowFlags nFlags = pCli->bSetFocus ? ShowFlags::NONE : ShowFlags::NoFocusChange | ShowFlags::NoActivate;
996 if (pCli->xController)
998 if (!pCli->xController->getDialog()->get_visible())
1000 auto xController = pCli->xController;
1001 weld::DialogController::runAsync(xController,
1002 [=](sal_Int32 /*nResult*/){ xController->Close(); });
1005 else
1006 pCli->pWin->Show(true, nFlags);
1007 pCli->bSetFocus = false;
1009 else
1011 if (pCli->xController)
1013 if (pCli->xController->getDialog()->get_visible())
1014 pCli->xController->response(RET_CLOSE);
1016 else
1017 pCli->pWin->Hide();
1024 void SfxWorkWindow::HideChildren_Impl()
1026 for ( sal_uInt16 nPos = aChildren.size(); nPos > 0; --nPos )
1028 SfxChild_Impl *pChild = aChildren[nPos-1].get();
1029 if (!pChild)
1030 continue;
1031 if (pChild->xController)
1032 pChild->xController->response(RET_CLOSE);
1033 else if (pChild->pWin)
1034 pChild->pWin->Hide();
1038 void SfxWorkWindow::ResetObjectBars_Impl()
1040 for ( auto & n: aObjBarList )
1041 n.bDestroy = true;
1043 for ( auto & n: aChildWins )
1044 n->nId = 0;
1047 void SfxWorkWindow::SetObjectBar_Impl(sal_uInt16 nPos, SfxVisibilityFlags nFlags, ToolbarId eId)
1049 DBG_ASSERT( nPos < SFX_OBJECTBAR_MAX, "object bar position overflow" );
1051 SfxObjectBar_Impl aObjBar;
1052 aObjBar.eId = eId;
1053 aObjBar.nMode = nFlags;
1055 for (SfxObjectBar_Impl & rBar : aObjBarList)
1057 if ( rBar.eId == aObjBar.eId )
1059 rBar = aObjBar;
1060 return;
1064 aObjBarList.push_back( aObjBar );
1067 bool SfxWorkWindow::IsVisible_Impl( SfxVisibilityFlags nMode ) const
1069 switch( nUpdateMode )
1071 case SfxVisibilityFlags::Standard:
1072 return true;
1073 case SfxVisibilityFlags::Invisible:
1074 return false;
1075 case SfxVisibilityFlags::Client:
1076 case SfxVisibilityFlags::Server:
1077 return bool(nMode & nUpdateMode);
1078 default:
1079 return (nMode & nOrigMode ) ||
1080 nOrigMode == SfxVisibilityFlags::Standard;
1084 void SfxWorkWindow::UpdateObjectBars_Impl()
1086 if ( pFrame->IsClosing_Impl() )
1087 return;
1089 UpdateObjectBars_Impl2();
1092 ArrangeChildren_Impl( false );
1094 ShowChildren_Impl();
1097 ShowChildren_Impl();
1100 Reference< css::task::XStatusIndicator > SfxWorkWindow::GetStatusIndicator()
1102 Reference< css::beans::XPropertySet > xPropSet( GetFrameInterface(), UNO_QUERY );
1103 Reference< css::frame::XLayoutManager > xLayoutManager;
1104 Reference< css::task::XStatusIndicator > xStatusIndicator;
1106 if ( xPropSet.is() )
1108 Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
1109 aValue >>= xLayoutManager;
1110 if ( xLayoutManager.is() )
1112 xLayoutManager->createElement( g_aProgressBarResName );
1113 xLayoutManager->showElement( g_aProgressBarResName );
1115 Reference< css::ui::XUIElement > xProgressBar =
1116 xLayoutManager->getElement( g_aProgressBarResName );
1117 if ( xProgressBar.is() )
1119 xStatusIndicator.set( xProgressBar->getRealInterface(), UNO_QUERY );
1124 return xStatusIndicator;
1128 bool SfxWorkWindow::IsPluginMode( SfxObjectShell const * pObjShell )
1130 if ( pObjShell && pObjShell->GetMedium() )
1132 const SfxBoolItem* pViewOnlyItem = SfxItemSet::GetItem<SfxBoolItem>(pObjShell->GetMedium()->GetItemSet(), SID_VIEWONLY, false);
1133 if ( pViewOnlyItem && pViewOnlyItem->GetValue() )
1134 return true;
1137 return false;
1141 css::uno::Reference< css::frame::XFrame > SfxWorkWindow::GetFrameInterface()
1143 css::uno::Reference< css::frame::XFrame > xFrame;
1145 SfxDispatcher* pDispatcher( GetBindings().GetDispatcher() );
1146 if ( pDispatcher )
1148 SfxViewFrame* pViewFrame = pDispatcher->GetFrame();
1149 if ( pViewFrame )
1150 xFrame = pViewFrame->GetFrame().GetFrameInterface();
1153 return xFrame;
1157 void SfxWorkWindow::UpdateObjectBars_Impl2()
1159 // Lock SplitWindows (which means suppressing the Resize-Reaction of the
1160 // DockingWindows)
1161 for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX; n++ )
1163 VclPtr<SfxSplitWindow> const & p = pSplit[n];
1164 if (p->GetWindowCount())
1165 p->Lock();
1168 Reference< css::beans::XPropertySet > xPropSet( GetFrameInterface(), UNO_QUERY );
1169 Reference< css::frame::XLayoutManager > xLayoutManager;
1171 if ( xPropSet.is() )
1173 Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
1174 aValue >>= xLayoutManager;
1177 if ( !xLayoutManager.is() )
1178 return;
1180 bool bPluginMode( false );
1181 SfxDispatcher* pDispatcher( GetBindings().GetDispatcher() );
1183 if ( pDispatcher )
1185 SfxViewFrame* pViewFrame = pDispatcher->GetFrame();
1186 if ( pViewFrame )
1187 bPluginMode = IsPluginMode( pViewFrame->GetObjectShell() );
1190 // Iterate over all Toolboxes
1191 xLayoutManager->lock();
1192 const bool isNotebookBarActive = sfx2::SfxNotebookBar::IsActive();
1193 for ( auto const & n: aObjBarList )
1195 ToolbarId eId = n.eId;
1196 bool bDestroy = n.bDestroy;
1198 // Determine the valid mode for the ToolBox
1199 SfxVisibilityFlags nTbxMode = n.nMode;
1200 bool bFullScreenTbx( nTbxMode & SfxVisibilityFlags::FullScreen );
1201 nTbxMode &= ~SfxVisibilityFlags::FullScreen;
1202 nTbxMode &= ~SfxVisibilityFlags::Viewer;
1204 // Is a ToolBox required in this context ?
1205 bool bModesMatching = (nUpdateMode != SfxVisibilityFlags::Invisible) && ((nTbxMode & nUpdateMode) == nUpdateMode);
1206 if ( bDestroy || isNotebookBarActive)
1208 OUString aTbxId = g_aTbxTypeName + GetResourceURLFromToolbarId(eId);
1209 xLayoutManager->destroyElement( aTbxId );
1211 else if ( eId != ToolbarId::None && ( ( bModesMatching && !bIsFullScreen ) ||
1212 ( bIsFullScreen && bFullScreenTbx ) ) )
1214 OUString aTbxId = g_aTbxTypeName + GetResourceURLFromToolbarId(eId);
1215 if ( !IsDockingAllowed() && !xLayoutManager->isElementFloating( aTbxId ))
1216 xLayoutManager->destroyElement( aTbxId );
1217 else
1219 xLayoutManager->requestElement( aTbxId );
1220 if ( bPluginMode )
1221 xLayoutManager->lockWindow( aTbxId );
1224 else if ( eId != ToolbarId::None )
1226 // Delete the Toolbox at this Position if possible
1227 OUString aTbxId = g_aTbxTypeName + GetResourceURLFromToolbarId(eId);
1228 xLayoutManager->destroyElement( aTbxId );
1232 UpdateStatusBar_Impl();
1234 // unlocking automatically forces Layout
1235 xLayoutManager->unlock();
1237 UpdateChildWindows_Impl();
1239 // Unlock the SplitWindows again
1240 for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX; n++ )
1242 VclPtr<SfxSplitWindow> const & p = pSplit[n];
1243 if (p->GetWindowCount())
1244 p->Lock(false);
1248 void SfxWorkWindow::UpdateChildWindows_Impl()
1250 // tdf#100870, tdf#101320: don't use range-based for loop when
1251 // container is modified
1252 for ( size_t n=0; n<aChildWins.size(); n++ )
1254 // any current or in the context available Childwindows
1255 SfxChildWin_Impl *pCW = aChildWins[n].get();
1256 SfxChildWindow *pChildWin = pCW->pWin;
1257 bool bCreate = false;
1258 if ( pCW->nId && (pCW->aInfo.nFlags & SfxChildWindowFlags::ALWAYSAVAILABLE || IsVisible_Impl( pCW->nVisibility ) ) )
1260 // In the context is an appropriate ChildWindow allowed;
1261 // it is also turned on?
1262 if ( pChildWin == nullptr && pCW->bCreate )
1264 // Internal docking is only used for embedding into another
1265 // container. We force the floating state of all floatable
1266 // child windows.
1267 if ( !bInternalDockingAllowed )
1269 // Special case for all non-floatable child windows. We have
1270 // to prevent the creation here!
1271 bCreate = !( pCW->aInfo.nFlags & SfxChildWindowFlags::FORCEDOCK );
1273 else if ( !IsDockingAllowed() || bIsFullScreen ) // || !bInternalDocking )
1275 // In Presentation mode or FullScreen only FloatingWindows
1276 SfxChildAlignment eAlign;
1277 if ( pCW->aInfo.GetExtraData_Impl( &eAlign ) )
1278 bCreate = ( eAlign == SfxChildAlignment::NOALIGNMENT );
1280 else
1281 bCreate = true;
1283 if (pCW->aInfo.nFlags & SfxChildWindowFlags::NEVERCLONE)
1284 pCW->bCreate = bCreate = false; // Don't create and remember that we haven't created.
1286 // Currently, no window here, but it is enabled; windows
1287 // Create window and if possible theContext
1288 if ( bCreate )
1289 CreateChildWin_Impl( pCW, false );
1291 if ( !bAllChildrenVisible && pCW->pCli )
1292 pCW->pCli->nVisible &= ~SfxChildVisibility::ACTIVE;
1294 else if ( pChildWin )
1296 // Window already exists, it should also be visible?
1297 if ( ( !bIsFullScreen || pChildWin->GetAlignment() == SfxChildAlignment::NOALIGNMENT ) && bAllChildrenVisible )
1299 // Update Mode is compatible; definitely enable it
1300 bCreate = true;
1301 if ( pCW->pCli )
1303 // The window is a direct Child
1304 if ((IsDockingAllowed() && bInternalDockingAllowed)
1305 || pCW->pCli->eAlign == SfxChildAlignment::NOALIGNMENT)
1306 pCW->pCli->nVisible |= SfxChildVisibility::NOT_HIDDEN;
1308 else
1310 if ( pCW->bCreate && IsDockingAllowed() && bInternalDockingAllowed )
1311 // The window ia within a SplitWindow
1312 static_cast<SfxDockingWindow*>(pChildWin->GetWindow())->Reappear_Impl();
1318 if ( pChildWin && !bCreate )
1320 if ( !pChildWin->QueryClose() || pChildWin->IsHideNotDelete() || Application::IsUICaptured() )
1322 if ( pCW->pCli )
1324 if ( pCW->pCli->nVisible & SfxChildVisibility::NOT_HIDDEN )
1325 pCW->pCli->nVisible ^= SfxChildVisibility::NOT_HIDDEN;
1327 else
1328 static_cast<SfxDockingWindow*>(pChildWin->GetWindow())->Disappear_Impl();
1330 else
1331 RemoveChildWin_Impl( pCW );
1336 void SfxWorkWindow::CreateChildWin_Impl( SfxChildWin_Impl *pCW, bool bSetFocus )
1338 pCW->aInfo.bVisible = true;
1340 SfxChildWindow *pChildWin = SfxChildWindow::CreateChildWindow( pCW->nId, pWorkWin, &GetBindings(), pCW->aInfo).release();
1341 if (!pChildWin)
1342 return;
1344 if ( bSetFocus )
1345 bSetFocus = pChildWin->WantsFocus();
1346 pChildWin->SetWorkWindow_Impl( this );
1348 // At least the extra string is changed during the evaluation,
1349 // also get it anewed
1350 SfxChildWinInfo aInfo = pChildWin->GetInfo();
1351 pCW->aInfo.aExtraString = aInfo.aExtraString;
1352 pCW->aInfo.bVisible = aInfo.bVisible;
1353 pCW->aInfo.nFlags |= aInfo.nFlags;
1355 // The creation was successful
1356 GetBindings().Invalidate(pCW->nId);
1358 sal_uInt16 nPos = pChildWin->GetPosition();
1359 if (nPos != CHILDWIN_NOPOS)
1361 DBG_ASSERT(nPos < SFX_OBJECTBAR_MAX, "Illegal objectbar position!");
1362 if ( aChildren[TbxMatch(nPos)] )// &&
1364 // ChildWindow replaces ObjectBar
1365 aChildren[TbxMatch(nPos)]->nVisible ^= SfxChildVisibility::NOT_HIDDEN;
1369 // make childwin keyboard accessible
1370 pWorkWin->GetSystemWindow()->GetTaskPaneList()->AddWindow( pChildWin->GetWindow() );
1372 pCW->pWin = pChildWin;
1374 if ( pChildWin->GetAlignment() == SfxChildAlignment::NOALIGNMENT || pChildWin->GetWindow()->GetParent() == pWorkWin)
1376 // The window is not docked or docked outside of one split windows
1377 // and must therefore be registered explicitly as a Child
1378 if (pChildWin->GetController())
1379 pCW->pCli = RegisterChild_Impl(pChildWin->GetController(), pChildWin->GetAlignment());
1380 else
1381 pCW->pCli = RegisterChild_Impl(*(pChildWin->GetWindow()), pChildWin->GetAlignment());
1382 pCW->pCli->nVisible = SfxChildVisibility::VISIBLE;
1383 if ( pChildWin->GetAlignment() != SfxChildAlignment::NOALIGNMENT && bIsFullScreen )
1384 pCW->pCli->nVisible ^= SfxChildVisibility::ACTIVE;
1385 pCW->pCli->bSetFocus = bSetFocus;
1387 else
1389 // A docked window which parent is not a WorkingWindow, must lie
1390 // in a SplitWindow and thus not be explicitly registered.
1391 // This happens already in the initialization of SfxDockingWindows!
1394 // Save the information in the INI file
1395 SaveStatus_Impl(pChildWin, pCW->aInfo);
1398 void SfxWorkWindow::RemoveChildWin_Impl( SfxChildWin_Impl *pCW )
1400 sal_uInt16 nId = pCW->nSaveId;
1401 SfxChildWindow *pChildWin = pCW->pWin;
1403 // Save the information in the INI file
1404 SfxChildWindowFlags nFlags = pCW->aInfo.nFlags;
1405 pCW->aInfo = pChildWin->GetInfo();
1406 pCW->aInfo.nFlags |= nFlags;
1407 SaveStatus_Impl(pChildWin, pCW->aInfo);
1409 pChildWin->Hide();
1411 if ( pCW->pCli )
1413 // Child window is a direct child window and must therefore unregister
1414 // itself from the WorkWindow
1415 pCW->pCli = nullptr;
1416 if (pChildWin->GetController())
1417 ReleaseChild_Impl(*pChildWin->GetController());
1418 else
1419 ReleaseChild_Impl(*pChildWin->GetWindow());
1421 else
1423 // ChildWindow is within a SplitWindow and unregister itself in
1424 // the destructor.
1427 pWorkWin->GetSystemWindow()->GetTaskPaneList()->RemoveWindow( pChildWin->GetWindow() );
1428 pCW->pWin = nullptr;
1429 pChildWin->Destroy();
1431 GetBindings().Invalidate( nId );
1434 void SfxWorkWindow::ResetStatusBar_Impl()
1436 aStatBar.eId = StatusBarId::None;
1439 void SfxWorkWindow::SetStatusBar_Impl(StatusBarId eId)
1441 if (eId != StatusBarId::None && bShowStatusBar && IsVisible_Impl())
1442 aStatBar.eId = eId;
1445 void SfxWorkWindow::UpdateStatusBar_Impl()
1447 Reference< css::beans::XPropertySet > xPropSet( GetFrameInterface(), UNO_QUERY );
1448 Reference< css::frame::XLayoutManager > xLayoutManager;
1450 Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
1451 aValue >>= xLayoutManager;
1453 // No status bar, if no ID is required or when in FullScreenView or
1454 // if disabled
1455 if (aStatBar.eId != StatusBarId::None && IsDockingAllowed() && bInternalDockingAllowed && bShowStatusBar &&
1456 !bIsFullScreen)
1458 // Id has changed, thus create a suitable Statusbarmanager, this takes
1459 // over the current status bar;
1460 if ( xLayoutManager.is() )
1461 xLayoutManager->requestElement( g_aStatusBarResName );
1463 else
1465 // Destroy the current StatusBar
1466 // The Manager only creates the Status bar, does not destroy it.
1467 if ( xLayoutManager.is() )
1468 xLayoutManager->destroyElement( g_aStatusBarResName );
1472 void SfxWorkWindow::MakeVisible_Impl( bool bVis )
1474 if ( bVis )
1475 nOrigMode = SfxVisibilityFlags::Standard;
1476 else
1477 nOrigMode = SfxVisibilityFlags::Invisible;
1479 if ( nOrigMode != nUpdateMode)
1480 nUpdateMode = nOrigMode;
1483 bool SfxWorkWindow::IsVisible_Impl() const
1485 return nOrigMode != SfxVisibilityFlags::Invisible;
1489 void SfxWorkWindow::HidePopups_Impl(bool bHide, sal_uInt16 nId )
1491 if (comphelper::LibreOfficeKit::isActive() && bHide)
1492 return;
1494 for (const std::unique_ptr<SfxChildWin_Impl>& i : aChildWins)
1496 SfxChildWindow *pCW = i->pWin;
1497 if (pCW && pCW->GetAlignment() == SfxChildAlignment::NOALIGNMENT && pCW->GetType() != nId)
1499 vcl::Window *pWin = pCW->GetWindow();
1500 SfxChild_Impl *pChild = FindChild_Impl(pWin);
1501 if (!pChild)
1503 SAL_WARN("sfx.appl", "missing SfxChild_Impl child!");
1504 continue;
1506 if (bHide)
1508 pChild->nVisible &= ~SfxChildVisibility::ACTIVE;
1509 pCW->Hide();
1511 else if ( !comphelper::LibreOfficeKit::isActive() ||
1512 SfxChildVisibility::ACTIVE != (pChild->nVisible & SfxChildVisibility::ACTIVE) )
1514 pChild->nVisible |= SfxChildVisibility::ACTIVE;
1515 if ( SfxChildVisibility::VISIBLE == (pChild->nVisible & SfxChildVisibility::VISIBLE) )
1516 pCW->Show( ShowFlags::NoFocusChange | ShowFlags::NoActivate );
1523 void SfxWorkWindow::ConfigChild_Impl(SfxChildIdentifier eChild,
1524 SfxDockingConfig eConfig, sal_uInt16 nId)
1526 SfxDockingWindow* pDockWin=nullptr;
1527 sal_uInt16 nPos = USHRT_MAX;
1528 vcl::Window *pWin=nullptr;
1529 SfxChildWin_Impl *pCW = nullptr;
1531 // configure direct childwindow
1532 for (const std::unique_ptr<SfxChildWin_Impl>& i : aChildWins)
1534 pCW = i.get();
1535 SfxChildWindow *pChild = pCW->pWin;
1536 if ( pChild && (pChild->GetType() == nId ))
1538 if (SfxDockingWindow* pSfxDockingWindow = dynamic_cast<SfxDockingWindow*>(pChild->GetWindow()))
1540 // it's a DockingWindow
1541 pDockWin = pSfxDockingWindow;
1543 else
1545 // FloatingWindow or ModelessDialog
1546 pWin = pChild->GetWindow();
1548 break;
1552 if ( pDockWin )
1554 if ( eChild == SfxChildIdentifier::DOCKINGWINDOW || pDockWin->GetAlignment() == SfxChildAlignment::NOALIGNMENT )
1556 if ( eChild == SfxChildIdentifier::SPLITWINDOW && eConfig == SfxDockingConfig::TOGGLEFLOATMODE)
1558 // DockingWindow was dragged out of a SplitWindow
1559 pCW->pCli = RegisterChild_Impl(*pDockWin, pDockWin->GetAlignment());
1560 pCW->pCli->nVisible = SfxChildVisibility::VISIBLE;
1563 pWin = pDockWin;
1565 else
1567 SfxSplitWindow *pSplitWin = GetSplitWindow_Impl(pDockWin->GetAlignment());
1569 // configure DockingWindow inside a SplitWindow
1570 if ( eConfig == SfxDockingConfig::TOGGLEFLOATMODE)
1572 // DockingWindow was dragged into a SplitWindow
1573 pCW->pCli = nullptr;
1574 ReleaseChild_Impl(*pDockWin);
1577 pWin = pSplitWin->GetSplitWindow();
1578 if ( pSplitWin->GetWindowCount() == 1 )
1579 static_cast<SplitWindow*>(pWin)->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
1583 DBG_ASSERT( pCW, "Unknown window!" );
1585 if ( !bSorted )
1586 // windows may have been registered and released without an update until now
1587 Sort_Impl();
1589 decltype(aSortedList)::size_type n;
1590 for ( n=0; n<aSortedList.size(); ++n )
1592 SfxChild_Impl *pChild = aChildren[aSortedList[n]].get();
1593 if ( pChild && pChild->pWin == pWin )
1594 break;
1597 if ( n < aSortedList.size() )
1598 // sometimes called while toggling float mode
1599 nPos = aSortedList[n];
1601 switch ( eConfig )
1603 case SfxDockingConfig::SETDOCKINGRECTS :
1605 if (nPos == USHRT_MAX || !pDockWin)
1606 return;
1608 tools::Rectangle aOuterRect( GetTopRect_Impl() );
1609 aOuterRect.SetPos( pWorkWin->OutputToScreenPixel( aOuterRect.TopLeft() ));
1610 tools::Rectangle aInnerRect( aOuterRect );
1612 // The current affected window is included in the calculation of
1613 // the inner rectangle!
1614 for (sal_uInt16 i : aSortedList)
1616 SfxChild_Impl* pCli = aChildren[i].get();
1618 if ( pCli && pCli->nVisible == SfxChildVisibility::VISIBLE && pCli->pWin )
1620 switch ( pCli->eAlign )
1622 case SfxChildAlignment::TOP:
1623 // Object-Toolboxes come always last
1624 aInnerRect.AdjustTop(pCli->aSize.Height() );
1625 break;
1627 case SfxChildAlignment::HIGHESTTOP:
1628 // Always performed first
1629 aInnerRect.AdjustTop(pCli->aSize.Height() );
1630 break;
1632 case SfxChildAlignment::LOWESTTOP:
1633 // Is only counted if it is the current window
1634 if ( i == nPos )
1635 aInnerRect.AdjustTop(pCli->aSize.Height() );
1636 break;
1638 case SfxChildAlignment::BOTTOM:
1639 // Object-Toolboxes come always last
1640 aInnerRect.AdjustBottom( -(pCli->aSize.Height()) );
1641 break;
1643 case SfxChildAlignment::LOWESTBOTTOM:
1644 // Always performed first
1645 aInnerRect.AdjustBottom( -(pCli->aSize.Height()) );
1646 break;
1648 case SfxChildAlignment::HIGHESTBOTTOM:
1649 // Is only counted if it is the current window
1650 if ( i == nPos )
1651 aInnerRect.AdjustBottom( -(pCli->aSize.Height()) );
1652 break;
1654 case SfxChildAlignment::LEFT:
1655 // Toolboxes come always last
1656 aInnerRect.AdjustLeft(pCli->aSize.Width() );
1657 break;
1659 case SfxChildAlignment::FIRSTLEFT:
1660 // Always performed first
1661 aInnerRect.AdjustLeft(pCli->aSize.Width() );
1662 break;
1664 case SfxChildAlignment::LASTLEFT:
1665 // Is only counted if it is the current window
1666 if (i == nPos)
1667 aInnerRect.AdjustLeft(pCli->aSize.Width() );
1668 break;
1670 case SfxChildAlignment::RIGHT:
1671 // Toolboxes come always last
1672 aInnerRect.AdjustRight( -(pCli->aSize.Width()) );
1673 break;
1675 case SfxChildAlignment::FIRSTRIGHT:
1676 // Is only counted if it is the current window
1677 if (i == nPos)
1678 aInnerRect.AdjustRight( -(pCli->aSize.Width()) );
1679 break;
1681 case SfxChildAlignment::LASTRIGHT:
1682 // Always performed first
1683 aInnerRect.AdjustRight( -(pCli->aSize.Width()) );
1684 break;
1686 default:
1687 break;
1692 pDockWin->SetDockingRects(aOuterRect, aInnerRect);
1693 break;
1696 case SfxDockingConfig::ALIGNDOCKINGWINDOW :
1697 case SfxDockingConfig::TOGGLEFLOATMODE:
1699 if ( nPos == USHRT_MAX && !pCW )
1700 return;
1702 SfxChildAlignment eAlign = SfxChildAlignment::NOALIGNMENT;
1703 SfxChild_Impl *pCli = ( nPos != USHRT_MAX ) ? aChildren[nPos].get() : nullptr;
1704 if ( pCli && pDockWin )
1706 eAlign = pDockWin->GetAlignment();
1707 if ( eChild == SfxChildIdentifier::DOCKINGWINDOW || eAlign == SfxChildAlignment::NOALIGNMENT)
1709 // configuration inside the SplitWindow, no change for the SplitWindows' configuration
1710 pCli->bResize = true;
1711 pCli->aSize = pDockWin->GetSizePixel();
1715 if ( pCli )
1717 if( pCli->eAlign != eAlign )
1719 bSorted = false;
1720 pCli->eAlign = eAlign;
1723 ArrangeChildren_Impl();
1724 ShowChildren_Impl();
1727 if ( pCW && pCW->pWin )
1729 // store changed configuration
1730 SfxChildWindowFlags nFlags = pCW->aInfo.nFlags;
1731 pCW->aInfo = pCW->pWin->GetInfo();
1732 pCW->aInfo.nFlags |= nFlags;
1733 SaveStatus_Impl( pCW->pWin, pCW->aInfo);
1736 break;
1742 void SfxWorkWindow::SetChildWindowVisible_Impl( sal_uInt32 lId, bool bEnabled, SfxVisibilityFlags nMode )
1744 sal_uInt16 nId = static_cast<sal_uInt16>( lId & 0xFFFF );
1746 SfxChildWin_Impl *pCW=nullptr;
1748 if ( !pCW )
1750 // If no Parent or the Parent us still unknown, then search here
1751 sal_uInt16 nCount = aChildWins.size();
1752 for (sal_uInt16 n=0; n<nCount; n++)
1753 if (aChildWins[n]->nSaveId == nId)
1755 pCW = aChildWins[n].get();
1756 break;
1760 if ( !pCW )
1762 // If new, then initialize, add this here depending on the flag or
1763 // the Parent
1764 pCW = new SfxChildWin_Impl( lId );
1765 pCW->nId = nId;
1766 InitializeChild_Impl( pCW );
1767 aChildWins.push_back( std::unique_ptr<SfxChildWin_Impl>(pCW) );
1770 pCW->nId = nId;
1771 pCW->nVisibility = nMode;
1772 pCW->bEnable = bEnabled;
1776 // The on/off status of a ChildWindow is switched
1778 void SfxWorkWindow::ToggleChildWindow_Impl(sal_uInt16 nId, bool bSetFocus)
1780 sal_uInt16 nCount = aChildWins.size();
1781 sal_uInt16 n;
1782 for (n=0; n<nCount; n++)
1783 if (aChildWins[n]->nId == nId)
1784 break;
1786 if ( n<nCount )
1788 // The Window is already known
1789 SfxChildWin_Impl *pCW = aChildWins[n].get();
1790 SfxChildWindow *pChild = pCW->pWin;
1792 bool bCreationAllowed( true );
1793 if ( !bInternalDockingAllowed )
1795 // Special case for all non-floatable child windows. We have
1796 // to prevent the creation here!
1797 bCreationAllowed = !( pCW->aInfo.nFlags & SfxChildWindowFlags::FORCEDOCK );
1800 if ( bCreationAllowed )
1802 if ( pCW->bCreate )
1804 if ( pChild )
1806 if ( pChild->QueryClose() )
1808 pCW->bCreate = false;
1809 // The Window should be switched off
1810 pChild->SetVisible_Impl( false );
1811 RemoveChildWin_Impl( pCW );
1814 else
1816 // no actual Window exists, yet => just remember the "switched off" state
1817 pCW->bCreate = false;
1820 else
1822 pCW->bCreate = true;
1823 if ( pChild )
1825 ShowChildWindow_Impl( nId, true, bSetFocus );
1827 else
1829 // create actual Window
1830 CreateChildWin_Impl( pCW, bSetFocus );
1831 if ( !pCW->pWin )
1832 // no success
1833 pCW->bCreate = false;
1838 ArrangeChildren_Impl();
1839 ShowChildren_Impl();
1841 if ( pCW->bCreate && bCreationAllowed )
1843 if ( !pCW->pCli )
1845 SfxDockingWindow *pDock =
1846 static_cast<SfxDockingWindow*>( pCW->pWin->GetWindow() );
1847 if ( pDock->IsAutoHide_Impl() )
1848 pDock->AutoShow_Impl();
1852 return;
1855 #ifdef DBG_UTIL
1856 nCount = aChildWins.size();
1857 for (n=0; n<nCount; n++)
1858 if (aChildWins[n]->nSaveId == nId)
1859 break;
1861 if ( n < nCount )
1863 OSL_FAIL("The ChildWindow is not in context!");
1865 else
1867 OSL_FAIL("The ChildWindow is not registered!");
1869 #endif
1873 bool SfxWorkWindow::HasChildWindow_Impl(sal_uInt16 nId)
1875 sal_uInt16 nCount = aChildWins.size();
1876 sal_uInt16 n;
1877 for (n=0; n<nCount; n++)
1878 if (aChildWins[n]->nSaveId == nId)
1879 break;
1881 if (n<nCount)
1883 SfxChildWin_Impl *pCW = aChildWins[n].get();
1884 SfxChildWindow *pChild = pCW->pWin;
1885 return ( pChild && pCW->bCreate );
1888 return false;
1891 bool SfxWorkWindow::IsFloating( sal_uInt16 nId )
1893 SfxChildWin_Impl *pCW=nullptr;
1895 if ( !pCW )
1897 // If no Parent or the Parent us still unknown, then search here
1898 sal_uInt16 nCount = aChildWins.size();
1899 for (sal_uInt16 n=0; n<nCount; n++)
1900 if (aChildWins[n]->nSaveId == nId)
1902 pCW = aChildWins[n].get();
1903 break;
1907 if ( !pCW )
1909 // If new, then initialize, add this here depending on the flag or
1910 // the Parent
1911 pCW = new SfxChildWin_Impl( nId );
1912 pCW->bEnable = false;
1913 pCW->nId = 0;
1914 pCW->nVisibility = SfxVisibilityFlags::Invisible;
1915 InitializeChild_Impl( pCW );
1916 aChildWins.push_back( std::unique_ptr<SfxChildWin_Impl>(pCW) );
1919 SfxChildAlignment eAlign;
1920 if ( pCW->aInfo.GetExtraData_Impl( &eAlign ) )
1921 return( eAlign == SfxChildAlignment::NOALIGNMENT );
1922 else
1923 return true;
1927 bool SfxWorkWindow::KnowsChildWindow_Impl(sal_uInt16 nId)
1929 SfxChildWin_Impl *pCW=nullptr;
1930 sal_uInt16 nCount = aChildWins.size();
1931 sal_uInt16 n;
1932 for (n=0; n<nCount; n++)
1934 pCW = aChildWins[n].get();
1935 if ( pCW->nSaveId == nId)
1936 break;
1939 if (n<nCount)
1941 if ( !(pCW->aInfo.nFlags & SfxChildWindowFlags::ALWAYSAVAILABLE) && !IsVisible_Impl( pCW->nVisibility ) )
1942 return false;
1943 return pCW->bEnable;
1945 else
1946 return false;
1950 void SfxWorkWindow::SetChildWindow_Impl(sal_uInt16 nId, bool bOn, bool bSetFocus)
1952 SfxChildWin_Impl *pCW=nullptr;
1953 SfxWorkWindow *pWork = nullptr;
1955 if ( !pCW )
1957 // If no Parent or the Parent us still unknown, then search here
1958 sal_uInt16 nCount = aChildWins.size();
1959 for (sal_uInt16 n=0; n<nCount; n++)
1960 if (aChildWins[n]->nSaveId == nId)
1962 pCW = aChildWins[n].get();
1963 pWork = this;
1964 break;
1968 if ( !pCW )
1970 // If new, then initialize, add this here depending on the flag or
1971 // the Parent
1972 pCW = new SfxChildWin_Impl( nId );
1973 InitializeChild_Impl( pCW );
1974 if ( !pWork || pCW->aInfo.nFlags & SfxChildWindowFlags::TASK )
1975 pWork = this;
1976 pWork->aChildWins.push_back( std::unique_ptr<SfxChildWin_Impl>(pCW) );
1979 if ( pCW->bCreate != bOn )
1980 pWork->ToggleChildWindow_Impl(nId,bSetFocus);
1984 void SfxWorkWindow::ShowChildWindow_Impl(sal_uInt16 nId, bool bVisible, bool bSetFocus)
1986 sal_uInt16 nCount = aChildWins.size();
1987 SfxChildWin_Impl* pCW=nullptr;
1988 sal_uInt16 n;
1989 for (n=0; n<nCount; n++)
1991 pCW = aChildWins[n].get();
1992 if (pCW->nId == nId)
1993 break;
1996 if ( n<nCount )
1998 SfxChildWindow *pChildWin = pCW->pWin;
1999 if ( pChildWin )
2001 if ( bVisible )
2003 if ( pCW->pCli )
2005 pCW->pCli->bSetFocus = bSetFocus;
2006 pCW->pCli->nVisible = SfxChildVisibility::VISIBLE;
2007 pChildWin->Show( bSetFocus && pChildWin->WantsFocus() ? ShowFlags::NONE : ShowFlags::NoFocusChange | ShowFlags::NoActivate );
2009 else
2010 static_cast<SfxDockingWindow*>(pChildWin->GetWindow())->Reappear_Impl();
2013 else
2015 if ( pCW->pCli )
2017 pCW->pCli->nVisible = SfxChildVisibility::VISIBLE ^ SfxChildVisibility::NOT_HIDDEN;
2018 pCW->pWin->Hide();
2020 else
2021 static_cast<SfxDockingWindow*>(pChildWin->GetWindow())->Disappear_Impl();
2025 ArrangeChildren_Impl();
2026 ShowChildren_Impl();
2028 else if ( bVisible )
2030 SetChildWindow_Impl( nId, true, bSetFocus );
2031 pChildWin = pCW->pWin;
2034 if ( pChildWin )
2036 pChildWin->SetVisible_Impl( bVisible );
2037 SfxChildWindowFlags nFlags = pCW->aInfo.nFlags;
2038 pCW->aInfo = pChildWin->GetInfo();
2039 pCW->aInfo.nFlags |= nFlags;
2040 if ( !pCW->bCreate )
2041 SaveStatus_Impl( pChildWin, pCW->aInfo );
2044 return;
2047 #ifdef DBG_UTIL
2048 nCount = aChildWins.size();
2049 for (n=0; n<nCount; n++)
2050 if (aChildWins[n]->nSaveId == nId)
2051 break;
2053 if ( n<nCount )
2055 OSL_FAIL("The ChildWindow is not in context!");
2057 else
2059 OSL_FAIL("The ChildWindow is not registered");
2061 #endif
2065 SfxChildWindow* SfxWorkWindow::GetChildWindow_Impl(sal_uInt16 nId)
2067 sal_uInt16 nCount = aChildWins.size();
2068 sal_uInt16 n;
2069 for (n=0; n<nCount; n++)
2070 if (aChildWins[n]->nSaveId == nId)
2071 break;
2073 if (n<nCount)
2074 return aChildWins[n]->pWin;
2075 return nullptr;
2079 void SfxWorkWindow::ResetChildWindows_Impl()
2081 for (std::unique_ptr<SfxChildWin_Impl>& pChildWin : aChildWins)
2083 pChildWin->nId = 0;
2084 pChildWin->bEnable = false;
2088 // returns the size of the area (client area) of the
2089 // parent windows, in which the ChildWindow can be fitted.
2091 tools::Rectangle SfxWorkWindow::GetTopRect_Impl() const
2093 return pMasterFrame->GetTopOuterRectPixel_Impl();
2097 // Virtual method to find out if there is room for a ChildWindow in the
2098 // client area of the parent.
2100 bool SfxWorkWindow::RequestTopToolSpacePixel_Impl( SvBorder aBorder )
2102 return !(!IsDockingAllowed() ||
2103 aClientArea.GetWidth() < aBorder.Left() + aBorder.Right() ||
2104 aClientArea.GetHeight() < aBorder.Top() + aBorder.Bottom());
2107 void SfxWorkWindow::SaveStatus_Impl(SfxChildWindow *pChild, const SfxChildWinInfo &rInfo)
2109 // The Status of the Presentation mode is not saved
2110 if ( IsDockingAllowed() && bInternalDockingAllowed )
2111 pChild->SaveStatus(rInfo);
2114 void SfxWorkWindow::InitializeChild_Impl(SfxChildWin_Impl *pCW)
2116 SfxDispatcher *pDisp = pBindings->GetDispatcher_Impl();
2117 SfxViewFrame *pViewFrame = pDisp ? pDisp->GetFrame() :nullptr;
2118 SfxModule *pMod = pViewFrame ? SfxModule::GetActiveModule(pViewFrame) :nullptr;
2120 OUString sModule;
2121 if (pViewFrame)
2125 uno::Reference< frame::XModuleManager2 > xModuleManager(
2126 frame::ModuleManager::create(::comphelper::getProcessComponentContext()));
2127 sModule = xModuleManager->identify(pViewFrame->GetFrame().GetFrameInterface());
2128 SvtModuleOptions::EFactory eFac = SvtModuleOptions::ClassifyFactoryByServiceName(sModule);
2129 sModule = SvtModuleOptions::GetFactoryShortName(eFac);
2131 catch (...)
2136 SfxChildWinFactory* pFact=nullptr;
2137 SfxApplication *pApp = SfxGetpApp();
2139 pFact = pApp->GetChildWinFactoryById(pCW->nSaveId);
2140 if ( pFact )
2142 pCW->aInfo = pFact->aInfo;
2143 pCW->aInfo.aModule = sModule;
2144 SfxChildWindow::InitializeChildWinFactory_Impl(
2145 pCW->nSaveId, pCW->aInfo);
2146 pCW->bCreate = pCW->aInfo.bVisible;
2147 SfxChildWindowFlags nFlags = pFact->aInfo.nFlags;
2148 if ( nFlags & SfxChildWindowFlags::TASK )
2149 pCW->aInfo.nFlags |= SfxChildWindowFlags::TASK;
2150 if ( nFlags & SfxChildWindowFlags::CANTGETFOCUS )
2151 pCW->aInfo.nFlags |= SfxChildWindowFlags::CANTGETFOCUS;
2152 if ( nFlags & SfxChildWindowFlags::FORCEDOCK )
2153 pCW->aInfo.nFlags |= SfxChildWindowFlags::FORCEDOCK;
2154 pFact->aInfo = pCW->aInfo;
2155 return;
2159 if ( !pMod )
2160 return;
2162 pFact = pMod->GetChildWinFactoryById(pCW->nSaveId);
2163 if ( !pFact )
2164 return;
2166 pCW->aInfo = pFact->aInfo;
2167 pCW->aInfo.aModule = sModule;
2168 SfxChildWindow::InitializeChildWinFactory_Impl(
2169 pCW->nSaveId, pCW->aInfo);
2170 pCW->bCreate = pCW->aInfo.bVisible;
2171 SfxChildWindowFlags nFlags = pFact->aInfo.nFlags;
2172 if ( nFlags & SfxChildWindowFlags::TASK )
2173 pCW->aInfo.nFlags |= SfxChildWindowFlags::TASK;
2174 if ( nFlags & SfxChildWindowFlags::CANTGETFOCUS )
2175 pCW->aInfo.nFlags |= SfxChildWindowFlags::CANTGETFOCUS;
2176 if ( nFlags & SfxChildWindowFlags::FORCEDOCK )
2177 pCW->aInfo.nFlags |= SfxChildWindowFlags::FORCEDOCK;
2178 if ( nFlags & SfxChildWindowFlags::ALWAYSAVAILABLE )
2179 pCW->aInfo.nFlags |= SfxChildWindowFlags::ALWAYSAVAILABLE;
2180 pFact->aInfo = pCW->aInfo;
2183 SfxSplitWindow* SfxWorkWindow::GetSplitWindow_Impl( SfxChildAlignment eAlign )
2185 switch ( eAlign )
2187 case SfxChildAlignment::TOP:
2188 return pSplit[2];
2190 case SfxChildAlignment::BOTTOM:
2191 return pSplit[3];
2193 case SfxChildAlignment::LEFT:
2194 return pSplit[0];
2196 case SfxChildAlignment::RIGHT:
2197 return pSplit[1];
2199 default:
2200 return nullptr;
2204 void SfxWorkWindow::MakeChildrenVisible_Impl( bool bVis )
2206 bAllChildrenVisible = bVis;
2207 if ( bVis )
2209 if ( !bSorted )
2210 Sort_Impl();
2211 for (sal_uInt16 n : aSortedList)
2213 SfxChild_Impl* pCli = aChildren[n].get();
2214 if ( (pCli->eAlign == SfxChildAlignment::NOALIGNMENT) || (IsDockingAllowed() && bInternalDockingAllowed) )
2215 pCli->nVisible |= SfxChildVisibility::ACTIVE;
2218 else
2220 if ( !bSorted )
2221 Sort_Impl();
2222 for (sal_uInt16 n : aSortedList)
2224 SfxChild_Impl* pCli = aChildren[n].get();
2225 pCli->nVisible &= ~SfxChildVisibility::ACTIVE;
2230 bool SfxWorkWindow::IsAutoHideMode( const SfxSplitWindow *pSplitWin )
2232 for (const VclPtr<SfxSplitWindow> & pWin : pSplit)
2234 if ( pWin.get() != pSplitWin && pWin->IsAutoHide( true ) )
2235 return true;
2237 return false;
2241 void SfxWorkWindow::EndAutoShow_Impl( Point aPos )
2243 for (VclPtr<SfxSplitWindow> & p : pSplit)
2245 if ( p && p->IsAutoHide(false) )
2247 Point aLocalPos = p->ScreenToOutputPixel( aPos );
2248 tools::Rectangle aRect( Point(), p->GetSizePixel() );
2249 if ( !aRect.Contains( aLocalPos ) )
2250 p->FadeOut();
2255 void SfxWorkWindow::ArrangeAutoHideWindows( SfxSplitWindow *pActSplitWin )
2257 if ( m_nLock )
2258 return;
2260 tools::Rectangle aArea( aUpperClientArea );
2261 for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX; n++ )
2263 // Either dummy window or window in the auto-show-mode are processed
2264 // (not pinned, FadeIn).
2265 // Only the abandoned window may be invisible, because perhaps its
2266 // size is just being calculated before it is displayed.
2267 VclPtr<SfxSplitWindow> const & pSplitWin = pSplit[n];
2268 bool bDummyWindow = !pSplitWin->IsFadeIn();
2269 vcl::Window *pDummy = pSplitWin->GetSplitWindow();
2270 vcl::Window *pWin = bDummyWindow ? pDummy : pSplitWin;
2271 if ( (pSplitWin->IsPinned() && !bDummyWindow) || (!pWin->IsVisible() && pActSplitWin != pSplitWin) )
2272 continue;
2274 // Width and position of the dummy window as a starting point
2275 Size aSize = pDummy->GetSizePixel();
2276 Point aPos = pDummy->GetPosPixel();
2278 switch ( n )
2280 case 0 :
2282 // Left SplitWindow
2283 // Get the width of the Window yourself, if no DummyWindow
2284 if ( !bDummyWindow )
2285 aSize.setWidth( pSplitWin->GetSizePixel().Width() );
2287 // If a Window is visible to the left, then the free region
2288 // starts to the right from it, for example at the Client area
2289 tools::Long nLeft = aPos.X() + aSize.Width();
2290 if ( nLeft > aArea.Left() )
2291 aArea.SetLeft( nLeft );
2292 break;
2294 case 1 :
2296 // Right SplitWindow
2297 // Position to correct the difference of the widths
2298 aPos.AdjustX(aSize.Width() );
2300 // Get the width of the Window yourself, if no DummyWindow
2301 if ( !bDummyWindow )
2302 aSize.setWidth( pSplitWin->GetSizePixel().Width() );
2304 aPos.AdjustX( -(aSize.Width()) );
2306 // If already a window is opened at the left side, then the
2307 // right is not allowed to overlap this one.
2308 if ( aPos.X() < aArea.Left() )
2310 aPos.setX( aArea.Left() );
2311 aSize.setWidth( aArea.GetWidth() );
2314 // If a Window is visible to the right, then the free region
2315 // starts to the left from it, for example at the Client area
2316 tools::Long nRight = aPos.X();
2317 if ( !aArea.IsWidthEmpty() && nRight < aArea.Right() )
2318 aArea.SetRight( nRight );
2319 break;
2321 case 2 :
2323 // Top SplitWindow
2324 // Get the height of the Window yourself, if no DummyWindow
2325 if ( !bDummyWindow )
2326 aSize.setHeight( pSplitWin->GetSizePixel().Height() );
2329 // Adjust width with regard to if a Window is already open
2330 // to the left or right
2331 aPos.setX( aArea.Left() );
2332 aSize.setWidth( aArea.GetWidth() );
2334 // If a Window is visible at the top, then the free region
2335 // starts beneath it, for example at the Client area
2336 tools::Long nTop = aPos.Y() + aSize.Height();
2337 if ( nTop > aArea.Top() )
2338 aArea.SetTop( nTop );
2339 break;
2341 case 3 :
2343 // The bottom SplitWindow
2344 // Position to correct the difference of the heights
2345 aPos.AdjustY(aSize.Height() );
2347 // Get the height of the Window yourself, if no DummyWindow
2348 if ( !bDummyWindow )
2349 aSize.setHeight( pSplitWin->GetSizePixel().Height() );
2351 aPos.AdjustY( -(aSize.Height()) );
2353 // Adjust width with regard to if a Window is already open
2354 // to the left or right.
2355 aPos.setX( aArea.Left() );
2356 aSize.setWidth( aArea.GetWidth() );
2358 // If already a window is opened at the top, then the
2359 // bottom one is not allowed to overlap this one.
2360 if ( aPos.Y() < aArea.Top() )
2362 aPos.setY( aArea.Top() );
2363 aSize.setHeight( aArea.GetHeight() );
2366 break;
2370 if ( !bDummyWindow )
2371 // the FadeIn-Window is a Floating window, which coordinates are
2372 // set in Screen coordinates.
2373 pSplitWin->SetPosSizePixel( pWorkWin->OutputToScreenPixel(aPos), aSize );
2374 else
2375 // the docked DummyWindow
2376 pDummy->SetPosSizePixel( aPos, aSize );
2380 tools::Rectangle SfxWorkWindow::GetFreeArea( bool bAutoHide ) const
2382 if ( bAutoHide )
2384 tools::Rectangle aArea( aClientArea );
2385 for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX; n++ )
2387 if ( pSplit[n]->IsPinned() || !pSplit[n]->IsVisible() )
2388 continue;
2390 Size aSize = pSplit[n]->GetSizePixel();
2391 switch ( n )
2393 case 0 :
2394 aArea.AdjustLeft(aSize.Width() );
2395 break;
2396 case 1 :
2397 aArea.AdjustRight( -(aSize.Width()) );
2398 break;
2399 case 2 :
2400 aArea.AdjustTop(aSize.Height() );
2401 break;
2402 case 3 :
2403 aArea.AdjustBottom( -(aSize.Height()) );
2404 break;
2408 return aArea;
2410 else
2411 return aClientArea;
2414 void SfxWorkWindow::SetActiveChild_Impl( vcl::Window *pChild )
2416 pActiveChild = pChild;
2419 void SfxWorkWindow::DataChanged_Impl()
2421 ArrangeChildren_Impl();
2424 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */