Bug Summary

File:home/maarten/src/libreoffice/core/sfx2/source/appl/workwin.cxx
Warning:line 1863, column 53
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name workwin.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SFX2_DLLIMPLEMENTATION -D ENABLE_CUPS -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/liborcus/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/liborcus/include -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sfx2/inc -I /home/maarten/src/libreoffice/core/sfx2/source/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sfx2/sdi -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/sfx2/source/appl/workwin.cxx
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <config_features.h>
21#include <config_feature_desktop.h>
22#include <comphelper/lok.hxx>
23#include <comphelper/processfactory.hxx>
24#include <osl/diagnose.h>
25
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>
56
57using namespace ::com::sun::star;
58using namespace ::com::sun::star::uno;
59
60namespace {
61
62struct ResIdToResName
63{
64 ToolbarId eId;
65 const char* pName;
66};
67
68}
69
70const ResIdToResName pToolBarResToName[] =
71{
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, "" }
125};
126
127// Sort the Children according their alignment
128// The order corresponds to the enum SfxChildAlignment (->CHILDWIN.HXX).
129
130constexpr OUStringLiteral g_aLayoutManagerPropName = u"LayoutManager";
131
132// Help to make changes to the alignment compatible!
133LayoutManagerListener::LayoutManagerListener(
134 SfxWorkWindow* pWrkWin ) :
135 m_bHasFrame( false ),
136 m_pWrkWin( pWrkWin )
137{
138}
139
140LayoutManagerListener::~LayoutManagerListener()
141{
142}
143
144void LayoutManagerListener::setFrame( const css::uno::Reference< css::frame::XFrame >& xFrame )
145{
146 SolarMutexGuard aGuard;
147 if ( !m_pWrkWin || m_bHasFrame )
148 return;
149
150 m_xFrame = xFrame;
151 m_bHasFrame = true;
152
153 if ( !xFrame.is() )
154 return;
155
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;
160
161 try
162 {
163 Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
164 aValue >>= xLayoutManager;
165
166 if ( xLayoutManager.is() )
167 xLayoutManager->addLayoutManagerEventListener(
168 css::uno::Reference< css::frame::XLayoutManagerListener >(
169 static_cast< OWeakObject* >( this ), css::uno::UNO_QUERY ));
170
171 xPropSet.set( xLayoutManager, UNO_QUERY );
172 if ( xPropSet.is() )
173 {
174 aValue = xPropSet->getPropertyValue( "LockCount" );
175 aValue >>= m_pWrkWin->m_nLock;
176 }
177 }
178 catch ( css::lang::DisposedException& )
179 {
180 }
181 catch ( const css::uno::RuntimeException& )
182 {
183 throw;
184 }
185 catch ( css::uno::Exception& )
186 {
187 }
188}
189
190
191// XComponent
192
193void SAL_CALL LayoutManagerListener::addEventListener(
194 const css::uno::Reference< css::lang::XEventListener >& )
195{
196 // do nothing, only internal class
197}
198
199void SAL_CALL LayoutManagerListener::removeEventListener(
200 const css::uno::Reference< css::lang::XEventListener >& )
201{
202 // do nothing, only internal class
203}
204
205void SAL_CALL LayoutManagerListener::dispose()
206{
207 SolarMutexGuard aGuard;
208
209 // reset member
210 m_pWrkWin = nullptr;
211
212 css::uno::Reference< css::frame::XFrame > xFrame( m_xFrame.get(), css::uno::UNO_QUERY );
213 if ( !xFrame.is() )
214 return;
215
216 m_xFrame.clear();
217 m_bHasFrame = false;
218
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;
223
224 try
225 {
226 css::uno::Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
227 aValue >>= xLayoutManager;
228
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 ));
234 }
235 catch ( css::lang::DisposedException& )
236 {
237 }
238 catch ( const css::uno::RuntimeException& )
239 {
240 throw;
241 }
242 catch ( css::uno::Exception& )
243 {
244 }
245}
246
247
248// XEventListener
249
250void SAL_CALL LayoutManagerListener::disposing(
251 const css::lang::EventObject& )
252{
253 SolarMutexGuard aGuard;
254 m_pWrkWin = nullptr;
255 m_bHasFrame = false;
256 m_xFrame.clear();
257}
258
259
260// XLayoutManagerEventListener
261
262void SAL_CALL LayoutManagerListener::layoutEvent(
263 const css::lang::EventObject&,
264 ::sal_Int16 eLayoutEvent,
265 const css::uno::Any& )
266{
267 SolarMutexGuard aGuard;
268 if ( !m_pWrkWin )
269 return;
270
271 if ( eLayoutEvent == css::frame::LayoutManagerEvents::VISIBLE )
272 {
273 m_pWrkWin->MakeVisible_Impl( true );
274 m_pWrkWin->ShowChildren_Impl();
275 m_pWrkWin->ArrangeChildren_Impl();
276 }
277 else if ( eLayoutEvent == css::frame::LayoutManagerEvents::INVISIBLE )
278 {
279 m_pWrkWin->MakeVisible_Impl( false );
280 m_pWrkWin->HideChildren_Impl();
281 m_pWrkWin->ArrangeChildren_Impl();
282 }
283 else if ( eLayoutEvent == css::frame::LayoutManagerEvents::LOCK )
284 {
285 m_pWrkWin->Lock_Impl( true );
286 }
287 else if ( eLayoutEvent == css::frame::LayoutManagerEvents::UNLOCK )
288 {
289 m_pWrkWin->Lock_Impl( false );
290 }
291}
292
293namespace
294{
295 struct ToolbarIdHash
296 {
297 size_t operator()(ToolbarId t) const
298 {
299 typedef std::underlying_type<ToolbarId>::type underlying_type;
300 return std::hash<underlying_type>()(static_cast<underlying_type>(t));
301 }
302 };
303
304 class FilledToolBarResIdToResourceURLMap
305 {
306 private:
307 typedef std::unordered_map<ToolbarId, OUString, ToolbarIdHash> ToolBarResIdToResourceURLMap;
308 ToolBarResIdToResourceURLMap m_aResIdToResourceURLMap;
309 public:
310 FilledToolBarResIdToResourceURLMap()
311 {
312 sal_Int32 nIndex( 0 );
313 while (pToolBarResToName[nIndex].eId != ToolbarId::None)
314 {
315 OUString aResourceURL( OUString::createFromAscii( pToolBarResToName[nIndex].pName ));
316 m_aResIdToResourceURLMap.emplace(pToolBarResToName[nIndex].eId, aResourceURL);
317 ++nIndex;
318 }
319 }
320
321 OUString findURL(ToolbarId eId) const
322 {
323 ToolBarResIdToResourceURLMap::const_iterator aIter = m_aResIdToResourceURLMap.find(eId);
324 if ( aIter != m_aResIdToResourceURLMap.end() )
325 return aIter->second;
326 return OUString();
327 }
328 };
329
330 class theFilledToolBarResIdToResourceURLMap
331 : public rtl::Static<FilledToolBarResIdToResourceURLMap,
332 theFilledToolBarResIdToResourceURLMap>
333 {
334 };
335}
336
337static OUString GetResourceURLFromToolbarId(ToolbarId eId)
338{
339 return theFilledToolBarResIdToResourceURLMap::get().findURL(eId);
340}
341
342static sal_uInt16 TbxMatch( sal_uInt16 nPos )
343{
344 switch ( nPos )
345 {
346 case SFX_OBJECTBAR_APPLICATION0 :
347 return 0;
348 case SFX_OBJECTBAR_OPTIONS7:
349 return 1;
350 case SFX_OBJECTBAR_MACRO3:
351 return 2;
352 case SFX_OBJECTBAR_OBJECT1:
353 return 3;
354 case SFX_OBJECTBAR_TOOLS2:
355 return 4;
356 case SFX_OBJECTBAR_FULLSCREEN4:
357 case SFX_OBJECTBAR_COMMONTASK6:
358 case SFX_OBJECTBAR_RECORDING5:
359 return nPos+1;
360 default:
361 return nPos;
362 }
363}
364
365static sal_uInt16 ChildAlignValue(SfxChildAlignment eAlign)
366{
367 sal_uInt16 ret = 17;
368
369 switch (eAlign)
370 {
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...
421 }
422
423 return ret;
424}
425
426void SfxWorkWindow::Sort_Impl()
427{
428 aSortedList.clear();
429 for (size_t i = 0; i < aChildren.size(); ++i)
430 {
431 SfxChild_Impl *pCli = aChildren[i].get();
432 if (pCli)
433 {
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 );
440 }
441 }
442
443 bSorted = true;
444}
445
446constexpr OUStringLiteral g_aStatusBarResName( u"private:resource/statusbar/statusbar" );
447constexpr OUStringLiteral g_aTbxTypeName( u"private:resource/toolbar/" );
448constexpr OUStringLiteral g_aProgressBarResName( u"private:resource/progressbar/progressbar" );
449
450// constructor for workwin of a Frame
451
452SfxWorkWindow::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_LOK0
464 bIsFullScreen( false ),
465#else // Fennec-based Android Viewer
466 bIsFullScreen( true ),
467#endif
468#if HAVE_FEATURE_DESKTOP1
469 bShowStatusBar( true ),
470#else
471 bShowStatusBar( sal_False((sal_Bool)0) ),
472#endif
473 m_nLock( 0 ),
474 pMasterFrame( pMaster ),
475 pFrame( pFrm )
476{
477 DBG_ASSERT (pBindings, "No Bindings!")do { if (true && (!(pBindings))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/workwin.cxx"
":" "477" ": "), "%s", "No Bindings!"); } } while (false)
;
478
479 pBindings->SetWorkWindow_Impl( std::unique_ptr<SfxWorkWindow>(this) );
480
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_MAX13; ++i)
484 aChildren.push_back( nullptr );
485
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 );
492
493 SfxShell* pConfigShell = pFrm->GetCurrentViewFrame();
494 if ( pConfigShell && pConfigShell->GetObjectShell() )
495 {
496 bShowStatusBar = ( !pConfigShell->GetObjectShell()->IsInPlaceActive() );
497 bDockingAllowed = true;
498 bInternalDockingAllowed = true;
499 }
500
501 // The required split windows (one for each side) can be created
502 for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX4; n++ )
503 {
504 // The SplitWindows excludes direct ChildWindows of the WorkWindows
505 // and receives the docked window.
506
507 SfxChildAlignment eAlign =
508 ( n == SFX_SPLITWINDOWS_LEFT0 ? SfxChildAlignment::LEFT :
509 n == SFX_SPLITWINDOWS_RIGHT1 ? SfxChildAlignment::RIGHT :
510 n == SFX_SPLITWINDOWS_TOP2 ? SfxChildAlignment::TOP :
511 SfxChildAlignment::BOTTOM );
512 VclPtr<SfxSplitWindow> pSplitWin = VclPtr<SfxSplitWindow>::Create(pWorkWin, eAlign, this, true );
513 pSplit[n] = pSplitWin;
514 }
515
516 nOrigMode = SfxVisibilityFlags::Standard;
517 nUpdateMode = SfxVisibilityFlags::Standard;
518}
519
520
521// Destructor
522
523SfxWorkWindow::~SfxWorkWindow()
524{
525
526 // Delete SplitWindows
527 for (VclPtr<SfxSplitWindow> & p : pSplit)
528 {
529 if (p->GetWindowCount())
530 ReleaseChild_Impl(*p);
531 p.disposeAndClear();
532 }
533
534 // Delete help structure for Child-Windows
535 DBG_ASSERT( aChildren.empty(), "dangling children" )do { if (true && (!(aChildren.empty()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/workwin.cxx"
":" "535" ": "), "%s", "dangling children"); } } while (false
)
;
536
537 if ( m_xLayoutManagerListener.is() )
538 m_xLayoutManagerListener->dispose();
539}
540
541void SfxWorkWindow::Lock_Impl( bool bLock )
542{
543 if ( bLock )
544 m_nLock++;
545 else
546 --m_nLock;
547 if ( m_nLock<0 )
548 {
549 OSL_FAIL("Lock count underflow!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/workwin.cxx"
":" "549" ": "), "%s", "Lock count underflow!"); } } while (
false)
;
550 assert(m_nLock >= 0)(static_cast <bool> (m_nLock >= 0) ? void (0) : __assert_fail
("m_nLock >= 0", "/home/maarten/src/libreoffice/core/sfx2/source/appl/workwin.cxx"
, 550, __extension__ __PRETTY_FUNCTION__))
;
551 m_nLock = 0;
552 }
553
554 if ( !m_nLock )
555 ArrangeChildren_Impl();
556}
557
558
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.
563
564void SfxWorkWindow::DeleteControllers_Impl()
565{
566
567 // Lock SplitWindows (which means suppressing the Resize-Reaction of the
568 // DockingWindows)
569 for (size_t n=0; n<SFX_SPLITWINDOWS_MAX4; n++ )
570 {
571 VclPtr<SfxSplitWindow> const &p = pSplit[n];
572 if (p->GetWindowCount())
573 p->Lock();
574 }
575
576 // Delete Child-Windows
577 while(!aChildWins.empty())
578 {
579 std::unique_ptr<SfxChildWin_Impl> pCW = std::move(*aChildWins.begin());
580 aChildWins.erase(aChildWins.begin());
581 SfxChildWindow *pChild = pCW->pWin;
582 if (pChild)
583 {
584 if (comphelper::LibreOfficeKit::isActive())
585 {
586 vcl::Window* pWindow = pChild->GetWindow();
587 if (pWindow)
588 {
589 pWindow->ReleaseLOKNotifier();
590 }
591 }
592 pChild->Hide();
593
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)
599 {
600 if (pChild->GetController())
601 ReleaseChild_Impl(*pChild->GetController());
602 else
603 ReleaseChild_Impl(*pChild->GetWindow());
604 }
605
606 pCW->pWin = nullptr;
607 pWorkWin->GetSystemWindow()->GetTaskPaneList()->RemoveWindow( pChild->GetWindow() );
608 pChild->Destroy();
609 }
610
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)!!
616 }
617
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() )
622 {
623 try
624 {
625 Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
626 aValue >>= xLayoutManager;
627 }
628 catch ( Exception& )
629 {
630 }
631 }
632
633 if ( xLayoutManager.is() )
634 {
635 xLayoutManager->reset();
636
637 // Delete StatusBar
638 ResetStatusBar_Impl();
639
640 // Delete ObjectBars (this is done last, so that aChildren does not
641 // receive dead Pointers)
642 for (SfxObjectBar_Impl & i : aObjBarList)
643 {
644 // Not every position must be occupied
645 ToolbarId eId = i.eId;
646 if (eId != ToolbarId::None)
647 i.eId = ToolbarId::None;
648 }
649 }
650
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;
655
656 nChildren = 0;
657}
658
659
660// for placing the child window.
661
662void SfxWorkWindow::ArrangeChildren_Impl( bool bForce )
663{
664 if ( pFrame->IsClosing_Impl() || ( m_nLock && !bForce ))
665 return;
666
667 SfxInPlaceClient *pClient = nullptr;
668 SfxViewFrame *pF = pFrame->GetCurrentViewFrame();
669 if ( pF && pF->GetViewShell() )
670 pClient = pF->GetViewShell()->GetIPClient();
671
672 if ( pClient )
673 return;
674
675 aClientArea = GetTopRect_Impl();
676 if ( aClientArea.IsEmpty() )
677 return;
678
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())
691
692 pMasterFrame->SetToolSpaceBorderPixel_Impl( aBorder );
693
694 ArrangeAutoHideWindows( nullptr );
695}
696
697void SfxWorkWindow::FlushPendingChildSizes()
698{
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)
704 {
705 SfxChild_Impl *pCli = aChildren[i].get();
706 if (!pCli || !pCli->pWin)
707 continue;
708 (void)pCli->pWin->GetSizePixel();
709 }
710}
711
712SvBorder SfxWorkWindow::Arrange_Impl()
713
714/* [Description]
715
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".
720*/
721{
722 //tdf#116865 trigger pending sizing timers now so we arrange
723 //with the final size of the client area.
724 //
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;
732
733 SvBorder aBorder;
734 if ( !nChildren )
735 return aBorder;
736
737 if (!bSorted)
738 Sort_Impl();
739
740 Point aPos;
741 Size aSize;
742 tools::Rectangle aTmp( aClientArea );
743
744 for (sal_uInt16 n : aSortedList)
745 {
746 SfxChild_Impl* pCli = aChildren[n].get();
747 if ( !pCli->pWin )
748 continue;
749
750 // First, we assume that there is room for the window.
751 pCli->nVisible |= SfxChildVisibility::FITS_IN;
752
753 // Skip invisible windows
754 if (pCli->nVisible != SfxChildVisibility::VISIBLE)
755 continue;
756
757 if ( pCli->bResize )
758 aSize = pCli->aSize;
759 else
760 aSize = pCli->pWin->GetSizePixel();
761
762 SvBorder aTemp = aBorder;
763 bool bAllowHiding = true;
764 switch ( pCli->eAlign )
765 {
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;
780
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;
795
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;
810
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;
825
826 default:
827 pCli->aSize = pCli->pWin->GetSizePixel();
828 pCli->bResize = false;
829 continue;
830 }
831
832 pCli->pWin->SetPosSizePixel( aPos, aSize );
833 pCli->bResize = false;
834 pCli->aSize = aSize;
835 if( bAllowHiding && !RequestTopToolSpacePixel_Impl( aBorder ) )
836 {
837 pCli->nVisible ^= SfxChildVisibility::FITS_IN;
838 aBorder = aTemp;
839 }
840 }
841
842 if ( aClientArea.GetWidth() >= aBorder.Left() + aBorder.Right() )
843 {
844 aClientArea.AdjustLeft(aBorder.Left() );
845 aClientArea.AdjustRight( -(aBorder.Right()) );
846 }
847 else
848 {
849 aBorder.Left() = aClientArea.Left();
850 aBorder.Right() = aClientArea.Right();
851 aClientArea.SetRight( aTmp.Left() );
852 aClientArea.SetLeft( aTmp.Left() );
853 }
854
855 if ( aClientArea.GetHeight() >= aBorder.Top() + aBorder.Bottom() )
856 {
857 aClientArea.AdjustTop(aBorder.Top() );
858 aClientArea.AdjustBottom( -(aBorder.Bottom()) );
859 }
860 else
861 {
862 aBorder.Top() = aClientArea.Top();
863 aBorder.Bottom() = aClientArea.Bottom();
864 aClientArea.SetTop(aTmp.Top());
865 aClientArea.SetBottom(aTmp.Top());
866 }
867
868 return IsDockingAllowed() ? aBorder : SvBorder();
869}
870
871bool SfxWorkWindow::PrepareClose_Impl()
872{
873 for (const std::unique_ptr<SfxChildWin_Impl> &pCW : aChildWins)
874 {
875 SfxChildWindow *pChild = pCW->pWin;
876 if ( pChild && !pChild->QueryClose() )
877 return false;
878 }
879
880 return true;
881}
882
883SfxChild_Impl* SfxWorkWindow::RegisterChild_Impl( vcl::Window& rWindow,
884 SfxChildAlignment eAlign )
885{
886 DBG_ASSERT( aChildren.size() < 255, "too many children" )do { if (true && (!(aChildren.size() < 255))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/workwin.cxx"
":" "886" ": "), "%s", "too many children"); } } while (false
)
;
887 DBG_ASSERT( SfxChildAlignValid(eAlign), "invalid align" )do { if (true && (!(SfxChildAlignValid(eAlign)))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/workwin.cxx"
":" "887" ": "), "%s", "invalid align"); } } while (false)
;
888 DBG_ASSERT( !FindChild_Impl(&rWindow), "child registered more than once" )do { if (true && (!(!FindChild_Impl(&rWindow)))) {
sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"
), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/workwin.cxx"
":" "888" ": "), "%s", "child registered more than once"); }
} while (false)
;
889
890
891 if ( rWindow.GetParent() != pWorkWin )
892 rWindow.SetParent( pWorkWin );
893
894 auto pChild = std::make_unique<SfxChild_Impl>(rWindow, rWindow.GetSizePixel(),
895 eAlign, rWindow.IsVisible());
896
897 aChildren.push_back(std::move(pChild));
898 bSorted = false;
899 nChildren++;
900 return aChildren.back().get();
901}
902
903SfxChild_Impl* SfxWorkWindow::RegisterChild_Impl(std::shared_ptr<SfxDialogController>& rController,
904 SfxChildAlignment eAlign )
905{
906 DBG_ASSERT( aChildren.size() < 255, "too many children" )do { if (true && (!(aChildren.size() < 255))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/workwin.cxx"
":" "906" ": "), "%s", "too many children"); } } while (false
)
;
907 DBG_ASSERT( SfxChildAlignValid(eAlign), "invalid align" )do { if (true && (!(SfxChildAlignValid(eAlign)))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/workwin.cxx"
":" "907" ": "), "%s", "invalid align"); } } while (false)
;
908
909 auto pChild = std::make_unique<SfxChild_Impl>(rController, eAlign);
910
911 aChildren.push_back(std::move(pChild));
912 bSorted = false;
913 nChildren++;
914 return aChildren.back().get();
915}
916
917void SfxWorkWindow::ReleaseChild_Impl( vcl::Window& rWindow )
918{
919
920 SfxChild_Impl *pChild = nullptr;
921 decltype(aChildren)::size_type nPos;
922 for ( nPos = 0; nPos < aChildren.size(); ++nPos )
923 {
924 pChild = aChildren[nPos].get();
925 if ( pChild && pChild->pWin == &rWindow )
926 {
927 bSorted = false;
928 nChildren--;
929 aChildren.erase(aChildren.begin() + nPos);
930 return;
931 }
932 }
933 OSL_FAIL( "releasing unregistered child" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/workwin.cxx"
":" "933" ": "), "%s", "releasing unregistered child"); } } while
(false)
;
934}
935
936void SfxWorkWindow::ReleaseChild_Impl(SfxDialogController& rController)
937{
938
939 SfxChild_Impl *pChild = nullptr;
940 decltype(aChildren)::size_type nPos;
941 for ( nPos = 0; nPos < aChildren.size(); ++nPos )
942 {
943 pChild = aChildren[nPos].get();
944 if (pChild && pChild->xController.get() == &rController)
945 {
946 bSorted = false;
947 nChildren--;
948 aChildren.erase(aChildren.begin() + nPos);
949 return;
950 }
951 }
952 OSL_FAIL( "releasing unregistered child" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/workwin.cxx"
":" "952" ": "), "%s", "releasing unregistered child"); } } while
(false)
;
953}
954
955SfxChild_Impl* SfxWorkWindow::FindChild_Impl( const vcl::Window* rWindow ) const
956{
957
958 sal_uInt16 nCount = aChildren.size();
959 for ( sal_uInt16 nPos = 0; nPos < nCount; ++nPos )
960 {
961 SfxChild_Impl *pChild = aChildren[nPos].get();
962 if ( pChild && pChild->pWin == rWindow )
963 return pChild;
964 }
965
966 return nullptr;
967}
968
969void SfxWorkWindow::ShowChildren_Impl()
970{
971 bool bInvisible = ( !IsVisible_Impl() || ( !pWorkWin->IsReallyVisible() && !pWorkWin->IsReallyShown() ));
972
973 for (std::unique_ptr<SfxChild_Impl>& pCli : aChildren)
974 {
975 if (!pCli)
976 continue;
977 SfxChildWin_Impl* pCW = nullptr;
978 if (pCli->pWin || pCli->xController)
979 {
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)
983 {
984 SfxChild_Impl* pChild = pCWin->pCli;
985 if ( pChild == pCli.get() )
986 {
987 pCW = pCWin.get();
988 break;
989 }
990 }
991
992 bool bVisible( !bInvisible );
993 if ( pCW )
994 {
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 );
1000 }
1001
1002 if ( SfxChildVisibility::VISIBLE == (pCli->nVisible & SfxChildVisibility::VISIBLE) && bVisible )
1003 {
1004 ShowFlags nFlags = pCli->bSetFocus ? ShowFlags::NONE : ShowFlags::NoFocusChange | ShowFlags::NoActivate;
1005 if (pCli->xController)
1006 {
1007 if (!pCli->xController->getDialog()->get_visible())
1008 {
1009 auto xController = pCli->xController;
1010 weld::DialogController::runAsync(xController,
1011 [=](sal_Int32 /*nResult*/){ xController->Close(); });
1012 }
1013 }
1014 else
1015 pCli->pWin->Show(true, nFlags);
1016 pCli->bSetFocus = false;
1017 }
1018 else
1019 {
1020 if (pCli->xController)
1021 {
1022 if (pCli->xController->getDialog()->get_visible())
1023 pCli->xController->response(RET_CLOSE);
1024 }
1025 else
1026 pCli->pWin->Hide();
1027 }
1028 }
1029 }
1030}
1031
1032
1033void SfxWorkWindow::HideChildren_Impl()
1034{
1035 for ( sal_uInt16 nPos = aChildren.size(); nPos > 0; --nPos )
1036 {
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();
1044 }
1045}
1046
1047void SfxWorkWindow::ResetObjectBars_Impl()
1048{
1049 for ( auto & n: aObjBarList )
1050 n.bDestroy = true;
1051
1052 for ( auto & n: aChildWins )
1053 n->nId = 0;
1054}
1055
1056void SfxWorkWindow::SetObjectBar_Impl(sal_uInt16 nPos, SfxVisibilityFlags nFlags, ToolbarId eId)
1057{
1058 DBG_ASSERT( nPos < SFX_OBJECTBAR_MAX, "object bar position overflow" )do { if (true && (!(nPos < 13))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/workwin.cxx"
":" "1058" ": "), "%s", "object bar position overflow"); } }
while (false)
;
1059
1060 SfxObjectBar_Impl aObjBar;
1061 aObjBar.eId = eId;
1062 aObjBar.nMode = nFlags;
1063
1064 for (SfxObjectBar_Impl & rBar : aObjBarList)
1065 {
1066 if ( rBar.eId == aObjBar.eId )
1067 {
1068 rBar = aObjBar;
1069 return;
1070 }
1071 }
1072
1073 aObjBarList.push_back( aObjBar );
1074}
1075
1076bool SfxWorkWindow::IsVisible_Impl( SfxVisibilityFlags nMode ) const
1077{
1078 switch( nUpdateMode )
1079 {
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;
1090 }
1091}
1092
1093void SfxWorkWindow::UpdateObjectBars_Impl()
1094{
1095 if ( pFrame->IsClosing_Impl() )
1096 return;
1097
1098 UpdateObjectBars_Impl2();
1099
1100 {
1101 ArrangeChildren_Impl( false );
1102
1103 ShowChildren_Impl();
1104 }
1105
1106 ShowChildren_Impl();
1107}
1108
1109Reference< css::task::XStatusIndicator > SfxWorkWindow::GetStatusIndicator()
1110{
1111 Reference< css::beans::XPropertySet > xPropSet( GetFrameInterface(), UNO_QUERY );
1112 Reference< css::frame::XLayoutManager > xLayoutManager;
1113 Reference< css::task::XStatusIndicator > xStatusIndicator;
1114
1115 if ( xPropSet.is() )
1116 {
1117 Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
1118 aValue >>= xLayoutManager;
1119 if ( xLayoutManager.is() )
1120 {
1121 xLayoutManager->createElement( g_aProgressBarResName );
1122 xLayoutManager->showElement( g_aProgressBarResName );
1123
1124 Reference< css::ui::XUIElement > xProgressBar =
1125 xLayoutManager->getElement( g_aProgressBarResName );
1126 if ( xProgressBar.is() )
1127 {
1128 xStatusIndicator.set( xProgressBar->getRealInterface(), UNO_QUERY );
1129 }
1130 }
1131 }
1132
1133 return xStatusIndicator;
1134}
1135
1136
1137bool SfxWorkWindow::IsPluginMode( SfxObjectShell const * pObjShell )
1138{
1139 if ( pObjShell && pObjShell->GetMedium() )
1140 {
1141 const SfxBoolItem* pViewOnlyItem = SfxItemSet::GetItem<SfxBoolItem>(pObjShell->GetMedium()->GetItemSet(), SID_VIEWONLY(5000 + 1682), false);
1142 if ( pViewOnlyItem && pViewOnlyItem->GetValue() )
1143 return true;
1144 }
1145
1146 return false;
1147}
1148
1149
1150css::uno::Reference< css::frame::XFrame > SfxWorkWindow::GetFrameInterface()
1151{
1152 css::uno::Reference< css::frame::XFrame > xFrame;
1153
1154 SfxDispatcher* pDispatcher( GetBindings().GetDispatcher() );
1155 if ( pDispatcher )
1156 {
1157 SfxViewFrame* pViewFrame = pDispatcher->GetFrame();
1158 if ( pViewFrame )
1159 xFrame = pViewFrame->GetFrame().GetFrameInterface();
1160 }
1161
1162 return xFrame;
1163}
1164
1165
1166void SfxWorkWindow::UpdateObjectBars_Impl2()
1167{
1168 // Lock SplitWindows (which means suppressing the Resize-Reaction of the
1169 // DockingWindows)
1170 for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX4; n++ )
1171 {
1172 VclPtr<SfxSplitWindow> const & p = pSplit[n];
1173 if (p->GetWindowCount())
1174 p->Lock();
1175 }
1176
1177 Reference< css::beans::XPropertySet > xPropSet( GetFrameInterface(), UNO_QUERY );
1178 Reference< css::frame::XLayoutManager > xLayoutManager;
1179
1180 if ( xPropSet.is() )
1181 {
1182 Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
1183 aValue >>= xLayoutManager;
1184 }
1185
1186 if ( !xLayoutManager.is() )
1187 return;
1188
1189 bool bPluginMode( false );
1190 SfxDispatcher* pDispatcher( GetBindings().GetDispatcher() );
1191
1192 if ( pDispatcher )
1193 {
1194 SfxViewFrame* pViewFrame = pDispatcher->GetFrame();
1195 if ( pViewFrame )
1196 bPluginMode = IsPluginMode( pViewFrame->GetObjectShell() );
1197 }
1198
1199 // Iterate over all Toolboxes
1200 xLayoutManager->lock();
1201 for ( auto const & n: aObjBarList )
1202 {
1203 ToolbarId eId = n.eId;
1204 bool bDestroy = n.bDestroy;
1205
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;
1211
1212 // Is a ToolBox required in this context ?
1213 bool bModesMatching = (nUpdateMode != SfxVisibilityFlags::Invisible) && ((nTbxMode & nUpdateMode) == nUpdateMode);
1214 if ( bDestroy || sfx2::SfxNotebookBar::IsActive())
1215 {
1216 OUString aTbxId = g_aTbxTypeName + GetResourceURLFromToolbarId(eId);
1217 xLayoutManager->destroyElement( aTbxId );
1218 }
1219 else if ( eId != ToolbarId::None && ( ( bModesMatching && !bIsFullScreen ) ||
1220 ( bIsFullScreen && bFullScreenTbx ) ) )
1221 {
1222 OUString aTbxId = g_aTbxTypeName + GetResourceURLFromToolbarId(eId);
1223 if ( !IsDockingAllowed() && !xLayoutManager->isElementFloating( aTbxId ))
1224 xLayoutManager->destroyElement( aTbxId );
1225 else
1226 {
1227 xLayoutManager->requestElement( aTbxId );
1228 if ( bPluginMode )
1229 xLayoutManager->lockWindow( aTbxId );
1230 }
1231 }
1232 else if ( eId != ToolbarId::None )
1233 {
1234 // Delete the Toolbox at this Position if possible
1235 OUString aTbxId = g_aTbxTypeName + GetResourceURLFromToolbarId(eId);
1236 xLayoutManager->destroyElement( aTbxId );
1237 }
1238 }
1239
1240 UpdateStatusBar_Impl();
1241
1242 // unlocking automatically forces Layout
1243 xLayoutManager->unlock();
1244
1245 UpdateChildWindows_Impl();
1246
1247 // Unlock the SplitWindows again
1248 for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX4; n++ )
1249 {
1250 VclPtr<SfxSplitWindow> const & p = pSplit[n];
1251 if (p->GetWindowCount())
1252 p->Lock(false);
1253 }
1254}
1255
1256void SfxWorkWindow::UpdateChildWindows_Impl()
1257{
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++ )
1261 {
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 ) ) )
1267 {
1268 // In the context is an appropriate ChildWindow allowed;
1269 // it is also turned on?
1270 if ( pChildWin == nullptr && pCW->bCreate )
1271 {
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 )
1276 {
1277 // Special case for all non-floatable child windows. We have
1278 // to prevent the creation here!
1279 bCreate = !( pCW->aInfo.nFlags & SfxChildWindowFlags::FORCEDOCK );
1280 }
1281 else if ( !IsDockingAllowed() || bIsFullScreen ) // || !bInternalDocking )
1282 {
1283 // In Presentation mode or FullScreen only FloatingWindows
1284 SfxChildAlignment eAlign;
1285 if ( pCW->aInfo.GetExtraData_Impl( &eAlign ) )
1286 bCreate = ( eAlign == SfxChildAlignment::NOALIGNMENT );
1287 }
1288 else
1289 bCreate = true;
1290
1291 if (pCW->aInfo.nFlags & SfxChildWindowFlags::NEVERCLONE)
1292 pCW->bCreate = bCreate = false; // Don't create and remember that we haven't created.
1293
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 );
1298
1299 if ( !bAllChildrenVisible && pCW->pCli )
1300 pCW->pCli->nVisible &= ~SfxChildVisibility::ACTIVE;
1301 }
1302 else if ( pChildWin )
1303 {
1304 // Window already exists, it should also be visible?
1305 if ( ( !bIsFullScreen || pChildWin->GetAlignment() == SfxChildAlignment::NOALIGNMENT ) && bAllChildrenVisible )
1306 {
1307 // Update Mode is compatible; definitely enable it
1308 bCreate = true;
1309 if ( pCW->pCli )
1310 {
1311 // The window is a direct Child
1312 if ((IsDockingAllowed() && bInternalDockingAllowed)
1313 || pCW->pCli->eAlign == SfxChildAlignment::NOALIGNMENT)
1314 pCW->pCli->nVisible |= SfxChildVisibility::NOT_HIDDEN;
1315 }
1316 else
1317 {
1318 if ( pCW->bCreate && IsDockingAllowed() && bInternalDockingAllowed )
1319 // The window ia within a SplitWindow
1320 static_cast<SfxDockingWindow*>(pChildWin->GetWindow())->Reappear_Impl();
1321 }
1322
1323 if ( pCW->nInterfaceId != pChildWin->GetContextId() )
1324 pChildWin->CreateContext( pCW->nInterfaceId, GetBindings() );
1325 }
1326 }
1327 }
1328
1329 if ( pChildWin && !bCreate )
1330 {
1331 if ( !pChildWin->QueryClose() || pChildWin->IsHideNotDelete() || Application::IsUICaptured() )
1332 {
1333 if ( pCW->pCli )
1334 {
1335 if ( pCW->pCli->nVisible & SfxChildVisibility::NOT_HIDDEN )
1336 pCW->pCli->nVisible ^= SfxChildVisibility::NOT_HIDDEN;
1337 }
1338 else
1339 static_cast<SfxDockingWindow*>(pChildWin->GetWindow())->Disappear_Impl();
1340 }
1341 else
1342 RemoveChildWin_Impl( pCW );
1343 }
1344 }
1345}
1346
1347void SfxWorkWindow::CreateChildWin_Impl( SfxChildWin_Impl *pCW, bool bSetFocus )
1348{
1349 pCW->aInfo.bVisible = true;
1350
1351 SfxChildWindow *pChildWin = SfxChildWindow::CreateChildWindow( pCW->nId, pWorkWin, &GetBindings(), pCW->aInfo).release();
1352 if (!pChildWin)
1353 return;
1354
1355 if ( bSetFocus )
1356 bSetFocus = pChildWin->WantsFocus();
1357 pChildWin->SetWorkWindow_Impl( this );
1358
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;
1365
1366 // The creation was successful
1367 GetBindings().Invalidate(pCW->nId);
1368
1369 sal_uInt16 nPos = pChildWin->GetPosition();
1370 if (nPos != CHILDWIN_NOPOS(32767 *2 +1))
1371 {
1372 DBG_ASSERT(nPos < SFX_OBJECTBAR_MAX, "Illegal objectbar position!")do { if (true && (!(nPos < 13))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/workwin.cxx"
":" "1372" ": "), "%s", "Illegal objectbar position!"); } } while
(false)
;
1373 if ( aChildren[TbxMatch(nPos)] )// &&
1374 {
1375 // ChildWindow replaces ObjectBar
1376 aChildren[TbxMatch(nPos)]->nVisible ^= SfxChildVisibility::NOT_HIDDEN;
1377 }
1378 }
1379
1380 // make childwin keyboard accessible
1381 pWorkWin->GetSystemWindow()->GetTaskPaneList()->AddWindow( pChildWin->GetWindow() );
1382
1383 pCW->pWin = pChildWin;
1384
1385 if ( pChildWin->GetAlignment() == SfxChildAlignment::NOALIGNMENT || pChildWin->GetWindow()->GetParent() == pWorkWin)
1386 {
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;
1397 }
1398 else
1399 {
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!
1403 }
1404
1405 if ( pCW->nInterfaceId != pChildWin->GetContextId() )
1406 pChildWin->CreateContext( pCW->nInterfaceId, GetBindings() );
1407
1408 // Save the information in the INI file
1409 SaveStatus_Impl(pChildWin, pCW->aInfo);
1410}
1411
1412void SfxWorkWindow::RemoveChildWin_Impl( SfxChildWin_Impl *pCW )
1413{
1414 sal_uInt16 nId = pCW->nSaveId;
1415 SfxChildWindow *pChildWin = pCW->pWin;
1416
1417 // Save the information in the INI file
1418 SfxChildWindowFlags nFlags = pCW->aInfo.nFlags;
1419 pCW->aInfo = pChildWin->GetInfo();
1420 pCW->aInfo.nFlags |= nFlags;
49
Value assigned to field 'bCreate', which participates in a condition later
50
Value assigned to field 'pCli', which participates in a condition later
1421 SaveStatus_Impl(pChildWin, pCW->aInfo);
1422
1423 pChildWin->Hide();
1424
1425 if ( pCW->pCli )
51
Assuming field 'pCli' is null, which participates in a condition later
52
Taking false branch
1426 {
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());
1434 }
1435 else
1436 {
1437 // ChildWindow is within a SplitWindow and unregister itself in
1438 // the destructor.
1439 }
1440
1441 pWorkWin->GetSystemWindow()->GetTaskPaneList()->RemoveWindow( pChildWin->GetWindow() );
1442 pCW->pWin = nullptr;
53
Null pointer value stored to field 'pWin'
1443 pChildWin->Destroy();
1444
1445 GetBindings().Invalidate( nId );
1446}
1447
1448void SfxWorkWindow::ResetStatusBar_Impl()
1449{
1450 aStatBar.eId = StatusBarId::None;
1451}
1452
1453void SfxWorkWindow::SetStatusBar_Impl(StatusBarId eId)
1454{
1455 if (eId != StatusBarId::None && bShowStatusBar && IsVisible_Impl())
1456 aStatBar.eId = eId;
1457}
1458
1459void SfxWorkWindow::UpdateStatusBar_Impl()
1460{
1461 Reference< css::beans::XPropertySet > xPropSet( GetFrameInterface(), UNO_QUERY );
1462 Reference< css::frame::XLayoutManager > xLayoutManager;
1463
1464 Any aValue = xPropSet->getPropertyValue( g_aLayoutManagerPropName );
1465 aValue >>= xLayoutManager;
1466
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)
1471 {
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 );
1476 }
1477 else
1478 {
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 );
1483 }
1484}
1485
1486void SfxWorkWindow::MakeVisible_Impl( bool bVis )
1487{
1488 if ( bVis )
1489 nOrigMode = SfxVisibilityFlags::Standard;
1490 else
1491 nOrigMode = SfxVisibilityFlags::Invisible;
1492
1493 if ( nOrigMode != nUpdateMode)
1494 nUpdateMode = nOrigMode;
1495}
1496
1497bool SfxWorkWindow::IsVisible_Impl() const
1498{
1499 return nOrigMode != SfxVisibilityFlags::Invisible;
1500}
1501
1502
1503void SfxWorkWindow::HidePopups_Impl(bool bHide, sal_uInt16 nId )
1504{
1505 if (comphelper::LibreOfficeKit::isActive() && bHide)
1506 return;
1507
1508 for (const std::unique_ptr<SfxChildWin_Impl>& i : aChildWins)
1509 {
1510 SfxChildWindow *pCW = i->pWin;
1511 if (pCW && pCW->GetAlignment() == SfxChildAlignment::NOALIGNMENT && pCW->GetType() != nId)
1512 {
1513 vcl::Window *pWin = pCW->GetWindow();
1514 SfxChild_Impl *pChild = FindChild_Impl(pWin);
1515 if (!pChild)
1516 {
1517 SAL_WARN("sfx.appl", "missing SfxChild_Impl child!")do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "sfx.appl")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case
SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "missing SfxChild_Impl child!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sfx.appl"
), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/workwin.cxx"
":" "1517" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "missing SfxChild_Impl child!"), 0);
} else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "missing SfxChild_Impl child!"; ::sal::detail::log(
(::SAL_DETAIL_LOG_LEVEL_WARN), ("sfx.appl"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/workwin.cxx"
":" "1517" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "missing SfxChild_Impl child!") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("sfx.appl"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/workwin.cxx"
":" "1517" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "missing SfxChild_Impl child!"), 0);
} else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "missing SfxChild_Impl child!"; ::sal::detail::log(
(::SAL_DETAIL_LOG_LEVEL_WARN), ("sfx.appl"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/workwin.cxx"
":" "1517" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1518 continue;
1519 }
1520 if (bHide)
1521 {
1522 pChild->nVisible &= ~SfxChildVisibility::ACTIVE;
1523 pCW->Hide();
1524 }
1525 else if ( !comphelper::LibreOfficeKit::isActive() ||
1526 SfxChildVisibility::ACTIVE != (pChild->nVisible & SfxChildVisibility::ACTIVE) )
1527 {
1528 pChild->nVisible |= SfxChildVisibility::ACTIVE;
1529 if ( SfxChildVisibility::VISIBLE == (pChild->nVisible & SfxChildVisibility::VISIBLE) )
1530 pCW->Show( ShowFlags::NoFocusChange | ShowFlags::NoActivate );
1531 }
1532 }
1533 }
1534}
1535
1536
1537void SfxWorkWindow::ConfigChild_Impl(SfxChildIdentifier eChild,
1538 SfxDockingConfig eConfig, sal_uInt16 nId)
1539{
1540 SfxDockingWindow* pDockWin=nullptr;
1541 sal_uInt16 nPos = USHRT_MAX(32767 *2 +1);
1542 vcl::Window *pWin=nullptr;
1543 SfxChildWin_Impl *pCW = nullptr;
1544
1545 // configure direct childwindow
1546 for (const std::unique_ptr<SfxChildWin_Impl>& i : aChildWins)
1547 {
1548 pCW = i.get();
1549 SfxChildWindow *pChild = pCW->pWin;
1550 if ( pChild && (pChild->GetType() == nId ))
1551 {
1552 if (SfxDockingWindow* pSfxDockingWindow = dynamic_cast<SfxDockingWindow*>(pChild->GetWindow()))
1553 {
1554 // it's a DockingWindow
1555 pDockWin = pSfxDockingWindow;
1556 }
1557 else
1558 {
1559 // FloatingWindow or ModelessDialog
1560 pWin = pChild->GetWindow();
1561 }
1562 break;
1563 }
1564 }
1565
1566 if ( pDockWin )
1567 {
1568 if ( eChild == SfxChildIdentifier::DOCKINGWINDOW || pDockWin->GetAlignment() == SfxChildAlignment::NOALIGNMENT )
1569 {
1570 if ( eChild == SfxChildIdentifier::SPLITWINDOW && eConfig == SfxDockingConfig::TOGGLEFLOATMODE)
1571 {
1572 // DockingWindow was dragged out of a SplitWindow
1573 pCW->pCli = RegisterChild_Impl(*pDockWin, pDockWin->GetAlignment());
1574 pCW->pCli->nVisible = SfxChildVisibility::VISIBLE;
1575 }
1576
1577 pWin = pDockWin;
1578 }
1579 else
1580 {
1581 SfxSplitWindow *pSplitWin = GetSplitWindow_Impl(pDockWin->GetAlignment());
1582
1583 // configure DockingWindow inside a SplitWindow
1584 if ( eConfig == SfxDockingConfig::TOGGLEFLOATMODE)
1585 {
1586 // DockingWindow was dragged into a SplitWindow
1587 pCW->pCli = nullptr;
1588 ReleaseChild_Impl(*pDockWin);
1589 }
1590
1591 pWin = pSplitWin->GetSplitWindow();
1592 if ( pSplitWin->GetWindowCount() == 1 )
1593 static_cast<SplitWindow*>(pWin)->Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
1594 }
1595 }
1596
1597 DBG_ASSERT( pCW, "Unknown window!" )do { if (true && (!(pCW))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/workwin.cxx"
":" "1597" ": "), "%s", "Unknown window!"); } } while (false
)
;
1598
1599 if ( !bSorted )
1600 // windows may have been registered and released without an update until now
1601 Sort_Impl();
1602
1603 decltype(aSortedList)::size_type n;
1604 for ( n=0; n<aSortedList.size(); ++n )
1605 {
1606 SfxChild_Impl *pChild = aChildren[aSortedList[n]].get();
1607 if ( pChild && pChild->pWin == pWin )
1608 break;
1609 }
1610
1611 if ( n < aSortedList.size() )
1612 // sometimes called while toggling float mode
1613 nPos = aSortedList[n];
1614
1615 switch ( eConfig )
1616 {
1617 case SfxDockingConfig::SETDOCKINGRECTS :
1618 {
1619 if (nPos == USHRT_MAX(32767 *2 +1) || !pDockWin)
1620 return;
1621
1622 tools::Rectangle aOuterRect( GetTopRect_Impl() );
1623 aOuterRect.SetPos( pWorkWin->OutputToScreenPixel( aOuterRect.TopLeft() ));
1624 tools::Rectangle aInnerRect( aOuterRect );
1625
1626 // The current affected window is included in the calculation of
1627 // the inner rectangle!
1628 for (sal_uInt16 i : aSortedList)
1629 {
1630 SfxChild_Impl* pCli = aChildren[i].get();
1631
1632 if ( pCli && pCli->nVisible == SfxChildVisibility::VISIBLE && pCli->pWin )
1633 {
1634 switch ( pCli->eAlign )
1635 {
1636 case SfxChildAlignment::TOP:
1637 // Object-Toolboxes come always last
1638 aInnerRect.AdjustTop(pCli->aSize.Height() );
1639 break;
1640
1641 case SfxChildAlignment::HIGHESTTOP:
1642 // Always performed first
1643 aInnerRect.AdjustTop(pCli->aSize.Height() );
1644 break;
1645
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;
1651
1652 case SfxChildAlignment::BOTTOM:
1653 // Object-Toolboxes come always last
1654 aInnerRect.AdjustBottom( -(pCli->aSize.Height()) );
1655 break;
1656
1657 case SfxChildAlignment::LOWESTBOTTOM:
1658 // Always performed first
1659 aInnerRect.AdjustBottom( -(pCli->aSize.Height()) );
1660 break;
1661
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;
1667
1668 case SfxChildAlignment::LEFT:
1669 // Toolboxes come always last
1670 aInnerRect.AdjustLeft(pCli->aSize.Width() );
1671 break;
1672
1673 case SfxChildAlignment::FIRSTLEFT:
1674 // Always performed first
1675 aInnerRect.AdjustLeft(pCli->aSize.Width() );
1676 break;
1677
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;
1683
1684 case SfxChildAlignment::RIGHT:
1685 // Toolboxes come always last
1686 aInnerRect.AdjustRight( -(pCli->aSize.Width()) );
1687 break;
1688
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;
1694
1695 case SfxChildAlignment::LASTRIGHT:
1696 // Always performed first
1697 aInnerRect.AdjustRight( -(pCli->aSize.Width()) );
1698 break;
1699
1700 default:
1701 break;
1702 }
1703 }
1704 }
1705
1706 pDockWin->SetDockingRects(aOuterRect, aInnerRect);
1707 break;
1708 }
1709
1710 case SfxDockingConfig::ALIGNDOCKINGWINDOW :
1711 case SfxDockingConfig::TOGGLEFLOATMODE:
1712 {
1713 if ( nPos == USHRT_MAX(32767 *2 +1) && !pCW )
1714 return;
1715
1716 SfxChildAlignment eAlign = SfxChildAlignment::NOALIGNMENT;
1717 SfxChild_Impl *pCli = ( nPos != USHRT_MAX(32767 *2 +1) ) ? aChildren[nPos].get() : nullptr;
1718 if ( pCli && pDockWin )
1719 {
1720 eAlign = pDockWin->GetAlignment();
1721 if ( eChild == SfxChildIdentifier::DOCKINGWINDOW || eAlign == SfxChildAlignment::NOALIGNMENT)
1722 {
1723 // configuration inside the SplitWindow, no change for the SplitWindows' configuration
1724 pCli->bResize = true;
1725 pCli->aSize = pDockWin->GetSizePixel();
1726 }
1727 }
1728
1729 if ( pCli )
1730 {
1731 if( pCli->eAlign != eAlign )
1732 {
1733 bSorted = false;
1734 pCli->eAlign = eAlign;
1735 }
1736
1737 ArrangeChildren_Impl();
1738 ShowChildren_Impl();
1739 }
1740
1741 if ( pCW && pCW->pWin )
1742 {
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);
1748 }
1749
1750 break;
1751 }
1752 }
1753}
1754
1755
1756void SfxWorkWindow::SetChildWindowVisible_Impl( sal_uInt32 lId, bool bEnabled, SfxVisibilityFlags nMode )
1757{
1758 sal_uInt16 nInter = static_cast<sal_uInt16>( lId >> 16 );
1759 sal_uInt16 nId = static_cast<sal_uInt16>( lId & 0xFFFF );
1760
1761 SfxChildWin_Impl *pCW=nullptr;
1762
1763 if ( !pCW )
1764 {
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)
1769 {
1770 pCW = aChildWins[n].get();
1771 break;
1772 }
1773 }
1774
1775 if ( !pCW )
1776 {
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) );
1783 }
1784
1785 pCW->nId = nId;
1786 if ( nInter )
1787 pCW->nInterfaceId = nInter;
1788 pCW->nVisibility = nMode;
1789 pCW->bEnable = bEnabled;
1790}
1791
1792
1793// The on/off status of a ChildWindow is switched
1794
1795void SfxWorkWindow::ToggleChildWindow_Impl(sal_uInt16 nId, bool bSetFocus)
1796{
1797 sal_uInt16 nCount = aChildWins.size();
1798 sal_uInt16 n;
1799 for (n=0; n<nCount; n++)
1
Assuming 'n' is < 'nCount'
2
Loop condition is true. Entering loop body
33
Assuming 'n' is < 'nCount'
34
Loop condition is true. Entering loop body
1800 if (aChildWins[n]->nId == nId)
3
Assuming 'nId' is equal to field 'nId'
4
Taking true branch
35
Assuming 'nId' is equal to field 'nId'
36
Taking true branch
1801 break;
5
Execution continues on line 1803
37
Execution continues on line 1803
1802
1803 if ( n
5.1
'n' is < 'nCount'
37.1
'n' is < 'nCount'
<nCount )
6
Taking true branch
38
Taking true branch
1804 {
1805 // The Window is already known
1806 SfxChildWin_Impl *pCW = aChildWins[n].get();
1807 SfxChildWindow *pChild = pCW->pWin;
1808
1809 bool bCreationAllowed( true );
1810 if ( !bInternalDockingAllowed )
7
Assuming field 'bInternalDockingAllowed' is true
8
Taking false branch
39
Assuming field 'bInternalDockingAllowed' is true
40
Taking false branch
1811 {
1812 // Special case for all non-floatable child windows. We have
1813 // to prevent the creation here!
1814 bCreationAllowed = !( pCW->aInfo.nFlags & SfxChildWindowFlags::FORCEDOCK );
1815 }
1816
1817 if ( bCreationAllowed
8.1
'bCreationAllowed' is true
40.1
'bCreationAllowed' is true
)
9
Taking true branch
41
Taking true branch
1818 {
1819 if ( pCW->bCreate )
10
Assuming field 'bCreate' is false
11
Taking false branch
42
Assuming field 'bCreate' is true
43
Taking true branch
1820 {
1821 if ( pChild )
44
Assuming 'pChild' is non-null
45
Taking true branch
1822 {
1823 if ( pChild->QueryClose() )
46
Assuming the condition is true
47
Taking true branch
1824 {
1825 pCW->bCreate = false;
1826 // The Window should be switched off
1827 pChild->SetVisible_Impl( false );
1828 RemoveChildWin_Impl( pCW );
48
Calling 'SfxWorkWindow::RemoveChildWin_Impl'
54
Returning from 'SfxWorkWindow::RemoveChildWin_Impl'
1829 }
1830 }
1831 else
1832 {
1833 // no actual Window exists, yet => just remember the "switched off" state
1834 pCW->bCreate = false;
1835 }
1836 }
1837 else
1838 {
1839 pCW->bCreate = true;
1840 if ( pChild )
12
Assuming 'pChild' is non-null
13
Taking true branch
1841 {
1842 ShowChildWindow_Impl( nId, true, bSetFocus );
14
Calling 'SfxWorkWindow::ShowChildWindow_Impl'
1843 }
1844 else
1845 {
1846 // create actual Window
1847 CreateChildWin_Impl( pCW, bSetFocus );
1848 if ( !pCW->pWin )
1849 // no success
1850 pCW->bCreate = false;
1851 }
1852 }
1853 }
1854
1855 ArrangeChildren_Impl();
1856 ShowChildren_Impl();
1857
1858 if ( pCW->bCreate && bCreationAllowed
55.1
'bCreationAllowed' is true
)
55
Assuming field 'bCreate' is true
56
Taking true branch
1859 {
1860 if ( !pCW->pCli
56.1
Field 'pCli' is null
)
57
Taking true branch
1861 {
1862 SfxDockingWindow *pDock =
1863 static_cast<SfxDockingWindow*>( pCW->pWin->GetWindow() );
58
Called C++ object pointer is null
1864 if ( pDock->IsAutoHide_Impl() )
1865 pDock->AutoShow_Impl();
1866 }
1867 }
1868
1869 return;
1870 }
1871
1872#ifdef DBG_UTIL
1873 nCount = aChildWins.size();
1874 for (n=0; n<nCount; n++)
1875 if (aChildWins[n]->nSaveId == nId)
1876 break;
1877
1878 if ( n < nCount )
1879 {
1880 OSL_FAIL("The ChildWindow is not in context!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/workwin.cxx"
":" "1880" ": "), "%s", "The ChildWindow is not in context!"
); } } while (false)
;
1881 }
1882 else
1883 {
1884 OSL_FAIL("The ChildWindow is not registered!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/workwin.cxx"
":" "1884" ": "), "%s", "The ChildWindow is not registered!"
); } } while (false)
;
1885 }
1886#endif
1887}
1888
1889
1890bool SfxWorkWindow::HasChildWindow_Impl(sal_uInt16 nId)
1891{
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;
1897
1898 if (n<nCount)
1899 {
1900 SfxChildWin_Impl *pCW = aChildWins[n].get();
1901 SfxChildWindow *pChild = pCW->pWin;
1902 return ( pChild && pCW->bCreate );
1903 }
1904
1905 return false;
1906}
1907
1908bool SfxWorkWindow::IsFloating( sal_uInt16 nId )
1909{
1910 SfxChildWin_Impl *pCW=nullptr;
1911
1912 if ( !pCW )
1913 {
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)
1918 {
1919 pCW = aChildWins[n].get();
1920 break;
1921 }
1922 }
1923
1924 if ( !pCW )
1925 {
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) );
1934 }
1935
1936 SfxChildAlignment eAlign;
1937 if ( pCW->aInfo.GetExtraData_Impl( &eAlign ) )
1938 return( eAlign == SfxChildAlignment::NOALIGNMENT );
1939 else
1940 return true;
1941}
1942
1943
1944bool SfxWorkWindow::KnowsChildWindow_Impl(sal_uInt16 nId)
1945{
1946 SfxChildWin_Impl *pCW=nullptr;
1947 sal_uInt16 nCount = aChildWins.size();
1948 sal_uInt16 n;
1949 for (n=0; n<nCount; n++)
1950 {
1951 pCW = aChildWins[n].get();
1952 if ( pCW->nSaveId == nId)
1953 break;
1954 }
1955
1956 if (n<nCount)
1957 {
1958 if ( !(pCW->aInfo.nFlags & SfxChildWindowFlags::ALWAYSAVAILABLE) && !IsVisible_Impl( pCW->nVisibility ) )
1959 return false;
1960 return pCW->bEnable;
1961 }
1962 else
1963 return false;
1964}
1965
1966
1967void SfxWorkWindow::SetChildWindow_Impl(sal_uInt16 nId, bool bOn, bool bSetFocus)
1968{
1969 SfxChildWin_Impl *pCW=nullptr;
1970 SfxWorkWindow *pWork = nullptr;
1971
1972 if ( !pCW
24.1
'pCW' is null
)
25
Taking true branch
1973 {
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++)
26
Assuming 'n' is >= 'nCount'
27
Loop condition is false. Execution continues on line 1985
1977 if (aChildWins[n]->nSaveId == nId)
1978 {
1979 pCW = aChildWins[n].get();
1980 pWork = this;
1981 break;
1982 }
1983 }
1984
1985 if ( !pCW
27.1
'pCW' is null
)
28
Taking true branch
1986 {
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
28.1
'pWork' is null
|| pCW->aInfo.nFlags & SfxChildWindowFlags::TASK )
29
Taking true branch
1992 pWork = this;
1993 pWork->aChildWins.push_back( std::unique_ptr<SfxChildWin_Impl>(pCW) );
1994 }
1995
1996 if ( pCW->bCreate != bOn )
30
Assuming 'bOn' is not equal to field 'bCreate'
31
Taking true branch
1997 pWork->ToggleChildWindow_Impl(nId,bSetFocus);
32
Calling 'SfxWorkWindow::ToggleChildWindow_Impl'
1998}
1999
2000
2001void SfxWorkWindow::ShowChildWindow_Impl(sal_uInt16 nId, bool bVisible, bool bSetFocus)
2002{
2003 sal_uInt16 nCount = aChildWins.size();
2004 SfxChildWin_Impl* pCW=nullptr;
2005 sal_uInt16 n;
2006 for (n=0; n<nCount; n++)
15
Assuming 'n' is < 'nCount'
16
Loop condition is true. Entering loop body
2007 {
2008 pCW = aChildWins[n].get();
2009 if (pCW->nId == nId)
17
Assuming 'nId' is equal to field 'nId'
18
Taking true branch
2010 break;
19
Execution continues on line 2013
2011 }
2012
2013 if ( n
19.1
'n' is < 'nCount'
<nCount )
20
Taking true branch
2014 {
2015 SfxChildWindow *pChildWin = pCW->pWin;
2016 if ( pChildWin )
21
Assuming 'pChildWin' is null
22
Taking false branch
2017 {
2018 if ( bVisible )
2019 {
2020 if ( pCW->pCli )
2021 {
2022 pCW->pCli->bSetFocus = bSetFocus;
2023 pCW->pCli->nVisible = SfxChildVisibility::VISIBLE;
2024 pChildWin->Show( bSetFocus && pChildWin->WantsFocus() ? ShowFlags::NONE : ShowFlags::NoFocusChange | ShowFlags::NoActivate );
2025 }
2026 else
2027 static_cast<SfxDockingWindow*>(pChildWin->GetWindow())->Reappear_Impl();
2028
2029 }
2030 else
2031 {
2032 if ( pCW->pCli )
2033 {
2034 pCW->pCli->nVisible = SfxChildVisibility::VISIBLE ^ SfxChildVisibility::NOT_HIDDEN;
2035 pCW->pWin->Hide();
2036 }
2037 else
2038 static_cast<SfxDockingWindow*>(pChildWin->GetWindow())->Disappear_Impl();
2039
2040 }
2041
2042 ArrangeChildren_Impl();
2043 ShowChildren_Impl();
2044 }
2045 else if ( bVisible
22.1
'bVisible' is true
)
23
Taking true branch
2046 {
2047 SetChildWindow_Impl( nId, true, bSetFocus );
24
Calling 'SfxWorkWindow::SetChildWindow_Impl'
2048 pChildWin = pCW->pWin;
2049 }
2050
2051 if ( pChildWin )
2052 {
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 );
2059 }
2060
2061 return;
2062 }
2063
2064#ifdef DBG_UTIL
2065 nCount = aChildWins.size();
2066 for (n=0; n<nCount; n++)
2067 if (aChildWins[n]->nSaveId == nId)
2068 break;
2069
2070 if ( n<nCount )
2071 {
2072 OSL_FAIL("The ChildWindow is not in context!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/workwin.cxx"
":" "2072" ": "), "%s", "The ChildWindow is not in context!"
); } } while (false)
;
2073 }
2074 else
2075 {
2076 OSL_FAIL("The ChildWindow is not registered")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sfx2/source/appl/workwin.cxx"
":" "2076" ": "), "%s", "The ChildWindow is not registered")
; } } while (false)
;
2077 }
2078#endif
2079}
2080
2081
2082SfxChildWindow* SfxWorkWindow::GetChildWindow_Impl(sal_uInt16 nId)
2083{
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;
2089
2090 if (n<nCount)
2091 return aChildWins[n]->pWin;
2092 return nullptr;
2093}
2094
2095
2096void SfxWorkWindow::ResetChildWindows_Impl()
2097{
2098 for (std::unique_ptr<SfxChildWin_Impl>& pChildWin : aChildWins)
2099 {
2100 pChildWin->nId = 0;
2101 pChildWin->bEnable = false;
2102 }
2103}
2104
2105// returns the size of the area (client area) of the
2106// parent windows, in which the ChildWindow can be fitted.
2107
2108tools::Rectangle SfxWorkWindow::GetTopRect_Impl() const
2109{
2110 return pMasterFrame->GetTopOuterRectPixel_Impl();
2111}
2112
2113
2114// Virtual method to find out if there is room for a ChildWindow in the
2115// client area of the parent.
2116
2117bool SfxWorkWindow::RequestTopToolSpacePixel_Impl( SvBorder aBorder )
2118{
2119 return !(!IsDockingAllowed() ||
2120 aClientArea.GetWidth() < aBorder.Left() + aBorder.Right() ||
2121 aClientArea.GetHeight() < aBorder.Top() + aBorder.Bottom());
2122}
2123
2124void SfxWorkWindow::SaveStatus_Impl(SfxChildWindow *pChild, const SfxChildWinInfo &rInfo)
2125{
2126 // The Status of the Presentation mode is not saved
2127 if ( IsDockingAllowed() && bInternalDockingAllowed )
2128 pChild->SaveStatus(rInfo);
2129}
2130
2131void SfxWorkWindow::InitializeChild_Impl(SfxChildWin_Impl *pCW)
2132{
2133 SfxDispatcher *pDisp = pBindings->GetDispatcher_Impl();
2134 SfxViewFrame *pViewFrame = pDisp ? pDisp->GetFrame() :nullptr;
2135 SfxModule *pMod = pViewFrame ? SfxModule::GetActiveModule(pViewFrame) :nullptr;
2136
2137 OUString sModule;
2138 if (pViewFrame)
2139 {
2140 try
2141 {
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);
2147 }
2148 catch (...)
2149 {
2150 }
2151 }
2152
2153 SfxChildWinFactory* pFact=nullptr;
2154 SfxApplication *pApp = SfxGetpApp();
2155 {
2156 SfxChildWinFactArr_Impl &rFactories = pApp->GetChildWinFactories_Impl();
2157 for ( size_t nFactory = 0; nFactory < rFactories.size(); ++nFactory )
2158 {
2159 pFact = &rFactories[nFactory];
2160 if ( pFact->nId == pCW->nSaveId )
2161 {
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;
2176 }
2177 }
2178 }
2179
2180 if ( !pMod )
2181 return;
2182
2183 SfxChildWinFactArr_Impl *pFactories = pMod->GetChildWinFactories_Impl();
2184 if ( !pFactories )
2185 return;
2186
2187 SfxChildWinFactArr_Impl &rFactories = *pFactories;
2188 for ( size_t nFactory = 0; nFactory < rFactories.size(); ++nFactory )
2189 {
2190 pFact = &rFactories[nFactory];
2191 if ( pFact->nId == pCW->nSaveId )
2192 {
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;
2209 }
2210 }
2211}
2212
2213SfxSplitWindow* SfxWorkWindow::GetSplitWindow_Impl( SfxChildAlignment eAlign )
2214{
2215 switch ( eAlign )
2216 {
2217 case SfxChildAlignment::TOP:
2218 return pSplit[2];
2219
2220 case SfxChildAlignment::BOTTOM:
2221 return pSplit[3];
2222
2223 case SfxChildAlignment::LEFT:
2224 return pSplit[0];
2225
2226 case SfxChildAlignment::RIGHT:
2227 return pSplit[1];
2228
2229 default:
2230 return nullptr;
2231 }
2232}
2233
2234void SfxWorkWindow::MakeChildrenVisible_Impl( bool bVis )
2235{
2236 bAllChildrenVisible = bVis;
2237 if ( bVis )
2238 {
2239 if ( !bSorted )
2240 Sort_Impl();
2241 for (sal_uInt16 n : aSortedList)
2242 {
2243 SfxChild_Impl* pCli = aChildren[n].get();
2244 if ( (pCli->eAlign == SfxChildAlignment::NOALIGNMENT) || (IsDockingAllowed() && bInternalDockingAllowed) )
2245 pCli->nVisible |= SfxChildVisibility::ACTIVE;
2246 }
2247 }
2248 else
2249 {
2250 if ( !bSorted )
2251 Sort_Impl();
2252 for (sal_uInt16 n : aSortedList)
2253 {
2254 SfxChild_Impl* pCli = aChildren[n].get();
2255 pCli->nVisible &= ~SfxChildVisibility::ACTIVE;
2256 }
2257 }
2258}
2259
2260bool SfxWorkWindow::IsAutoHideMode( const SfxSplitWindow *pSplitWin )
2261{
2262 for (const VclPtr<SfxSplitWindow> & pWin : pSplit)
2263 {
2264 if ( pWin.get() != pSplitWin && pWin->IsAutoHide( true ) )
2265 return true;
2266 }
2267 return false;
2268}
2269
2270
2271void SfxWorkWindow::EndAutoShow_Impl( Point aPos )
2272{
2273 for (VclPtr<SfxSplitWindow> & p : pSplit)
2274 {
2275 if ( p && p->IsAutoHide(false) )
2276 {
2277 Point aLocalPos = p->ScreenToOutputPixel( aPos );
2278 tools::Rectangle aRect( Point(), p->GetSizePixel() );
2279 if ( !aRect.IsInside( aLocalPos ) )
2280 p->FadeOut();
2281 }
2282 }
2283}
2284
2285void SfxWorkWindow::ArrangeAutoHideWindows( SfxSplitWindow *pActSplitWin )
2286{
2287 if ( m_nLock )
2288 return;
2289
2290 tools::Rectangle aArea( aUpperClientArea );
2291 for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX4; n++ )
2292 {
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;
2303
2304 // Width and position of the dummy window as a starting point
2305 Size aSize = pDummy->GetSizePixel();
2306 Point aPos = pDummy->GetPosPixel();
2307
2308 switch ( n )
2309 {
2310 case 0 :
2311 {
2312 // Left SplitWindow
2313 // Get the width of the Window yourself, if no DummyWindow
2314 if ( !bDummyWindow )
2315 aSize.setWidth( pSplitWin->GetSizePixel().Width() );
2316
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 long nLeft = aPos.X() + aSize.Width();
2320 if ( nLeft > aArea.Left() )
2321 aArea.SetLeft( nLeft );
2322 break;
2323 }
2324 case 1 :
2325 {
2326 // Right SplitWindow
2327 // Position to correct the difference of the widths
2328 aPos.AdjustX(aSize.Width() );
2329
2330 // Get the width of the Window yourself, if no DummyWindow
2331 if ( !bDummyWindow )
2332 aSize.setWidth( pSplitWin->GetSizePixel().Width() );
2333
2334 aPos.AdjustX( -(aSize.Width()) );
2335
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() )
2339 {
2340 aPos.setX( aArea.Left() );
2341 aSize.setWidth( aArea.GetWidth() );
2342 }
2343
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 long nRight = aPos.X();
2347 if ( !aArea.IsWidthEmpty() && nRight < aArea.Right() )
2348 aArea.SetRight( nRight );
2349 break;
2350 }
2351 case 2 :
2352 {
2353 // Top SplitWindow
2354 // Get the height of the Window yourself, if no DummyWindow
2355 if ( !bDummyWindow )
2356 aSize.setHeight( pSplitWin->GetSizePixel().Height() );
2357
2358
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() );
2363
2364 // If a Window is visible at the top, then the free region
2365 // starts beneath it, for example at the Client area
2366 long nTop = aPos.Y() + aSize.Height();
2367 if ( nTop > aArea.Top() )
2368 aArea.SetTop( nTop );
2369 break;
2370 }
2371 case 3 :
2372 {
2373 // The bottom SplitWindow
2374 // Position to correct the difference of the heights
2375 aPos.AdjustY(aSize.Height() );
2376
2377 // Get the height of the Window yourself, if no DummyWindow
2378 if ( !bDummyWindow )
2379 aSize.setHeight( pSplitWin->GetSizePixel().Height() );
2380
2381 aPos.AdjustY( -(aSize.Height()) );
2382
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() );
2387
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() )
2391 {
2392 aPos.setY( aArea.Top() );
2393 aSize.setHeight( aArea.GetHeight() );
2394 }
2395
2396 break;
2397 }
2398 }
2399
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 );
2407 }
2408}
2409
2410tools::Rectangle SfxWorkWindow::GetFreeArea( bool bAutoHide ) const
2411{
2412 if ( bAutoHide )
2413 {
2414 tools::Rectangle aArea( aClientArea );
2415 for ( sal_uInt16 n=0; n<SFX_SPLITWINDOWS_MAX4; n++ )
2416 {
2417 if ( pSplit[n]->IsPinned() || !pSplit[n]->IsVisible() )
2418 continue;
2419
2420 Size aSize = pSplit[n]->GetSizePixel();
2421 switch ( n )
2422 {
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;
2435 }
2436 }
2437
2438 return aArea;
2439 }
2440 else
2441 return aClientArea;
2442}
2443
2444void SfxWorkWindow::SetActiveChild_Impl( vcl::Window *pChild )
2445{
2446 pActiveChild = pChild;
2447}
2448
2449void SfxWorkWindow::DataChanged_Impl()
2450{
2451 ArrangeChildren_Impl();
2452}
2453
2454/* vim:set shiftwidth=4 softtabstop=4 expandtab: */