LibreOffice Module sfx2 (master) 1
splitwin.cxx
Go to the documentation of this file.
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#ifdef __sun
21#include <ctime>
22#endif
23
25#include <rtl/ustrbuf.hxx>
26#include <sal/log.hxx>
27#include <tools/debug.hxx>
28
29#include <vcl/dialoghelper.hxx>
30#include <vcl/event.hxx>
31#include <vcl/timer.hxx>
32#include <vcl/svapp.hxx>
33
34#include <splitwin.hxx>
35#include <workwin.hxx>
36#include <sfx2/dockwin.hxx>
37#include <o3tl/string_view.hxx>
38
39#include <memory>
40#include <vector>
41#include <utility>
42
43using namespace ::com::sun::star::uno;
44
45#define VERSION 1
46#define nPixel 30L
47constexpr OUStringLiteral USERITEM_NAME = u"UserItem";
48
49namespace {
50 // helper class to deactivate UpdateMode, if needed, for the life time of an instance
51 class DeactivateUpdateMode
52 {
53 public:
54 explicit DeactivateUpdateMode( SfxSplitWindow& rSplitWindow )
55 : mrSplitWindow( rSplitWindow )
56 , mbUpdateMode( rSplitWindow.IsUpdateMode() )
57 {
58 if ( mbUpdateMode )
59 {
60 mrSplitWindow.SetUpdateMode( false );
61 }
62 }
63
64 ~DeactivateUpdateMode()
65 {
66 if ( mbUpdateMode )
67 {
68 mrSplitWindow.SetUpdateMode( true );
69 }
70 }
71
72 private:
73 SfxSplitWindow& mrSplitWindow;
74 const bool mbUpdateMode;
75 };
76}
77
79{
80/* [Description]
81
82 The SfxEmptySplitWin_Impldow is an empty SplitWindow, that replaces the
83 SfxSplitWindow AutoHide mode. It only serves as a placeholder to receive
84 mouse moves and if possible blend in the true SplitWindow display.
85*/
86friend class SfxSplitWindow;
87
89 bool bFadeIn;
91 bool bSplit;
95 sal_uInt16 nState;
96
97public:
99 : SplitWindow( pParent->GetParent(), WinBits( WB_BORDER | WB_3DLOOK ) )
100 , pOwner( pParent )
101 , bFadeIn( false )
102 , bAutoHide( false )
103 , bSplit( false )
104 , bEndAutoHide( false )
105 , aTimer("sfx2 SfxEmptySplitWin_Impl aTimer")
106 , nState( 1 )
107 {
109 LINK(pOwner, SfxSplitWindow, TimerHdl ) );
110 aTimer.SetTimeout( 200 );
111 SetAlign( pOwner->GetAlign() );
112 Actualize();
114 }
115
116 virtual ~SfxEmptySplitWin_Impl() override
117 { disposeOnce(); }
118 virtual void dispose() override
119 {
120 aTimer.Stop();
121 pOwner.clear();
123 }
124
125 virtual void FadeIn() override;
126 void Actualize();
127};
128
130{
131 Size aSize( pOwner->GetSizePixel() );
132 switch ( pOwner->GetAlign() )
133 {
134 case WindowAlign::Left:
135 case WindowAlign::Right:
136 aSize.setWidth( GetFadeInSize() );
137 break;
138 case WindowAlign::Top:
139 case WindowAlign::Bottom:
140 aSize.setHeight( GetFadeInSize() );
141 break;
142 }
143
144 SetSizePixel( aSize );
145}
146
148{
149 if (!bAutoHide )
151 pOwner->SetFadeIn_Impl( true );
152 if ( bAutoHide )
153 {
154 // Set Timer to close; the caller has to ensure themselves that the
155 // Window is not closed instantly (eg by setting the focus or a modal
156 // mode.
158 aTimer.Start();
159 }
160 else
161 pOwner->SaveConfig_Impl();
162}
163
164
166{
167 if ( rMEvt.GetClicks() != 2 )
169}
170
172 SfxWorkWindow *pW, bool bWithButtons )
173
174/* [Description]
175
176 A SfxSplitWindow brings the recursive structure of the SV-SplitWindows to
177 the outside by simulating a table-like structure with rows and columns
178 (maximum recursion depth 2). Furthermore, it ensures the persistence of
179 the arrangement of the SfxDockingWindows.
180*/
181
183 eAlign(eAl),
184 pWorkWin(pW),
185 bPinned(true),
186 pEmptyWin(nullptr),
187 pActive(nullptr)
188{
189 if (bWithButtons)
190 {
192 }
193
194 // Set SV-Alignment
195 WindowAlign eTbxAlign;
196 switch ( eAlign )
197 {
199 eTbxAlign = WindowAlign::Left;
200 break;
202 eTbxAlign = WindowAlign::Right;
203 break;
205 eTbxAlign = WindowAlign::Top;
206 break;
208 eTbxAlign = WindowAlign::Bottom;
209 bPinned = true;
210 break;
211 default:
212 eTbxAlign = WindowAlign::Top; // some sort of default...
213 break; // -Wall lots not handled...
214 }
215
216 SetAlign (eTbxAlign);
218 if ( bPinned )
219 {
220 pEmptyWin->bFadeIn = true;
221 pEmptyWin->nState = 2;
222 }
223
224 if ( bWithButtons )
225 {
226 // Read Configuration
227 const OUString aWindowId{ "SplitWindow" + OUString::number(static_cast<sal_Int32>(eTbxAlign)) };
228 SvtViewOptions aWinOpt( EViewType::Window, aWindowId );
229 OUString aWinData;
230 Any aUserItem = aWinOpt.GetUserItem( USERITEM_NAME );
231 OUString aTemp;
232 if ( aUserItem >>= aTemp )
233 aWinData = aTemp;
234 if ( aWinData.startsWith("V") )
235 {
236 sal_Int32 nIdx{ 0 };
237 pEmptyWin->nState = static_cast<sal_uInt16>(o3tl::toInt32(o3tl::getToken(aWinData, 1, ',', nIdx )));
238 if ( pEmptyWin->nState & 2 )
239 pEmptyWin->bFadeIn = true;
240 bPinned = true; // always assume pinned - floating mode not used anymore
241
242 const sal_Int32 nCount{ o3tl::toInt32(o3tl::getToken(aWinData, 0, ',', nIdx)) };
243 for ( sal_Int32 n=0; n<nCount; ++n )
244 {
245 std::unique_ptr<SfxDock_Impl> pDock(new SfxDock_Impl);
246 pDock->pWin = nullptr;
247 pDock->bNewLine = false;
248 pDock->bHide = true;
249 pDock->nType = static_cast<sal_uInt16>(o3tl::toInt32(o3tl::getToken(aWinData, 0, ',', nIdx)));
250 if ( !pDock->nType )
251 {
252 // could mean NewLine
253 pDock->nType = static_cast<sal_uInt16>(o3tl::toInt32(o3tl::getToken(aWinData, 0, ',', nIdx)));
254 if ( !pDock->nType )
255 {
256 // Read error
257 break;
258 }
259 else
260 pDock->bNewLine = true;
261 }
262
263 maDockArr.insert(maDockArr.begin() + n, std::move(pDock));
264 }
265 }
266 }
267 else
268 {
269 bPinned = true;
270 pEmptyWin->bFadeIn = true;
271 pEmptyWin->nState = 2;
272 }
273}
274
275
277{
278 disposeOnce();
279}
280
282{
284
285 if ( pEmptyWin )
286 {
287 // Set pOwner to NULL, otherwise try to delete pEmptyWin once more. The
288 // window that is just being docked is always deleted from the outside.
289 pEmptyWin->pOwner = nullptr;
290 }
292
293 maDockArr.clear();
294 pActive.clear();
296}
297
299{
300 // Save configuration
301 OUStringBuffer aWinData =
302 "V"
303 + OUString::number(static_cast<sal_Int32>(VERSION))
304 + ","
305 + OUString::number(static_cast<sal_Int32>(pEmptyWin->nState))
306 + ",";
307
308 sal_uInt16 nCount = 0;
309 for ( auto const & rDock: maDockArr )
310 {
311 if ( rDock->bHide || rDock->pWin )
312 nCount++;
313 }
314
315 aWinData.append(static_cast<sal_Int32>(nCount));
316
317 for ( auto const & rDock: maDockArr )
318 {
319 if ( !rDock->bHide && !rDock->pWin )
320 continue;
321 if ( rDock->bNewLine )
322 aWinData.append(",0");
323 aWinData.append("," + OUString::number(static_cast<sal_Int32>(rDock->nType)));
324 }
325
326 const OUString aWindowId{ "SplitWindow" + OUString::number(static_cast<sal_Int32>(GetAlign())) };
327 SvtViewOptions aWinOpt( EViewType::Window, aWindowId );
328 aWinOpt.SetUserItem( USERITEM_NAME, Any( aWinData.makeStringAndClear() ) );
329}
330
331
333{
334 tools::Long nSize = 0;
335 Size aSize = GetSizePixel();
336
337 if ( pEmptyWin )
338 {
339 pEmptyWin->bFadeIn = true;
340 pEmptyWin->bSplit = true;
341 }
342
344 switch ( GetAlign() )
345 {
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;
354 }
355
356 SetMaxSizePixel( nSize );
357}
358
359
361{
362 if ( bPinned )
363 {
366 }
367 else
369}
370
371
373{
374 if ( pEmptyWin )
375 pEmptyWin->bSplit = false;
376
378
379 std::vector< std::pair< sal_uInt16, tools::Long > > aNewOrgSizes;
380
381 sal_uInt16 nCount = maDockArr.size();
382 for ( sal_uInt16 n=0; n<nCount; n++ )
383 {
384 const SfxDock_Impl& rD = *maDockArr[n];
385 if ( rD.pWin )
386 {
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;
391
392 if ( IsHorizontal() )
393 {
394 aSize.setWidth( nSize );
395 aSize.setHeight( nSetSize );
396 }
397 else
398 {
399 aSize.setWidth( nSetSize );
400 aSize.setHeight( nSize );
401 }
402
403 rD.pWin->SetItemSize_Impl( aSize );
404
405 aNewOrgSizes.emplace_back( nId, nSize );
406 }
407 }
408
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
411 {
412 DeactivateUpdateMode aDeactivateUpdateMode( *this );
413 for (const std::pair< sal_uInt16, tools::Long > & rNewOrgSize : aNewOrgSizes)
414 {
415 SetItemSize( rNewOrgSize.first, rNewOrgSize.second );
416 }
417 }
418
420}
421
422
424
425/*
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.
429*/
430{
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++ )
439 {
440 SfxDock_Impl& rDock = *maDockArr[n];
441 if ( rDock.bNewLine )
442 {
443 // The window opens a new line
444 if ( pFoundDock )
445 // But after the just inserted window
446 break;
447
448 // New line
449 nPos = 0;
450 bNewLine = true;
451 }
452
453 if ( rDock.pWin )
454 {
455 // Does there exist a window now at this position
456 if ( bNewLine && !pFoundDock )
457 {
458 // Not known until now in which real line it is located
459 GetWindowPos( rDock.pWin, nL, nPos );
460 nLine = static_cast<short>(nL);
461 }
462
463 if ( !pFoundDock )
464 {
465 // The window is located before the inserted one
466 nPos++;
467 }
468
469 // Line is opened
470 bNewLine = false;
471 if ( pFoundDock )
472 break;
473 }
474
475 if ( rDock.nType == pDockWin->GetType() )
476 {
477 DBG_ASSERT( !pFoundDock && !rDock.pWin, "Window already exists!");
478 pFoundDock = &rDock;
479 if ( !bNewLine )
480 break;
481 else
482 {
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++;
488 }
489 }
490 }
491
492 if ( !pFoundDock )
493 {
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;
504 }
505
506 pFoundDock->pWin = pDockWin;
507 pFoundDock->bHide = false;
508 InsertWindow_Impl( pFoundDock, rSize, nLine, nPos, bNewLine );
509 if ( bSaveConfig )
511}
512
513
515{
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++ )
519 {
520 const SfxDock_Impl& rDock = *maDockArr[n];
521 if ( rDock.nType == pDockWin->GetType() )
522 {
523 if ( rDock.bNewLine && n<nCount-1 )
524 maDockArr[n+1]->bNewLine = true;
525
526 // Window has a position, this we forget
527 maDockArr.erase(maDockArr.begin() + n);
528 break;
529 }
530 }
531
532 if ( bSave )
534}
535
536
538 sal_uInt16 nLine, sal_uInt16 nPos, bool bNewLine)
539
540/* [Description]
541
542 The docking window is moved within the SplitWindows.
543*/
544
545{
546 sal_uInt16 nL, nP;
547 GetWindowPos( pDockWin, nL, nP );
548
549 if ( nLine > nL && GetItemCount( GetItemId( nL ) ) == 1 )
550 {
551 // If the last window is removed from its line, then everything slips
552 // one line to the front!
553 nLine--;
554 }
555 RemoveWindow( pDockWin );
556 InsertWindow( pDockWin, rSize, nLine, nPos, bNewLine );
557}
558
559
561 sal_uInt16 nLine, sal_uInt16 nPos, bool bNewLine)
562
563/* [Description]
564
565 The DockingWindow that is pushed on this SplitWindow and shall hold the
566 given position and size.
567*/
568{
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;
575
576 DBG_ASSERT( nPos==0 || !bNewLine, "Wrong Parameter!");
577 if ( bNewLine )
578 nPos = 0;
579
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);
584
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++ )
588 {
589 SfxDock_Impl& rD = *maDockArr[n];
590
591 if (rD.pWin)
592 {
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 );
600
601 if ( (nL == nLine && nP == nPos) || nL > nLine )
602 {
603 DBG_ASSERT( nL == nLine || bNewLine || nPos > 0, "Wrong Parameter!" );
604 if ( nL == nLine && nPos == 0 && !bNewLine )
605 {
606 DBG_ASSERT(rD.bNewLine, "No new line?");
607
608 // The position is pushed to nPos==0
609 rD.bNewLine = false;
610 pDock->bNewLine = true;
611 }
612
613 nInsertPos = n != 0 ? nLastWindowIdx + 1 : 0; // ignore all non-windows after the last window
614 break;
615 }
616 }
617 }
618 if (nCount != 0 && nInsertPos == nCount && nLastWindowIdx != nCount - 1)
619 {
620 nInsertPos = nLastWindowIdx + 1; // ignore all non-windows after the last window
621 }
622
623 maDockArr.insert(maDockArr.begin() + nInsertPos, std::unique_ptr<SfxDock_Impl>(pDock));
624 InsertWindow_Impl( pDock, rSize, nLine, nPos, bNewLine );
626}
627
628
630 const Size& rSize,
631 sal_uInt16 nLine, sal_uInt16 nPos, bool bNewLine)
632
633/* [Description]
634
635 Adds a DockingWindow, and causes the recalculation of the size of
636 the SplitWindows.
637*/
638
639{
640 SfxDockingWindow* pDockWin = pDock->pWin;
641
642 SplitWindowItemFlags nItemBits = SplitWindowItemFlags::NONE;
643
644 tools::Long nWinSize, nSetSize;
645 if ( IsHorizontal() )
646 {
647 nWinSize = rSize.Width();
648 nSetSize = rSize.Height();
649 }
650 else
651 {
652 nSetSize = rSize.Width();
653 nWinSize = rSize.Height();
654 }
655
656 std::unique_ptr<DeactivateUpdateMode> pDeactivateUpdateMode(new DeactivateUpdateMode( *this ));
657
658 if ( bNewLine || nLine == GetItemCount() )
659 {
660 // An existing row should not be inserted, instead a new one
661 // will be created
662
663 sal_uInt16 nId = 1;
664 for ( sal_uInt16 n=0; n<GetItemCount(); n++ )
665 {
666 if ( GetItemId(n) >= nId )
667 nId = GetItemId(n)+1;
668 }
669
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 );
675 }
676
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 );
684
685 // SplitWindows are once created in SFX and when inserting the first
686 // DockingWindows is made visible.
687 if ( GetItemCount() == 1 && GetItemCount( 1 ) == 1 )
688 {
689 // The Rearranging in WorkWindow and a Show() on the SplitWindow is
690 // caused by SfxDockingwindow (->SfxWorkWindow::ConfigChild_Impl)
691 if ( !bPinned && !IsFloatingMode() )
692 {
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" );
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
706 }
707 else
708 {
709 bool bFadeIn = ( pEmptyWin->nState & 2 ) != 0;
710 pEmptyWin->bFadeIn = false;
711 pEmptyWin->Actualize();
712 if ( !bPinned || !pEmptyWin->bFadeIn )
713 {
714 SAL_INFO("sfx", "SfxSplitWindow::InsertWindow_Impl - registering empty Splitwindow" );
715 }
716 else
717 {
718 SAL_INFO("sfx", "SfxSplitWindow::InsertWindow_Impl - registering real Splitwindow" );
719 }
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
727 }
728
730 }
731
732 pDeactivateUpdateMode.reset();
733
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
736 {
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 )
741 {
742 const SfxDock_Impl& rD = *maDockArr[n];
743 if ( rD.pWin )
744 {
745 const sal_uInt16 nId = rD.nType;
746 const tools::Long nSize = GetItemSize( nId, SplitWindowItemFlags::Fixed );
747 aNewOrgSizes.emplace_back( nId, nSize );
748 }
749 }
750 // apply new item sizes
751 DeactivateUpdateMode aDeactivateUpdateMode( *this );
752 for (const std::pair< sal_uInt16, tools::Long > & rNewOrgSize : aNewOrgSizes)
753 {
754 SetItemSize( rNewOrgSize.first, rNewOrgSize.second );
755 }
756 }
757}
758
759
760void SfxSplitWindow::RemoveWindow( SfxDockingWindow const * pDockWin, bool bHide )
761
762/* [Description]
763
764 Removes a DockingWindow. If it was the last one, then the SplitWindow is
765 being hidden.
766*/
767{
768 sal_uInt16 nSet = GetSet( pDockWin->GetType() );
769
770 // SplitWindows are once created in SFX and is made invisible after
771 // removing the last DockingWindows.
772 if ( GetItemCount( nSet ) == 1 && GetItemCount() == 1 )
773 {
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 )
782 {
783 SAL_INFO("sfx", "SfxSplitWindow::RemoveWindow - releasing empty Splitwindow" );
784 }
785 else
786 {
787 SAL_INFO("sfx", "SfxSplitWindow::RemoveWindow - releasing real Splitwindow" );
788 }
789#endif
791 pEmptyWin->nState = nRealState;
793 }
794
795 sal_uInt16 nCount = maDockArr.size();
796 for ( sal_uInt16 n=0; n<nCount; n++ )
797 {
798 SfxDock_Impl& rDock = *maDockArr[n];
799 if ( rDock.nType == pDockWin->GetType() )
800 {
801 rDock.pWin = nullptr;
802 rDock.bHide = bHide;
803 break;
804 }
805 }
806
807 // Remove Windows, and if it was the last of the line, then also remove
808 // the line (line = itemset)
809 DeactivateUpdateMode aDeactivateUpdateMode( *this );
810
811 RemoveItem( pDockWin->GetType() );
812
813 if ( nSet && !GetItemCount( nSet ) )
814 RemoveItem( nSet );
815};
816
817
819 sal_uInt16& rLine, sal_uInt16& rPos ) const
820/* [Description]
821
822 Returns the ID of the item sets and items for the DockingWindow in
823 the position passed on the old row / column-name.
824*/
825
826{
827 sal_uInt16 nSet = GetSet ( pWindow->GetType() );
828 if ( nSet == SPLITWINDOW_ITEM_NOTFOUND )
829 return false;
830
831 rPos = GetItemPos( pWindow->GetType(), nSet );
832 rLine = GetItemPos( nSet );
833 return true;
834}
835
836
838 sal_uInt16& rLine, sal_uInt16& rPos ) const
839/* [Description]
840
841 Returns the ID of the item sets and items for the DockingWindow in
842 the position passed on the old row / column-name.
843*/
844
845{
846 sal_uInt16 nId = GetItemId( rTestPos );
847 if ( nId == 0 )
848 return false;
849
850 sal_uInt16 nSet = GetSet ( nId );
851 rPos = GetItemPos( nId, nSet );
852 rLine = GetItemPos( nSet );
853 return true;
854}
855
856
858
859/* [Description]
860
861 Returns the number of rows = number of sub-itemsets in the root set.
862*/
863{
864 return GetItemCount();
865}
866
867
869
870/* [Description]
871
872 Returns the Row Height of nline itemset.
873*/
874{
875 sal_uInt16 nId = GetItemId( nLine );
876 return GetItemSize( nId );
877}
878
879
880sal_uInt16 SfxSplitWindow::GetWindowCount( sal_uInt16 nLine ) const
881
882/* [Description]
883
884 Returns the total number of windows
885*/
886{
887 sal_uInt16 nId = GetItemId( nLine );
888 return GetItemCount( nId );
889}
890
891
893
894/* [Description]
895
896 Returns the total number of windows
897*/
898{
899 return GetItemCount();
900}
901
902
903IMPL_LINK( SfxSplitWindow, TimerHdl, Timer*, pTimer, void)
904{
905 if ( pTimer )
906 pTimer->Stop();
907
908 if ( CursorIsOverRect() || !pTimer )
909 {
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();
915
916 pEmptyWin->aLastPos = GetPointerPosPixel();
917 pEmptyWin->aTimer.Start();
918 }
919 else if ( pEmptyWin->bAutoHide )
920 {
921 if ( GetPointerPosPixel() != pEmptyWin->aLastPos )
922 {
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;
928 }
929
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() )
934 {
935 pEmptyWin->bEndAutoHide = false;
938 !pEmptyWin->bSplit && !HasChildPathFocus( true ) )
939 {
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;
945 }
946
947 if ( pEmptyWin->bEndAutoHide )
948 {
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 ) )
953 {
954 FadeOut_Impl();
956 }
957 else
958 {
959 pEmptyWin->aLastPos = GetPointerPosPixel();
960 pEmptyWin->aTimer.Start();
961 }
962 }
963 else
964 {
965 pEmptyWin->aLastPos = GetPointerPosPixel();
966 pEmptyWin->aTimer.Start();
967 }
968 }
969 }
970}
971
972
974{
975 bool bVisible = IsVisible();
976
977 // Also, take the collapsed SplitWindow into account
978 Point aPos = pEmptyWin->GetParent()->OutputToScreenPixel( pEmptyWin->GetPosPixel() );
979 Size aSize = pEmptyWin->GetSizePixel();
980
981 tools::Rectangle aRect( aPos, aSize );
982
983 if ( bVisible )
984 {
985 Point aVisPos = GetPosPixel();
986 Size aVisSize = GetSizePixel();
987
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 );
993
994 tools::Rectangle aVisRect( aVisPos, aVisSize );
995 aRect = aRect.GetUnion( aVisRect );
996 }
997
998 return aRect.Contains( OutputToScreenPixel( static_cast<vcl::Window*>(const_cast<SfxSplitWindow *>(this))->GetPointerPosPixel() ) );
999}
1000
1001
1003{
1004 if ( !bPinned || !pEmptyWin->bFadeIn )
1005 return pEmptyWin;
1006 return this;
1007}
1008
1009
1011{
1012 return pEmptyWin->bFadeIn;
1013}
1014
1015bool SfxSplitWindow::IsAutoHide( bool bSelf ) const
1016{
1017 return bSelf ? pEmptyWin->bAutoHide && !pEmptyWin->bEndAutoHide : pEmptyWin->bAutoHide;
1018}
1019
1020
1022{
1023 if ( bPinned == bOn )
1024 return;
1025
1026 bPinned = bOn;
1027 if ( GetItemCount() == 0 )
1028 return;
1029
1030 if ( !bOn )
1031 {
1032 pEmptyWin->nState |= 1;
1033 if ( pEmptyWin->bFadeIn )
1034 {
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" );
1042 }
1043
1044 Point aPos( GetPosPixel() );
1045 aPos = GetParent()->OutputToScreenPixel( aPos );
1046 SetFloatingPos( aPos );
1047 SetFloatingMode( true );
1049
1050 if ( pEmptyWin->bFadeIn )
1051 Show();
1052 }
1053 else
1054 {
1055 pEmptyWin->nState &= ~1;
1057 SetFloatingMode(false);
1058
1059 if ( pEmptyWin->bFadeIn )
1060 {
1061 // Unregister replacement windows
1062 SAL_INFO("sfx", "SfxSplitWindow::SetPinned_Impl - releasing empty Splitwindow" );
1064 pEmptyWin->Hide();
1065 SAL_INFO("sfx", "SfxSplitWindow::SetPinned_Impl - registering real Splitwindow" );
1067 }
1068 }
1069}
1070
1072{
1073 if ( bOn == pEmptyWin->bFadeIn )
1074 return;
1075
1076 if ( GetItemCount() == 0 )
1077 return;
1078
1079 pEmptyWin->bFadeIn = bOn;
1080 if ( bOn )
1081 {
1082 pEmptyWin->nState |= 2;
1083 if ( IsFloatingMode() )
1084 {
1085 // FloatingWindow is not visible, thus display it
1087 Show();
1088 }
1089 else
1090 {
1091 SAL_INFO("sfx", "SfxSplitWindow::SetFadeIn_Impl - releasing empty Splitwindow" );
1093 pEmptyWin->Hide();
1094 SAL_INFO("sfx", "SfxSplitWindow::SetFadeIn_Impl - registering real Splitwindow" );
1098 }
1099 }
1100 else
1101 {
1102 pEmptyWin->bAutoHide = false;
1103 pEmptyWin->nState &= ~2;
1104 if ( !IsFloatingMode() )
1105 {
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" );
1116 }
1117 else
1118 {
1119 Hide();
1121 }
1122 }
1123}
1124
1126{
1127 if ( pEmptyWin->aTimer.IsActive() )
1128 {
1129 pEmptyWin->bAutoHide = false;
1130 pEmptyWin->aTimer.Stop();
1131 }
1132
1133 SetFadeIn_Impl( false );
1134}
1135
1137{
1138 FadeOut_Impl();
1140}
1141
1143{
1144 SetFadeIn_Impl( true );
1145}
1146
1148{
1149 pActive = pWin;
1151}
1152
1153
1154/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SfxChildAlignment
Definition: chalign.hxx:27
static bool IsInModalMode()
void SetOutputSizePixel(const Size &rNewSize) override
Point GetPosPixel() const override
bool IsFloatingMode() const
void SetFloatingMode(bool bFloatMode)
Size GetSizePixel() const override
Size GetOutputSizePixel() const
SystemWindow * GetFloatingWindow() const
void SetFloatingPos(const Point &rNewPos)
sal_uInt16 GetClicks() const
tools::Long AdjustY(tools::Long nVertMove)
tools::Long AdjustX(tools::Long nHorzMove)
sal_uInt16 GetType() const
Definition: dockwin.hxx:97
virtual void FadeIn() override
Definition: splitwin.cxx:147
virtual void dispose() override
Definition: splitwin.cxx:118
VclPtr< SfxSplitWindow > pOwner
Definition: splitwin.cxx:88
virtual ~SfxEmptySplitWin_Impl() override
Definition: splitwin.cxx:116
SfxEmptySplitWin_Impl(SfxSplitWindow *pParent)
Definition: splitwin.cxx:98
std::vector< std::unique_ptr< SfxDock_Impl > > maDockArr
Definition: splitwin.hxx:49
VclPtr< SfxEmptySplitWin_Impl > pEmptyWin
Definition: splitwin.hxx:51
bool CursorIsOverRect() const
Definition: splitwin.cxx:973
sal_uInt16 GetWindowCount() const
Definition: splitwin.cxx:892
VclPtr< SfxDockingWindow > pActive
Definition: splitwin.hxx:52
sal_uInt16 GetLineCount() const
Definition: splitwin.cxx:857
void InsertWindow_Impl(SfxDock_Impl const *pDockWin, const Size &rSize, sal_uInt16 nLine, sal_uInt16 nPos, bool bNewLine)
Definition: splitwin.cxx:629
SplitWindow * GetSplitWindow()
Definition: splitwin.cxx:1002
SfxChildAlignment eAlign
Definition: splitwin.hxx:46
void InsertWindow(SfxDockingWindow *pDockWin, const Size &rSize)
Definition: splitwin.cxx:423
virtual void dispose() override
Definition: splitwin.cxx:281
void SetActiveWindow_Impl(SfxDockingWindow *pWin)
Definition: splitwin.cxx:1147
bool GetWindowPos(const SfxDockingWindow *pWindow, sal_uInt16 &rLine, sal_uInt16 &rPos) const
Definition: splitwin.cxx:818
bool IsAutoHide(bool bSelf) const
Definition: splitwin.cxx:1015
SfxSplitWindow(vcl::Window *pParent, SfxChildAlignment eAl, SfxWorkWindow *pW, bool bWithButtons)
Definition: splitwin.cxx:171
virtual ~SfxSplitWindow() override
Definition: splitwin.cxx:276
virtual void Split() override
Definition: splitwin.cxx:372
void MoveWindow(SfxDockingWindow *pDockWin, const Size &rSize, sal_uInt16 nLine, sal_uInt16 nPos, bool bNewLine)
Definition: splitwin.cxx:537
void FadeOut_Impl()
Definition: splitwin.cxx:1125
SfxWorkWindow * pWorkWin
Definition: splitwin.hxx:47
void ReleaseWindow_Impl(SfxDockingWindow const *pWin, bool bSaveConfig=true)
Definition: splitwin.cxx:514
void SetPinned_Impl(bool)
Definition: splitwin.cxx:1021
virtual void FadeOut() override
Definition: splitwin.cxx:1136
bool IsFadeIn() const
Definition: splitwin.cxx:1010
tools::Long GetLineSize(sal_uInt16) const
Definition: splitwin.cxx:868
void SaveConfig_Impl()
Definition: splitwin.cxx:298
virtual void MouseButtonDown(const MouseEvent &) override
Definition: splitwin.cxx:165
void SetFadeIn_Impl(bool)
Definition: splitwin.cxx:1071
void RemoveWindow(SfxDockingWindow const *pDockWin, bool bHide=true)
Definition: splitwin.cxx:760
virtual void StartSplit() override
Definition: splitwin.cxx:332
virtual void FadeIn() override
Definition: splitwin.cxx:1142
virtual void SplitResize() override
Definition: splitwin.cxx:360
void ArrangeChildren_Impl(bool bForce=true)
Definition: workwin.cxx:654
void SetActiveChild_Impl(vcl::Window *pChild)
Definition: workwin.cxx:2424
void ReleaseChild_Impl(vcl::Window &rWindow)
Definition: workwin.cxx:909
SfxChild_Impl * RegisterChild_Impl(vcl::Window &rWindow, SfxChildAlignment eAlign)
Definition: workwin.cxx:875
void ShowChildren_Impl()
Definition: workwin.cxx:961
bool IsAutoHideMode(const SfxSplitWindow *pSplit)
Definition: workwin.cxx:2240
tools::Rectangle GetFreeArea(bool bAutoHide) const
Definition: workwin.cxx:2390
void ArrangeAutoHideWindows(SfxSplitWindow *pSplit)
Definition: workwin.cxx:2265
constexpr tools::Long Height() const
tools::Long AdjustHeight(tools::Long n)
void setWidth(tools::Long nWidth)
tools::Long AdjustWidth(tools::Long n)
void setHeight(tools::Long nHeight)
constexpr tools::Long Width() const
WindowAlign GetAlign() const
sal_uInt16 GetItemPos(sal_uInt16 nId, sal_uInt16 nSetId=0) const
sal_uInt16 GetItemId(vcl::Window *pWindow) const
virtual void Split()
virtual void MouseButtonDown(const MouseEvent &rMEvt) override
void SetAlign(WindowAlign eNewAlign)
void ShowFadeInHideButton()
tools::Long GetItemSize(sal_uInt16 nId) const
bool IsHorizontal() const
tools::Long GetFadeInSize() const
bool IsFadeNoButtonMode() const
virtual void dispose() override
void ShowFadeOutButton()
sal_uInt16 GetItemCount(sal_uInt16 nSetId=0) const
sal_uInt16 GetSet(sal_uInt16 nId) const
void InsertItem(sal_uInt16 nId, vcl::Window *pWindow, tools::Long nSize, sal_uInt16 nPos, sal_uInt16 nIntoSetId, SplitWindowItemFlags nBits)
void RemoveItem(sal_uInt16 nId)
void SetItemSize(sal_uInt16 nId, tools::Long nNewSize)
void SetMaxSizePixel(tools::Long nNewMaxSize)
css::uno::Any GetUserItem(const OUString &sName) const
void SetUserItem(const OUString &sName, const css::uno::Any &aValue)
void Stop()
void SetTimeout(sal_uInt64 nTimeoutMs)
void SetInvokeHandler(const Link< Timer *, void > &rLink)
virtual void Start(bool bStartTimer=true) override
void disposeAndClear()
void clear()
static VclPtr< reference_type > Create(Arg &&... arg)
constexpr tools::Long GetWidth() const
bool Contains(const Point &rPOINT) const
tools::Rectangle GetUnion(const tools::Rectangle &rRect) const
constexpr tools::Long GetHeight() const
Point OutputToScreenPixel(const Point &rPos) const
vcl::Window * GetParent() const
bool HasChildPathFocus(bool bSystemWindow=false) const
virtual void SetSizePixel(const Size &rNewSize)
bool IsUpdateMode() const
virtual void SetOutputSizePixel(const Size &rNewSize)
void Show(bool bVisible=true, ShowFlags nFlags=ShowFlags::NONE)
Point GetPointerPosPixel()
bool IsVisible() const
int nCount
#define DBG_ASSERT(sCon, aError)
float u
sal_Int64 n
sal_uInt16 nPos
Definition: linksrc.cxx:118
#define SAL_INFO(area, stream)
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
long Long
bool IsInPopupMenuExecute()
sal_Int16 nId
#define VERSION
Definition: splitwin.cxx:45
IMPL_LINK(SfxSplitWindow, TimerHdl, Timer *, pTimer, void)
Definition: splitwin.cxx:903
#define nPixel
Definition: splitwin.cxx:46
constexpr OUStringLiteral USERITEM_NAME
Definition: splitwin.cxx:47
#define SPLITWINDOW_ITEM_NOTFOUND
SplitWindowItemFlags
SfxChildVisibility nVisible
Definition: workwin.hxx:88
bool bNewLine
Definition: splitwin.hxx:37
sal_uInt16 nType
Definition: splitwin.hxx:35
VclPtr< SfxDockingWindow > pWin
Definition: splitwin.hxx:36
bool bVisible
sal_Int64 WinBits
WinBits const WB_SIZEABLE
WinBits const WB_3DLOOK
WinBits const WB_BORDER
WindowAlign
WinBits const WB_HIDE