LanguageTool: don't crash if REST protocol isn't set
[LibreOffice.git] / sfx2 / source / dialog / splitwin.cxx
blob6625b85d5aaf504a96d6c15baf3bb839e52a4415
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 #ifdef __sun
21 #include <ctime>
22 #endif
24 #include <unotools/viewoptions.hxx>
25 #include <rtl/ustrbuf.hxx>
26 #include <sal/log.hxx>
27 #include <tools/debug.hxx>
29 #include <vcl/event.hxx>
30 #include <vcl/menu.hxx>
31 #include <vcl/timer.hxx>
32 #include <vcl/svapp.hxx>
34 #include <splitwin.hxx>
35 #include <workwin.hxx>
36 #include <sfx2/dockwin.hxx>
38 #include <memory>
39 #include <vector>
40 #include <utility>
42 using namespace ::com::sun::star::uno;
44 #define VERSION 1
45 #define nPixel 30L
46 constexpr OUStringLiteral USERITEM_NAME = u"UserItem";
48 namespace {
49 // helper class to deactivate UpdateMode, if needed, for the life time of an instance
50 class DeactivateUpdateMode
52 public:
53 explicit DeactivateUpdateMode( SfxSplitWindow& rSplitWindow )
54 : mrSplitWindow( rSplitWindow )
55 , mbUpdateMode( rSplitWindow.IsUpdateMode() )
57 if ( mbUpdateMode )
59 mrSplitWindow.SetUpdateMode( false );
63 ~DeactivateUpdateMode()
65 if ( mbUpdateMode )
67 mrSplitWindow.SetUpdateMode( true );
71 private:
72 SfxSplitWindow& mrSplitWindow;
73 const bool mbUpdateMode;
77 class SfxEmptySplitWin_Impl : public SplitWindow
79 /* [Description]
81 The SfxEmptySplitWin_Impldow is an empty SplitWindow, that replaces the
82 SfxSplitWindow AutoHide mode. It only serves as a placeholder to receive
83 mouse moves and if possible blend in the true SplitWindow display.
85 friend class SfxSplitWindow;
87 VclPtr<SfxSplitWindow> pOwner;
88 bool bFadeIn;
89 bool bAutoHide;
90 bool bSplit;
91 bool bEndAutoHide;
92 Timer aTimer;
93 Point aLastPos;
94 sal_uInt16 nState;
96 public:
97 explicit SfxEmptySplitWin_Impl( SfxSplitWindow *pParent )
98 : SplitWindow( pParent->GetParent(), WinBits( WB_BORDER | WB_3DLOOK ) )
99 , pOwner( pParent )
100 , bFadeIn( false )
101 , bAutoHide( false )
102 , bSplit( false )
103 , bEndAutoHide( false )
104 , aTimer("sfx2 SfxEmptySplitWin_Impl aTimer")
105 , nState( 1 )
107 aTimer.SetInvokeHandler(
108 LINK(pOwner, SfxSplitWindow, TimerHdl ) );
109 aTimer.SetTimeout( 200 );
110 SetAlign( pOwner->GetAlign() );
111 Actualize();
112 ShowFadeInHideButton();
115 virtual ~SfxEmptySplitWin_Impl() override
116 { disposeOnce(); }
117 virtual void dispose() override
119 aTimer.Stop();
120 pOwner.clear();
121 SplitWindow::dispose();
124 virtual void FadeIn() override;
125 void Actualize();
128 void SfxEmptySplitWin_Impl::Actualize()
130 Size aSize( pOwner->GetSizePixel() );
131 switch ( pOwner->GetAlign() )
133 case WindowAlign::Left:
134 case WindowAlign::Right:
135 aSize.setWidth( GetFadeInSize() );
136 break;
137 case WindowAlign::Top:
138 case WindowAlign::Bottom:
139 aSize.setHeight( GetFadeInSize() );
140 break;
143 SetSizePixel( aSize );
146 void SfxEmptySplitWin_Impl::FadeIn()
148 if (!bAutoHide )
149 bAutoHide = IsFadeNoButtonMode();
150 pOwner->SetFadeIn_Impl( true );
151 if ( bAutoHide )
153 // Set Timer to close; the caller has to ensure themselves that the
154 // Window is not closed instantly (eg by setting the focus or a modal
155 // mode.
156 aLastPos = GetPointerPosPixel();
157 aTimer.Start();
159 else
160 pOwner->SaveConfig_Impl();
164 void SfxSplitWindow::MouseButtonDown( const MouseEvent& rMEvt )
166 if ( rMEvt.GetClicks() != 2 )
167 SplitWindow::MouseButtonDown( rMEvt );
170 SfxSplitWindow::SfxSplitWindow( vcl::Window* pParent, SfxChildAlignment eAl,
171 SfxWorkWindow *pW, bool bWithButtons )
173 /* [Description]
175 A SfxSplitWindow brings the recursive structure of the SV-SplitWindows to
176 the outside by simulating a table-like structure with rows and columns
177 (maximum recursion depth 2). Furthermore, it ensures the persistence of
178 the arrangement of the SfxDockingWindows.
181 : SplitWindow ( pParent, WB_BORDER | WB_SIZEABLE | WB_3DLOOK | WB_HIDE ),
182 eAlign(eAl),
183 pWorkWin(pW),
184 bPinned(true),
185 pEmptyWin(nullptr),
186 pActive(nullptr)
188 if (bWithButtons)
190 ShowFadeOutButton();
193 // Set SV-Alignment
194 WindowAlign eTbxAlign;
195 switch ( eAlign )
197 case SfxChildAlignment::LEFT:
198 eTbxAlign = WindowAlign::Left;
199 break;
200 case SfxChildAlignment::RIGHT:
201 eTbxAlign = WindowAlign::Right;
202 break;
203 case SfxChildAlignment::TOP:
204 eTbxAlign = WindowAlign::Top;
205 break;
206 case SfxChildAlignment::BOTTOM:
207 eTbxAlign = WindowAlign::Bottom;
208 bPinned = true;
209 break;
210 default:
211 eTbxAlign = WindowAlign::Top; // some sort of default...
212 break; // -Wall lots not handled...
215 SetAlign (eTbxAlign);
216 pEmptyWin = VclPtr<SfxEmptySplitWin_Impl>::Create( this );
217 if ( bPinned )
219 pEmptyWin->bFadeIn = true;
220 pEmptyWin->nState = 2;
223 if ( bWithButtons )
225 // Read Configuration
226 const OUString aWindowId{ "SplitWindow" + OUString::number(static_cast<sal_Int32>(eTbxAlign)) };
227 SvtViewOptions aWinOpt( EViewType::Window, aWindowId );
228 OUString aWinData;
229 Any aUserItem = aWinOpt.GetUserItem( USERITEM_NAME );
230 OUString aTemp;
231 if ( aUserItem >>= aTemp )
232 aWinData = aTemp;
233 if ( aWinData.startsWith("V") )
235 sal_Int32 nIdx{ 0 };
236 pEmptyWin->nState = static_cast<sal_uInt16>(aWinData.getToken( 1, ',', nIdx ).toInt32());
237 if ( pEmptyWin->nState & 2 )
238 pEmptyWin->bFadeIn = true;
239 bPinned = true; // always assume pinned - floating mode not used anymore
241 const sal_Int32 nCount{ aWinData.getToken(0, ',', nIdx).toInt32() };
242 for ( sal_Int32 n=0; n<nCount; ++n )
244 std::unique_ptr<SfxDock_Impl> pDock(new SfxDock_Impl);
245 pDock->pWin = nullptr;
246 pDock->bNewLine = false;
247 pDock->bHide = true;
248 pDock->nType = static_cast<sal_uInt16>(aWinData.getToken(0, ',', nIdx).toInt32());
249 if ( !pDock->nType )
251 // could mean NewLine
252 pDock->nType = static_cast<sal_uInt16>(aWinData.getToken(0, ',', nIdx).toInt32());
253 if ( !pDock->nType )
255 // Read error
256 break;
258 else
259 pDock->bNewLine = true;
262 maDockArr.insert(maDockArr.begin() + n, std::move(pDock));
266 else
268 bPinned = true;
269 pEmptyWin->bFadeIn = true;
270 pEmptyWin->nState = 2;
275 SfxSplitWindow::~SfxSplitWindow()
277 disposeOnce();
280 void SfxSplitWindow::dispose()
282 SaveConfig_Impl();
284 if ( pEmptyWin )
286 // Set pOwner to NULL, otherwise try to delete pEmptyWin once more. The
287 // window that is just being docked is always deleted from the outside.
288 pEmptyWin->pOwner = nullptr;
290 pEmptyWin.disposeAndClear();
292 maDockArr.clear();
293 pActive.clear();
294 SplitWindow::dispose();
297 void SfxSplitWindow::SaveConfig_Impl()
299 // Save configuration
300 OUStringBuffer aWinData;
301 aWinData.append('V');
302 aWinData.append(static_cast<sal_Int32>(VERSION));
303 aWinData.append(',');
304 aWinData.append(static_cast<sal_Int32>(pEmptyWin->nState));
305 aWinData.append(',');
307 sal_uInt16 nCount = 0;
308 for ( auto const & rDock: maDockArr )
310 if ( rDock->bHide || rDock->pWin )
311 nCount++;
314 aWinData.append(static_cast<sal_Int32>(nCount));
316 for ( auto const & rDock: maDockArr )
318 if ( !rDock->bHide && !rDock->pWin )
319 continue;
320 if ( rDock->bNewLine )
321 aWinData.append(",0");
322 aWinData.append(',');
323 aWinData.append(static_cast<sal_Int32>(rDock->nType));
326 const OUString aWindowId{ "SplitWindow" + OUString::number(static_cast<sal_Int32>(GetAlign())) };
327 SvtViewOptions aWinOpt( EViewType::Window, aWindowId );
328 aWinOpt.SetUserItem( USERITEM_NAME, makeAny( aWinData.makeStringAndClear() ) );
332 void SfxSplitWindow::StartSplit()
334 tools::Long nSize = 0;
335 Size aSize = GetSizePixel();
337 if ( pEmptyWin )
339 pEmptyWin->bFadeIn = true;
340 pEmptyWin->bSplit = true;
343 tools::Rectangle aRect = pWorkWin->GetFreeArea( !bPinned );
344 switch ( GetAlign() )
346 case WindowAlign::Left:
347 case WindowAlign::Right:
348 nSize = aSize.Width() + aRect.GetWidth();
349 break;
350 case WindowAlign::Top:
351 case WindowAlign::Bottom:
352 nSize = aSize.Height() + aRect.GetHeight();
353 break;
356 SetMaxSizePixel( nSize );
360 void SfxSplitWindow::SplitResize()
362 if ( bPinned )
364 pWorkWin->ArrangeChildren_Impl();
365 pWorkWin->ShowChildren_Impl();
367 else
368 pWorkWin->ArrangeAutoHideWindows( this );
372 void SfxSplitWindow::Split()
374 if ( pEmptyWin )
375 pEmptyWin->bSplit = false;
377 SplitWindow::Split();
379 std::vector< std::pair< sal_uInt16, tools::Long > > aNewOrgSizes;
381 sal_uInt16 nCount = maDockArr.size();
382 for ( sal_uInt16 n=0; n<nCount; n++ )
384 const SfxDock_Impl& rD = *maDockArr[n];
385 if ( rD.pWin )
387 const sal_uInt16 nId = rD.nType;
388 const tools::Long nSize = GetItemSize( nId, SplitWindowItemFlags::Fixed );
389 const tools::Long nSetSize = GetItemSize( GetSet( nId ) );
390 Size aSize;
392 if ( IsHorizontal() )
394 aSize.setWidth( nSize );
395 aSize.setHeight( nSetSize );
397 else
399 aSize.setWidth( nSetSize );
400 aSize.setHeight( nSize );
403 rD.pWin->SetItemSize_Impl( aSize );
405 aNewOrgSizes.emplace_back( nId, nSize );
409 // workaround insufficiency of <SplitWindow> regarding dock layouting:
410 // apply FIXED item size as 'original' item size to improve layouting of undock-dock-cycle of a window
412 DeactivateUpdateMode aDeactivateUpdateMode( *this );
413 for (const std::pair< sal_uInt16, tools::Long > & rNewOrgSize : aNewOrgSizes)
415 SetItemSize( rNewOrgSize.first, rNewOrgSize.second );
419 SaveConfig_Impl();
423 void SfxSplitWindow::InsertWindow( SfxDockingWindow* pDockWin, const Size& rSize)
426 To insert SfxDockingWindows just pass no position. The SfxSplitWindow
427 searches the last marked one to the passed SfxDockingWindow or appends a
428 new one at the end.
431 short nLine = -1; // so that the first window cab set nline to 0
432 sal_uInt16 nL;
433 sal_uInt16 nPos = 0;
434 bool bNewLine = true;
435 bool bSaveConfig = false;
436 SfxDock_Impl *pFoundDock=nullptr;
437 sal_uInt16 nCount = maDockArr.size();
438 for ( sal_uInt16 n=0; n<nCount; n++ )
440 SfxDock_Impl& rDock = *maDockArr[n];
441 if ( rDock.bNewLine )
443 // The window opens a new line
444 if ( pFoundDock )
445 // But after the just inserted window
446 break;
448 // New line
449 nPos = 0;
450 bNewLine = true;
453 if ( rDock.pWin )
455 // Does there exist a window now at this position
456 if ( bNewLine && !pFoundDock )
458 // Not known until now in which real line it is located
459 GetWindowPos( rDock.pWin, nL, nPos );
460 nLine = static_cast<short>(nL);
463 if ( !pFoundDock )
465 // The window is located before the inserted one
466 nPos++;
469 // Line is opened
470 bNewLine = false;
471 if ( pFoundDock )
472 break;
475 if ( rDock.nType == pDockWin->GetType() )
477 DBG_ASSERT( !pFoundDock && !rDock.pWin, "Window already exists!");
478 pFoundDock = &rDock;
479 if ( !bNewLine )
480 break;
481 else
483 // A new line has been created but no window was found there;
484 // continue searching for a window in this line in-order to set
485 // bNewLine correctly. While doing so nline or nPos are not
486 // to be changed!
487 nLine++;
492 if ( !pFoundDock )
494 // Not found, insert at end
495 pFoundDock = new SfxDock_Impl;
496 pFoundDock->bHide = true;
497 maDockArr.push_back( std::unique_ptr<SfxDock_Impl>(pFoundDock) );
498 pFoundDock->nType = pDockWin->GetType();
499 nLine++;
500 nPos = 0;
501 bNewLine = true;
502 pFoundDock->bNewLine = bNewLine;
503 bSaveConfig = true;
506 pFoundDock->pWin = pDockWin;
507 pFoundDock->bHide = false;
508 InsertWindow_Impl( pFoundDock, rSize, nLine, nPos, bNewLine );
509 if ( bSaveConfig )
510 SaveConfig_Impl();
514 void SfxSplitWindow::ReleaseWindow_Impl(SfxDockingWindow const *pDockWin, bool bSave)
516 // The docking window is no longer stored in the internal data.
517 sal_uInt16 nCount = maDockArr.size();
518 for ( sal_uInt16 n=0; n<nCount; n++ )
520 const SfxDock_Impl& rDock = *maDockArr[n];
521 if ( rDock.nType == pDockWin->GetType() )
523 if ( rDock.bNewLine && n<nCount-1 )
524 maDockArr[n+1]->bNewLine = true;
526 // Window has a position, this we forget
527 maDockArr.erase(maDockArr.begin() + n);
528 break;
532 if ( bSave )
533 SaveConfig_Impl();
537 void SfxSplitWindow::MoveWindow( SfxDockingWindow* pDockWin, const Size& rSize,
538 sal_uInt16 nLine, sal_uInt16 nPos, bool bNewLine)
540 /* [Description]
542 The docking window is moved within the SplitWindows.
546 sal_uInt16 nL, nP;
547 GetWindowPos( pDockWin, nL, nP );
549 if ( nLine > nL && GetItemCount( GetItemId( nL ) ) == 1 )
551 // If the last window is removed from its line, then everything slips
552 // one line to the front!
553 nLine--;
555 RemoveWindow( pDockWin );
556 InsertWindow( pDockWin, rSize, nLine, nPos, bNewLine );
560 void SfxSplitWindow::InsertWindow( SfxDockingWindow* pDockWin, const Size& rSize,
561 sal_uInt16 nLine, sal_uInt16 nPos, bool bNewLine)
563 /* [Description]
565 The DockingWindow that is pushed on this SplitWindow and shall hold the
566 given position and size.
569 ReleaseWindow_Impl( pDockWin, false );
570 SfxDock_Impl *pDock = new SfxDock_Impl;
571 pDock->bHide = false;
572 pDock->nType = pDockWin->GetType();
573 pDock->bNewLine = bNewLine;
574 pDock->pWin = pDockWin;
576 DBG_ASSERT( nPos==0 || !bNewLine, "Wrong Parameter!");
577 if ( bNewLine )
578 nPos = 0;
580 // The window must be inserted before the first window so that it has the
581 // same or a greater position than pDockWin.
582 sal_uInt16 nCount = maDockArr.size();
583 sal_uInt16 nLastWindowIdx(0);
585 // If no window is found, a first window is inserted
586 sal_uInt16 nInsertPos = 0;
587 for ( sal_uInt16 n=0; n<nCount; n++ )
589 SfxDock_Impl& rD = *maDockArr[n];
591 if (rD.pWin)
593 // A docked window has been found. If no suitable window behind
594 // the desired insertion point s found, then insertion is done at
595 // the end.
596 nInsertPos = nCount;
597 nLastWindowIdx = n;
598 sal_uInt16 nL=0, nP=0;
599 GetWindowPos( rD.pWin, nL, nP );
601 if ( (nL == nLine && nP == nPos) || nL > nLine )
603 DBG_ASSERT( nL == nLine || bNewLine || nPos > 0, "Wrong Parameter!" );
604 if ( nL == nLine && nPos == 0 && !bNewLine )
606 DBG_ASSERT(rD.bNewLine, "No new line?");
608 // The position is pushed to nPos==0
609 rD.bNewLine = false;
610 pDock->bNewLine = true;
613 nInsertPos = n != 0 ? nLastWindowIdx + 1 : 0; // ignore all non-windows after the last window
614 break;
618 if (nCount != 0 && nInsertPos == nCount && nLastWindowIdx != nCount - 1)
620 nInsertPos = nLastWindowIdx + 1; // ignore all non-windows after the last window
623 maDockArr.insert(maDockArr.begin() + nInsertPos, std::unique_ptr<SfxDock_Impl>(pDock));
624 InsertWindow_Impl( pDock, rSize, nLine, nPos, bNewLine );
625 SaveConfig_Impl();
629 void SfxSplitWindow::InsertWindow_Impl( SfxDock_Impl const * pDock,
630 const Size& rSize,
631 sal_uInt16 nLine, sal_uInt16 nPos, bool bNewLine)
633 /* [Description]
635 Adds a DockingWindow, and causes the recalculation of the size of
636 the SplitWindows.
640 SfxDockingWindow* pDockWin = pDock->pWin;
642 SplitWindowItemFlags nItemBits = SplitWindowItemFlags::NONE;
644 tools::Long nWinSize, nSetSize;
645 if ( IsHorizontal() )
647 nWinSize = rSize.Width();
648 nSetSize = rSize.Height();
650 else
652 nSetSize = rSize.Width();
653 nWinSize = rSize.Height();
656 std::unique_ptr<DeactivateUpdateMode> pDeactivateUpdateMode(new DeactivateUpdateMode( *this ));
658 if ( bNewLine || nLine == GetItemCount() )
660 // An existing row should not be inserted, instead a new one
661 // will be created
663 sal_uInt16 nId = 1;
664 for ( sal_uInt16 n=0; n<GetItemCount(); n++ )
666 if ( GetItemId(n) >= nId )
667 nId = GetItemId(n)+1;
670 // Create a new nLine:th line
671 SplitWindowItemFlags nBits = nItemBits;
672 if ( GetAlign() == WindowAlign::Top || GetAlign() == WindowAlign::Bottom )
673 nBits |= SplitWindowItemFlags::ColSet;
674 InsertItem( nId, nSetSize, nLine, 0, nBits );
677 // Insert the window at line with the position nline. ItemWindowSize set to
678 // "percentage" share since the SV then does the re-sizing as expected,
679 // "pixel" actually only makes sense if also items with percentage or
680 // relative sizes are present.
681 nItemBits |= SplitWindowItemFlags::PercentSize;
682 sal_uInt16 nSet = GetItemId( nLine );
683 InsertItem( pDockWin->GetType(), pDockWin, nWinSize, nPos, nSet, nItemBits );
685 // SplitWindows are once created in SFX and when inserting the first
686 // DockingWindows is made visible.
687 if ( GetItemCount() == 1 && GetItemCount( 1 ) == 1 )
689 // The Rearranging in WorkWindow and a Show() on the SplitWindow is
690 // caused by SfxDockingwindow (->SfxWorkWindow::ConfigChild_Impl)
691 if ( !bPinned && !IsFloatingMode() )
693 bPinned = true;
694 bool bFadeIn = ( pEmptyWin->nState & 2 ) != 0;
695 pEmptyWin->bFadeIn = false;
696 SetPinned_Impl( false );
697 pEmptyWin->Actualize();
698 SAL_INFO("sfx", "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" );
699 pWorkWin->RegisterChild_Impl( *GetSplitWindow(), eAlign )->nVisible = SfxChildVisibility::VISIBLE;
700 // tdf#113539 FadeIn will call ArrangeChildren_Impl() for us, and avoiding extra calls to that
701 // can make a different to load times because it avoids extra accessibility calcs
702 if ( bFadeIn )
703 FadeIn();
704 else
705 pWorkWin->ArrangeChildren_Impl();
707 else
709 bool bFadeIn = ( pEmptyWin->nState & 2 ) != 0;
710 pEmptyWin->bFadeIn = false;
711 pEmptyWin->Actualize();
712 if ( !bPinned || !pEmptyWin->bFadeIn )
714 SAL_INFO("sfx", "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" );
716 else
718 SAL_INFO("sfx", "SfxSplitWindow::InsertWindow_Impl - registering real Splitwindow" );
720 pWorkWin->RegisterChild_Impl( *GetSplitWindow(), eAlign )->nVisible = SfxChildVisibility::VISIBLE;
721 // tdf#113539 FadeIn will call ArrangeChildren_Impl() for us, and avoiding extra calls to that
722 // can make a different to load times because it avoids extra accessibility calcs
723 if ( bFadeIn )
724 FadeIn();
725 else
726 pWorkWin->ArrangeChildren_Impl();
729 pWorkWin->ShowChildren_Impl();
732 pDeactivateUpdateMode.reset();
734 // workaround insufficiency of <SplitWindow> regarding dock layouting:
735 // apply FIXED item size as 'original' item size to improve layouting of undock-dock-cycle of a window
737 std::vector< std::pair< sal_uInt16, tools::Long > > aNewOrgSizes;
738 // get FIXED item sizes
739 sal_uInt16 nCount = maDockArr.size();
740 for ( sal_uInt16 n=0; n<nCount; ++n )
742 const SfxDock_Impl& rD = *maDockArr[n];
743 if ( rD.pWin )
745 const sal_uInt16 nId = rD.nType;
746 const tools::Long nSize = GetItemSize( nId, SplitWindowItemFlags::Fixed );
747 aNewOrgSizes.emplace_back( nId, nSize );
750 // apply new item sizes
751 DeactivateUpdateMode aDeactivateUpdateMode( *this );
752 for (const std::pair< sal_uInt16, tools::Long > & rNewOrgSize : aNewOrgSizes)
754 SetItemSize( rNewOrgSize.first, rNewOrgSize.second );
760 void SfxSplitWindow::RemoveWindow( SfxDockingWindow const * pDockWin, bool bHide )
762 /* [Description]
764 Removes a DockingWindow. If it was the last one, then the SplitWindow is
765 being hidden.
768 sal_uInt16 nSet = GetSet( pDockWin->GetType() );
770 // SplitWindows are once created in SFX and is made invisible after
771 // removing the last DockingWindows.
772 if ( GetItemCount( nSet ) == 1 && GetItemCount() == 1 )
774 // The Rearranging in WorkWindow is caused by SfxDockingwindow
775 Hide();
776 pEmptyWin->aTimer.Stop();
777 sal_uInt16 nRealState = pEmptyWin->nState;
778 FadeOut_Impl();
779 pEmptyWin->Hide();
780 #ifdef DBG_UTIL
781 if ( !bPinned || !pEmptyWin->bFadeIn )
783 SAL_INFO("sfx", "SfxSplitWindow::RemoveWindow - releasing empty Splitwindow" );
785 else
787 SAL_INFO("sfx", "SfxSplitWindow::RemoveWindow - releasing real Splitwindow" );
789 #endif
790 pWorkWin->ReleaseChild_Impl( *GetSplitWindow() );
791 pEmptyWin->nState = nRealState;
792 pWorkWin->ArrangeAutoHideWindows( this );
795 sal_uInt16 nCount = maDockArr.size();
796 for ( sal_uInt16 n=0; n<nCount; n++ )
798 SfxDock_Impl& rDock = *maDockArr[n];
799 if ( rDock.nType == pDockWin->GetType() )
801 rDock.pWin = nullptr;
802 rDock.bHide = bHide;
803 break;
807 // Remove Windows, and if it was the last of the line, then also remove
808 // the line (line = itemset)
809 DeactivateUpdateMode aDeactivateUpdateMode( *this );
811 RemoveItem( pDockWin->GetType() );
813 if ( nSet && !GetItemCount( nSet ) )
814 RemoveItem( nSet );
818 bool SfxSplitWindow::GetWindowPos( const SfxDockingWindow* pWindow,
819 sal_uInt16& rLine, sal_uInt16& rPos ) const
820 /* [Description]
822 Returns the ID of the item sets and items for the DockingWindow in
823 the position passed on the old row / column-name.
827 sal_uInt16 nSet = GetSet ( pWindow->GetType() );
828 if ( nSet == SPLITWINDOW_ITEM_NOTFOUND )
829 return false;
831 rPos = GetItemPos( pWindow->GetType(), nSet );
832 rLine = GetItemPos( nSet );
833 return true;
837 bool SfxSplitWindow::GetWindowPos( const Point& rTestPos,
838 sal_uInt16& rLine, sal_uInt16& rPos ) const
839 /* [Description]
841 Returns the ID of the item sets and items for the DockingWindow in
842 the position passed on the old row / column-name.
846 sal_uInt16 nId = GetItemId( rTestPos );
847 if ( nId == 0 )
848 return false;
850 sal_uInt16 nSet = GetSet ( nId );
851 rPos = GetItemPos( nId, nSet );
852 rLine = GetItemPos( nSet );
853 return true;
857 sal_uInt16 SfxSplitWindow::GetLineCount() const
859 /* [Description]
861 Returns the number of rows = number of sub-itemsets in the root set.
864 return GetItemCount();
868 tools::Long SfxSplitWindow::GetLineSize( sal_uInt16 nLine ) const
870 /* [Description]
872 Returns the Row Height of nline itemset.
875 sal_uInt16 nId = GetItemId( nLine );
876 return GetItemSize( nId );
880 sal_uInt16 SfxSplitWindow::GetWindowCount( sal_uInt16 nLine ) const
882 /* [Description]
884 Returns the total number of windows
887 sal_uInt16 nId = GetItemId( nLine );
888 return GetItemCount( nId );
892 sal_uInt16 SfxSplitWindow::GetWindowCount() const
894 /* [Description]
896 Returns the total number of windows
899 return GetItemCount();
903 IMPL_LINK( SfxSplitWindow, TimerHdl, Timer*, pTimer, void)
905 if ( pTimer )
906 pTimer->Stop();
908 if ( CursorIsOverRect() || !pTimer )
910 // If the cursor is within the window, display the SplitWindow and set
911 // up the timer for close
912 pEmptyWin->bAutoHide = true;
913 if ( !IsVisible() )
914 pEmptyWin->FadeIn();
916 pEmptyWin->aLastPos = GetPointerPosPixel();
917 pEmptyWin->aTimer.Start();
919 else if ( pEmptyWin->bAutoHide )
921 if ( GetPointerPosPixel() != pEmptyWin->aLastPos )
923 // The mouse has moved within the running time of the timer, thus
924 // do nothing
925 pEmptyWin->aLastPos = GetPointerPosPixel();
926 pEmptyWin->aTimer.Start();
927 return;
930 // Especially for TF_AUTOSHOW_ON_MOUSEMOVE :
931 // If the window is not visible, there is nothing to do
932 // (user has simply moved the mouse over pEmptyWin)
933 if ( IsVisible() )
935 pEmptyWin->bEndAutoHide = false;
936 if ( !Application::IsInModalMode() &&
937 !PopupMenu::IsInExecute() &&
938 !pEmptyWin->bSplit && !HasChildPathFocus( true ) )
940 // While a modal dialog or a popup menu is open or while the
941 // Splitting is done, in any case, do not close. Even as long
942 // as one of the Children has the focus, the window remains
943 // open.
944 pEmptyWin->bEndAutoHide = true;
947 if ( pEmptyWin->bEndAutoHide )
949 // As far as I am concerned this can be the end of AutoShow
950 // But maybe some other SfxSplitWindow will remain open,
951 // then all others remain open too.
952 if ( !pWorkWin->IsAutoHideMode( this ) )
954 FadeOut_Impl();
955 pWorkWin->ArrangeAutoHideWindows( this );
957 else
959 pEmptyWin->aLastPos = GetPointerPosPixel();
960 pEmptyWin->aTimer.Start();
963 else
965 pEmptyWin->aLastPos = GetPointerPosPixel();
966 pEmptyWin->aTimer.Start();
973 bool SfxSplitWindow::CursorIsOverRect() const
975 bool bVisible = IsVisible();
977 // Also, take the collapsed SplitWindow into account
978 Point aPos = pEmptyWin->GetParent()->OutputToScreenPixel( pEmptyWin->GetPosPixel() );
979 Size aSize = pEmptyWin->GetSizePixel();
981 tools::Rectangle aRect( aPos, aSize );
983 if ( bVisible )
985 Point aVisPos = GetPosPixel();
986 Size aVisSize = GetSizePixel();
988 // Extend with +/- a few pixels, otherwise it is too nervous
989 aVisPos.AdjustX( -(nPixel) );
990 aVisPos.AdjustY( -(nPixel) );
991 aVisSize.AdjustWidth(2 * nPixel );
992 aVisSize.AdjustHeight(2 * nPixel );
994 tools::Rectangle aVisRect( aVisPos, aVisSize );
995 aRect = aRect.GetUnion( aVisRect );
998 return aRect.Contains( OutputToScreenPixel( static_cast<vcl::Window*>(const_cast<SfxSplitWindow *>(this))->GetPointerPosPixel() ) );
1002 SplitWindow* SfxSplitWindow::GetSplitWindow()
1004 if ( !bPinned || !pEmptyWin->bFadeIn )
1005 return pEmptyWin;
1006 return this;
1010 bool SfxSplitWindow::IsFadeIn() const
1012 return pEmptyWin->bFadeIn;
1015 bool SfxSplitWindow::IsAutoHide( bool bSelf ) const
1017 return bSelf ? pEmptyWin->bAutoHide && !pEmptyWin->bEndAutoHide : pEmptyWin->bAutoHide;
1021 void SfxSplitWindow::SetPinned_Impl( bool bOn )
1023 if ( bPinned == bOn )
1024 return;
1026 bPinned = bOn;
1027 if ( GetItemCount() == 0 )
1028 return;
1030 if ( !bOn )
1032 pEmptyWin->nState |= 1;
1033 if ( pEmptyWin->bFadeIn )
1035 // Unregister replacement windows
1036 SAL_INFO("sfx", "SfxSplitWindow::SetPinned_Impl - releasing real Splitwindow" );
1037 pWorkWin->ReleaseChild_Impl( *this );
1038 Hide();
1039 pEmptyWin->Actualize();
1040 SAL_INFO("sfx", "SfxSplitWindow::SetPinned_Impl - registering empty Splitwindow" );
1041 pWorkWin->RegisterChild_Impl( *pEmptyWin, eAlign )->nVisible = SfxChildVisibility::VISIBLE;
1044 Point aPos( GetPosPixel() );
1045 aPos = GetParent()->OutputToScreenPixel( aPos );
1046 SetFloatingPos( aPos );
1047 SetFloatingMode( true );
1048 GetFloatingWindow()->SetOutputSizePixel( GetOutputSizePixel() );
1050 if ( pEmptyWin->bFadeIn )
1051 Show();
1053 else
1055 pEmptyWin->nState &= ~1;
1056 SetOutputSizePixel( GetFloatingWindow()->GetOutputSizePixel() );
1057 SetFloatingMode(false);
1059 if ( pEmptyWin->bFadeIn )
1061 // Unregister replacement windows
1062 SAL_INFO("sfx", "SfxSplitWindow::SetPinned_Impl - releasing empty Splitwindow" );
1063 pWorkWin->ReleaseChild_Impl( *pEmptyWin );
1064 pEmptyWin->Hide();
1065 SAL_INFO("sfx", "SfxSplitWindow::SetPinned_Impl - registering real Splitwindow" );
1066 pWorkWin->RegisterChild_Impl( *this, eAlign )->nVisible = SfxChildVisibility::VISIBLE;
1071 void SfxSplitWindow::SetFadeIn_Impl( bool bOn )
1073 if ( bOn == pEmptyWin->bFadeIn )
1074 return;
1076 if ( GetItemCount() == 0 )
1077 return;
1079 pEmptyWin->bFadeIn = bOn;
1080 if ( bOn )
1082 pEmptyWin->nState |= 2;
1083 if ( IsFloatingMode() )
1085 // FloatingWindow is not visible, thus display it
1086 pWorkWin->ArrangeAutoHideWindows( this );
1087 Show();
1089 else
1091 SAL_INFO("sfx", "SfxSplitWindow::SetFadeIn_Impl - releasing empty Splitwindow" );
1092 pWorkWin->ReleaseChild_Impl( *pEmptyWin );
1093 pEmptyWin->Hide();
1094 SAL_INFO("sfx", "SfxSplitWindow::SetFadeIn_Impl - registering real Splitwindow" );
1095 pWorkWin->RegisterChild_Impl( *this, eAlign )->nVisible = SfxChildVisibility::VISIBLE;
1096 pWorkWin->ArrangeChildren_Impl();
1097 pWorkWin->ShowChildren_Impl();
1100 else
1102 pEmptyWin->bAutoHide = false;
1103 pEmptyWin->nState &= ~2;
1104 if ( !IsFloatingMode() )
1106 // The window is not "floating", should be hidden
1107 SAL_INFO("sfx", "SfxSplitWindow::SetFadeIn_Impl - releasing real Splitwindow" );
1108 pWorkWin->ReleaseChild_Impl( *this );
1109 Hide();
1110 pEmptyWin->Actualize();
1111 SAL_INFO("sfx", "SfxSplitWindow::SetFadeIn_Impl - registering empty Splitwindow" );
1112 pWorkWin->RegisterChild_Impl( *pEmptyWin, eAlign )->nVisible = SfxChildVisibility::VISIBLE;
1113 pWorkWin->ArrangeChildren_Impl();
1114 pWorkWin->ShowChildren_Impl();
1115 pWorkWin->ArrangeAutoHideWindows( this );
1117 else
1119 Hide();
1120 pWorkWin->ArrangeAutoHideWindows( this );
1125 void SfxSplitWindow::FadeOut_Impl()
1127 if ( pEmptyWin->aTimer.IsActive() )
1129 pEmptyWin->bAutoHide = false;
1130 pEmptyWin->aTimer.Stop();
1133 SetFadeIn_Impl( false );
1136 void SfxSplitWindow::FadeOut()
1138 FadeOut_Impl();
1139 SaveConfig_Impl();
1142 void SfxSplitWindow::FadeIn()
1144 SetFadeIn_Impl( true );
1147 void SfxSplitWindow::SetActiveWindow_Impl( SfxDockingWindow* pWin )
1149 pActive = pWin;
1150 pWorkWin->SetActiveChild_Impl( this );
1154 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */