build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / vcl / source / window / splitwin.cxx
blobe1582cd96d1e481fb9d512f2656eeb2f23b443d4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <string.h>
22 #include <tools/debug.hxx>
23 #include <tools/rcid.h>
25 #include <vcl/event.hxx>
26 #include <vcl/wall.hxx>
27 #include <vcl/bitmap.hxx>
28 #include <vcl/decoview.hxx>
29 #include <vcl/image.hxx>
30 #include <vcl/help.hxx>
31 #include <vcl/splitwin.hxx>
32 #include <vcl/settings.hxx>
34 #include <rsc/rsc-vcl-shared-types.hxx>
36 #include <svdata.hxx>
37 #include <svids.hrc>
40 #define SPLITWIN_SPLITSIZE 4
41 #define SPLITWIN_SPLITSIZEEX 4
42 #define SPLITWIN_SPLITSIZEEXLN 7
43 #define SPLITWIN_SPLITSIZEAUTOHIDE 72
44 #define SPLITWIN_SPLITSIZEFADE 72
46 #define SPLIT_HORZ ((sal_uInt16)0x0001)
47 #define SPLIT_VERT ((sal_uInt16)0x0002)
48 #define SPLIT_WINDOW ((sal_uInt16)0x0004)
49 #define SPLIT_NOSPLIT ((sal_uInt16)0x8000)
51 class ImplSplitItem
53 public:
54 ImplSplitItem();
55 ~ImplSplitItem();
56 void dispose();
58 long mnSize;
59 long mnPixSize;
60 long mnLeft;
61 long mnTop;
62 long mnWidth;
63 long mnHeight;
64 long mnSplitPos;
65 long mnSplitSize;
66 long mnOldSplitPos;
67 long mnOldSplitSize;
68 long mnOldWidth;
69 long mnOldHeight;
70 ImplSplitSet* mpSet;
71 VclPtr<vcl::Window> mpWindow;
72 VclPtr<vcl::Window> mpOrgParent;
73 sal_uInt16 mnId;
74 SplitWindowItemFlags mnBits;
75 bool mbFixed;
76 bool mbSubSize;
77 /// Minimal width or height of the item. -1 means no restriction.
78 long mnMinSize;
79 /// Maximal width or height of the item. -1 means no restriction.
80 long mnMaxSize;
84 class ImplSplitSet
86 public:
87 ImplSplitSet();
88 ~ImplSplitSet();
89 void dispose();
91 std::vector< ImplSplitItem* > mpItems;
92 Wallpaper* mpWallpaper;
93 Bitmap* mpBitmap;
94 long mnLastSize;
95 long mnSplitSize;
96 sal_uInt16 mnId;
97 bool mbCalcPix;
100 ImplSplitItem::ImplSplitItem()
101 : mnSize(0)
102 , mnPixSize(0)
103 , mnLeft(0)
104 , mnTop(0)
105 , mnWidth(0)
106 , mnHeight(0)
107 , mnSplitPos(0)
108 , mnSplitSize(0)
109 , mnOldSplitPos(0)
110 , mnOldSplitSize(0)
111 , mnOldWidth(0)
112 , mnOldHeight(0)
113 , mpSet(nullptr)
114 , mnId(0)
115 , mnBits(SplitWindowItemFlags::NONE)
116 , mbFixed(false)
117 , mbSubSize(false)
118 , mnMinSize(-1)
119 , mnMaxSize(-1)
123 ImplSplitItem::~ImplSplitItem()
125 dispose();
128 void ImplSplitItem::dispose()
130 if (mpSet) {
131 delete mpSet ;
132 mpSet = nullptr;
134 mpWindow.clear();
135 mpOrgParent.clear();
138 ImplSplitSet::ImplSplitSet() :
139 mpWallpaper( nullptr ),
140 mpBitmap( nullptr ),
141 mnLastSize( 0 ),
142 mnSplitSize( SPLITWIN_SPLITSIZE ),
143 mnId( 0 ),
144 mbCalcPix( true )
148 ImplSplitSet::~ImplSplitSet()
150 dispose();
153 void ImplSplitSet::dispose()
155 size_t nItems = mpItems.size();
157 for ( size_t i = 0; i < nItems; i++ )
158 delete mpItems[i];
159 mpItems.clear();
161 if ( mpWallpaper ) {
162 delete mpWallpaper;
163 mpWallpaper = nullptr;
166 if ( mpBitmap ) {
167 delete mpBitmap;
168 mpBitmap = nullptr;
172 /** Check whether the given size is inside the valid range defined by
173 [rItem.mnMinSize,rItem.mnMaxSize]. When it is not inside it then return
174 the upper or lower bound, respectively. Otherwise return the given size
175 unmodified.
176 Note that either mnMinSize and/or mnMaxSize can be -1 in which case the
177 size has not lower or upper bound.
179 namespace {
180 long ValidateSize (const long nSize, const ImplSplitItem* pItem)
182 if (pItem->mnMinSize>=0 && nSize<pItem->mnMinSize)
183 return pItem->mnMinSize;
184 else if (pItem->mnMaxSize>0 && nSize>pItem->mnMaxSize)
185 return pItem->mnMaxSize;
186 else
187 return nSize;
191 static void ImplCalcBorder( WindowAlign eAlign, bool bNoAlign,
192 long& rLeft, long& rTop,
193 long& rRight, long& rBottom )
195 if ( bNoAlign )
197 rLeft = 2;
198 rTop = 2;
199 rRight = 2;
200 rBottom = 2;
202 else
204 switch ( eAlign )
206 case WindowAlign::Top:
207 rLeft = 2;
208 rTop = 2;
209 rRight = 2;
210 rBottom = 0;
211 break;
212 case WindowAlign::Left:
213 rLeft = 0;
214 rTop = 2;
215 rRight = 2;
216 rBottom = 2;
217 break;
218 case WindowAlign::Bottom:
219 rLeft = 2;
220 rTop = 0;
221 rRight = 2;
222 rBottom = 2;
223 break;
224 default:
225 rLeft = 0;
226 rTop = 2;
227 rRight = 2;
228 rBottom = 2;
229 break;
234 void SplitWindow::ImplDrawBorder(vcl::RenderContext& rRenderContext)
236 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
237 long nDX = mnDX;
238 long nDY = mnDY;
240 switch (meAlign)
242 case WindowAlign::Bottom:
243 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
244 rRenderContext.DrawLine(Point(0, 0), Point(nDX - 1, 0));
245 rRenderContext.DrawLine(Point(0, nDY - 2), Point(nDX - 1, nDY - 2));
247 rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
248 rRenderContext.DrawLine(Point(0, 1), Point(nDX - 1, 1));
249 rRenderContext.DrawLine(Point(0, nDY - 1), Point(nDX - 1, nDY - 1));
250 break;
251 case WindowAlign::Top:
252 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
253 rRenderContext.DrawLine(Point(0, nDY - 2), Point(nDX - 1, nDY - 2));
254 rRenderContext.DrawLine(Point(0, 0), Point(nDX - 1, 0));
256 rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
257 rRenderContext.DrawLine(Point(0, nDY - 1), Point(nDX - 1, nDY - 1));
258 rRenderContext.DrawLine(Point(0, 1), Point(nDX - 1, 1));
259 break;
260 case WindowAlign::Left:
261 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
262 rRenderContext.DrawLine(Point(nDX - 2, 0), Point(nDX - 2, nDY - 2));
263 rRenderContext.DrawLine(Point(0, 0), Point(nDX - 1, 0));
264 rRenderContext.DrawLine(Point(0, nDY - 2), Point(nDX - 2, nDY - 2));
266 rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
267 rRenderContext.DrawLine(Point(nDX - 1, 0), Point(nDX - 1, nDY - 1));
268 rRenderContext.DrawLine(Point(0, 1), Point(nDX - 3, 1));
269 rRenderContext.DrawLine(Point(0, nDY - 1), Point(nDX - 2, nDY - 1));
270 break;
271 default:
272 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
273 rRenderContext.DrawLine(Point(0, 0), Point( 0, nDY - 2));
274 rRenderContext.DrawLine(Point(0, 0), Point( nDX - 1, 0));
275 rRenderContext.DrawLine(Point(0, nDY - 2), Point(nDX - 1, nDY - 2));
277 rRenderContext.SetLineColor( rStyleSettings.GetLightColor());
278 rRenderContext.DrawLine(Point(1, 1), Point(1, nDY - 3));
279 rRenderContext.DrawLine(Point(1, 1), Point(nDX - 1, 1));
280 rRenderContext.DrawLine(Point(0, nDY - 1), Point(nDX - 1, nDY - 1));
284 void SplitWindow::ImplDrawBorderLine(vcl::RenderContext& rRenderContext)
286 if (mbFadeOut || mbAutoHide)
288 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
289 long nDX = mnDX;
290 long nDY = mnDY;
292 switch (meAlign)
294 case WindowAlign::Left:
295 rRenderContext.SetLineColor( rStyleSettings.GetShadowColor() );
296 rRenderContext.DrawLine( Point( nDX-SPLITWIN_SPLITSIZEEXLN-1, 1 ), Point( nDX-SPLITWIN_SPLITSIZEEXLN-1, nDY-2 ) );
298 rRenderContext.SetLineColor( rStyleSettings.GetLightColor() );
299 rRenderContext.DrawLine( Point( nDX-SPLITWIN_SPLITSIZEEXLN, 1 ), Point( nDX-SPLITWIN_SPLITSIZEEXLN, nDY-3 ) );
300 break;
301 case WindowAlign::Right:
302 rRenderContext.SetLineColor( rStyleSettings.GetShadowColor() );
303 rRenderContext.DrawLine( Point( SPLITWIN_SPLITSIZEEXLN-1, 0 ), Point( SPLITWIN_SPLITSIZEEXLN-1, nDY-2 ) );
305 rRenderContext.SetLineColor( rStyleSettings.GetLightColor() );
306 rRenderContext.DrawLine( Point( SPLITWIN_SPLITSIZEEXLN, 1 ), Point( SPLITWIN_SPLITSIZEEXLN, nDY-3 ) );
307 break;
308 case WindowAlign::Top:
309 rRenderContext.SetLineColor( rStyleSettings.GetShadowColor() );
310 rRenderContext.DrawLine( Point( 0, nDY-SPLITWIN_SPLITSIZEEXLN-1 ), Point( nDX-1, nDY-SPLITWIN_SPLITSIZEEXLN-1 ) );
312 rRenderContext.SetLineColor( rStyleSettings.GetLightColor() );
313 rRenderContext.DrawLine( Point( 0, nDY-SPLITWIN_SPLITSIZEEXLN ), Point( nDX-1, nDY-SPLITWIN_SPLITSIZEEXLN ) );
314 break;
315 case WindowAlign::Bottom:
316 rRenderContext.SetLineColor( rStyleSettings.GetShadowColor() );
317 rRenderContext.DrawLine( Point( 0, 5 ), Point( nDX-1, 5 ) );
319 rRenderContext.SetLineColor( rStyleSettings.GetLightColor() );
320 rRenderContext.DrawLine( Point( 0, SPLITWIN_SPLITSIZEEXLN ), Point( nDX-1, SPLITWIN_SPLITSIZEEXLN ) );
321 break;
326 static ImplSplitSet* ImplFindSet( ImplSplitSet* pSet, sal_uInt16 nId )
328 if ( pSet->mnId == nId )
329 return pSet;
331 sal_uInt16 i;
332 size_t nItems = pSet->mpItems.size();
333 std::vector< ImplSplitItem* >& rItems = pSet->mpItems;
335 for ( i = 0; i < nItems; i++ )
337 if ( rItems[i]->mnId == nId )
338 return rItems[i]->mpSet;
341 for ( i = 0; i < nItems; i++ )
343 if ( rItems[i]->mpSet )
345 ImplSplitSet* pFindSet = ImplFindSet( rItems[i]->mpSet, nId );
346 if ( pFindSet )
347 return pFindSet;
351 return nullptr;
354 static ImplSplitSet* ImplFindItem( ImplSplitSet* pSet, sal_uInt16 nId, sal_uInt16& rPos )
356 sal_uInt16 i;
357 size_t nItems = pSet->mpItems.size();
358 std::vector< ImplSplitItem* >& rItems = pSet->mpItems;
360 for ( i = 0; i < nItems; i++ )
362 if ( rItems[i]->mnId == nId )
364 rPos = i;
365 return pSet;
369 for ( i = 0; i < nItems; i++ )
371 if ( rItems[i]->mpSet )
373 ImplSplitSet* pFindSet = ImplFindItem( rItems[i]->mpSet, nId, rPos );
374 if ( pFindSet )
375 return pFindSet;
379 return nullptr;
382 static sal_uInt16 ImplFindItem( ImplSplitSet* pSet, vcl::Window* pWindow )
384 sal_uInt16 i;
385 size_t nItems = pSet->mpItems.size();
386 std::vector< ImplSplitItem* >& rItems = pSet->mpItems;
388 for ( i = 0; i < nItems; i++ )
390 if ( rItems[i]->mpWindow == pWindow )
391 return rItems[i]->mnId;
392 else
394 if ( rItems[i]->mpSet )
396 sal_uInt16 nId = ImplFindItem( rItems[i]->mpSet, pWindow );
397 if ( nId )
398 return nId;
403 return 0;
406 static sal_uInt16 ImplFindItem( ImplSplitSet* pSet, const Point& rPos,
407 bool bRows, bool bDown = true )
409 sal_uInt16 i;
410 size_t nItems = pSet->mpItems.size();
411 std::vector< ImplSplitItem* >& rItems = pSet->mpItems;
413 for ( i = 0; i < nItems; i++ )
415 if ( rItems[i]->mnWidth && rItems[i]->mnHeight )
417 Point aPoint( rItems[i]->mnLeft, rItems[i]->mnTop );
418 Size aSize( rItems[i]->mnWidth, rItems[i]->mnHeight );
419 Rectangle aRect( aPoint, aSize );
420 if ( bRows )
422 if ( bDown )
423 aRect.Bottom() += pSet->mnSplitSize;
424 else
425 aRect.Top() -= pSet->mnSplitSize;
427 else
429 if ( bDown )
430 aRect.Right() += pSet->mnSplitSize;
431 else
432 aRect.Left() -= pSet->mnSplitSize;
435 if ( aRect.IsInside( rPos ) )
437 if ( rItems[i]->mpSet && !rItems[i]->mpSet->mpItems.empty() )
439 return ImplFindItem( rItems[i]->mpSet, rPos,
440 !(rItems[i]->mnBits & SplitWindowItemFlags::ColSet) );
442 else
443 return rItems[i]->mnId;
448 return 0;
451 static void ImplCalcSet( ImplSplitSet* pSet,
452 long nSetLeft, long nSetTop,
453 long nSetWidth, long nSetHeight,
454 bool bRows, bool bDown = true )
456 if ( pSet->mpItems.empty() )
457 return;
459 sal_uInt16 i;
460 sal_uInt16 j;
461 sal_uInt16 nMins;
462 sal_uInt16 nCalcItems;
463 size_t nItems = pSet->mpItems.size();
464 sal_uInt16 nVisItems;
465 sal_uInt16 nAbsItems;
466 long nCalcSize;
467 long nPos;
468 long nMaxPos;
469 std::vector< ImplSplitItem* >& rItems = pSet->mpItems;
470 bool bEmpty;
472 // get number of visible items
473 nVisItems = 0;
474 for ( i = 0; i < nItems; i++ )
476 if ( !(rItems[i]->mnBits & SplitWindowItemFlags::Invisible) )
477 nVisItems++;
480 // calculate sizes
481 if ( bRows )
482 nCalcSize = nSetHeight;
483 else
484 nCalcSize = nSetWidth;
485 nCalcSize -= (nVisItems-1)*pSet->mnSplitSize;
486 if ( pSet->mbCalcPix || (pSet->mnLastSize != nCalcSize) )
488 long nPercentFactor = 10;
489 long nRelCount = 0;
490 long nPercent = 0;
491 long nRelPercent = 0;
492 long nAbsSize = 0;
493 long nCurSize = 0;
494 for ( i = 0; i < nItems; i++ )
496 if ( !(rItems[i]->mnBits & SplitWindowItemFlags::Invisible) )
498 if ( rItems[i]->mnBits & SplitWindowItemFlags::RelativeSize )
499 nRelCount += rItems[i]->mnSize;
500 else if ( rItems[i]->mnBits & SplitWindowItemFlags::PercentSize )
501 nPercent += rItems[i]->mnSize;
502 else
503 nAbsSize += rItems[i]->mnSize;
506 // map relative values to percentages (percentage here one tenth of a procent)
507 nPercent *= nPercentFactor;
508 if ( nRelCount )
510 long nRelPercentBase = 1000;
511 while ( (nRelCount > nRelPercentBase) && (nPercentFactor < 100000) )
513 nRelPercentBase *= 10;
514 nPercentFactor *= 10;
516 if ( nPercent < nRelPercentBase )
518 nRelPercent = (nRelPercentBase-nPercent)/nRelCount;
519 nPercent += nRelPercent*nRelCount;
521 else
522 nRelPercent = 0;
524 if ( !nPercent )
525 nPercent = 1;
526 long nSizeDelta = nCalcSize-nAbsSize;
527 for ( i = 0; i < nItems; i++ )
529 if ( rItems[i]->mnBits & SplitWindowItemFlags::Invisible )
530 rItems[i]->mnPixSize = 0;
531 else if ( rItems[i]->mnBits & SplitWindowItemFlags::RelativeSize )
533 if ( nSizeDelta <= 0 )
534 rItems[i]->mnPixSize = 0;
535 else
536 rItems[i]->mnPixSize = (nSizeDelta*rItems[i]->mnSize*nRelPercent)/nPercent;
538 else if ( rItems[i]->mnBits & SplitWindowItemFlags::PercentSize )
540 if ( nSizeDelta <= 0 )
541 rItems[i]->mnPixSize = 0;
542 else
543 rItems[i]->mnPixSize = (nSizeDelta*rItems[i]->mnSize*nPercentFactor)/nPercent;
545 else
546 rItems[i]->mnPixSize = rItems[i]->mnSize;
547 nCurSize += rItems[i]->mnPixSize;
550 pSet->mbCalcPix = false;
551 pSet->mnLastSize = nCalcSize;
553 // adapt window
554 nSizeDelta = nCalcSize-nCurSize;
555 if ( nSizeDelta )
557 nAbsItems = 0;
558 long nSizeWinSize = 0;
560 // first resize absolute items relative
561 for ( i = 0; i < nItems; i++ )
563 if ( !(rItems[i]->mnBits & SplitWindowItemFlags::Invisible) )
565 if ( !(rItems[i]->mnBits & (SplitWindowItemFlags::RelativeSize | SplitWindowItemFlags::PercentSize)) )
567 nAbsItems++;
568 nSizeWinSize += rItems[i]->mnPixSize;
572 // do not compensate rounding errors here
573 if ( (nAbsItems < (sal_uInt16)(std::abs( nSizeDelta ))) && nSizeWinSize )
575 long nNewSizeWinSize = 0;
577 for ( i = 0; i < nItems; i++ )
579 if ( !(rItems[i]->mnBits & SplitWindowItemFlags::Invisible) )
581 if ( !(rItems[i]->mnBits & (SplitWindowItemFlags::RelativeSize | SplitWindowItemFlags::PercentSize)) )
583 rItems[i]->mnPixSize += (nSizeDelta*rItems[i]->mnPixSize)/nSizeWinSize;
584 nNewSizeWinSize += rItems[i]->mnPixSize;
589 nSizeDelta -= nNewSizeWinSize-nSizeWinSize;
592 // compensate rounding errors now
593 j = 0;
594 nMins = 0;
595 while ( nSizeDelta && (nItems != nMins) )
597 // determine which items we can calculate
598 nCalcItems = 0;
599 while ( !nCalcItems )
601 for ( i = 0; i < nItems; i++ )
603 rItems[i]->mbSubSize = false;
605 if ( j >= 2 )
606 rItems[i]->mbSubSize = true;
607 else
609 if ( !(rItems[i]->mnBits & SplitWindowItemFlags::Invisible) )
611 if ( (nSizeDelta > 0) || rItems[i]->mnPixSize )
613 if ( j >= 1 )
614 rItems[i]->mbSubSize = true;
615 else
617 if ( (j == 0) && (rItems[i]->mnBits & (SplitWindowItemFlags::RelativeSize | SplitWindowItemFlags::PercentSize)) )
618 rItems[i]->mbSubSize = true;
624 if ( rItems[i]->mbSubSize )
625 nCalcItems++;
628 j++;
631 // subtract size of individual items
632 long nErrorSum = nSizeDelta % nCalcItems;
633 long nCurSizeDelta = nSizeDelta / nCalcItems;
634 nMins = 0;
635 for ( i = 0; i < nItems; i++ )
637 if ( rItems[i]->mnBits & SplitWindowItemFlags::Invisible )
638 nMins++;
639 else if ( rItems[i]->mbSubSize )
641 long* pSize = &(rItems[i]->mnPixSize);
642 long nTempErr;
644 if ( nErrorSum )
646 if ( nErrorSum < 0 )
647 nTempErr = -1;
648 else
649 nTempErr = 1;
651 else
652 nTempErr = 0;
654 if ( (*pSize+nCurSizeDelta+nTempErr) <= 0 )
656 long nTemp = *pSize;
657 if ( nTemp )
659 *pSize -= nTemp;
660 nSizeDelta += nTemp;
662 nMins++;
664 else
666 *pSize += nCurSizeDelta;
667 nSizeDelta -= nCurSizeDelta;
668 if ( nTempErr && (*pSize || (nTempErr > 0)) )
670 *pSize += nTempErr;
671 nSizeDelta -= nTempErr;
672 nErrorSum -= nTempErr;
681 // calculate maximum size
682 if ( bRows )
684 nPos = nSetTop;
685 if ( !bDown )
686 nMaxPos = nSetTop-nSetHeight;
687 else
688 nMaxPos = nSetTop+nSetHeight;
690 else
692 nPos = nSetLeft;
693 if ( !bDown )
694 nMaxPos = nSetLeft-nSetWidth;
695 else
696 nMaxPos = nSetLeft+nSetWidth;
699 // order windows and adept values
700 for ( i = 0; i < nItems; i++ )
702 rItems[i]->mnOldSplitPos = rItems[i]->mnSplitPos;
703 rItems[i]->mnOldSplitSize = rItems[i]->mnSplitSize;
704 rItems[i]->mnOldWidth = rItems[i]->mnWidth;
705 rItems[i]->mnOldHeight = rItems[i]->mnHeight;
707 if ( rItems[i]->mnBits & SplitWindowItemFlags::Invisible )
708 bEmpty = true;
709 else
711 bEmpty = false;
712 if ( bDown )
714 if ( nPos+rItems[i]->mnPixSize > nMaxPos )
715 bEmpty = true;
717 else
719 nPos -= rItems[i]->mnPixSize;
720 if ( nPos < nMaxPos )
721 bEmpty = true;
725 if ( bEmpty )
727 rItems[i]->mnWidth = 0;
728 rItems[i]->mnHeight = 0;
729 rItems[i]->mnSplitSize = 0;
731 else
733 if ( bRows )
735 rItems[i]->mnLeft = nSetLeft;
736 rItems[i]->mnTop = nPos;
737 rItems[i]->mnWidth = nSetWidth;
738 rItems[i]->mnHeight = rItems[i]->mnPixSize;
740 else
742 rItems[i]->mnLeft = nPos;
743 rItems[i]->mnTop = nSetTop;
744 rItems[i]->mnWidth = rItems[i]->mnPixSize;
745 rItems[i]->mnHeight = nSetHeight;
748 if ( i > nItems-1 )
749 rItems[i]->mnSplitSize = 0;
750 else
752 rItems[i]->mnSplitSize = pSet->mnSplitSize;
753 if ( bDown )
755 rItems[i]->mnSplitPos = nPos+rItems[i]->mnPixSize;
756 if ( rItems[i]->mnSplitPos+rItems[i]->mnSplitSize > nMaxPos )
757 rItems[i]->mnSplitSize = nMaxPos-rItems[i]->mnSplitPos;
759 else
761 rItems[i]->mnSplitPos = nPos-pSet->mnSplitSize;
762 if ( rItems[i]->mnSplitPos < nMaxPos )
763 rItems[i]->mnSplitSize = rItems[i]->mnSplitPos+pSet->mnSplitSize-nMaxPos;
768 if ( !(rItems[i]->mnBits & SplitWindowItemFlags::Invisible) )
770 if ( !bDown )
771 nPos -= pSet->mnSplitSize;
772 else
773 nPos += rItems[i]->mnPixSize+pSet->mnSplitSize;
777 // calculate Sub-Set's
778 for ( i = 0; i < nItems; i++ )
780 if ( rItems[i]->mpSet && rItems[i]->mnWidth && rItems[i]->mnHeight )
782 ImplCalcSet( rItems[i]->mpSet,
783 rItems[i]->mnLeft, rItems[i]->mnTop,
784 rItems[i]->mnWidth, rItems[i]->mnHeight,
785 !(rItems[i]->mnBits & SplitWindowItemFlags::ColSet) );
789 // set fixed
790 for ( i = 0; i < nItems; i++ )
792 rItems[i]->mbFixed = false;
793 if ( rItems[i]->mnBits & SplitWindowItemFlags::Fixed )
794 rItems[i]->mbFixed = true;
795 else
797 // this item is also fixed if Child-Set is available,
798 // if a child is fixed
799 if ( rItems[i]->mpSet )
801 for ( j = 0; j < rItems[i]->mpSet->mpItems.size(); j++ )
803 if ( rItems[i]->mpSet->mpItems[j]->mbFixed )
805 rItems[i]->mbFixed = true;
806 break;
814 void SplitWindow::ImplCalcSet2( SplitWindow* pWindow, ImplSplitSet* pSet, bool bHide,
815 bool bRows, bool /*bDown*/ )
817 sal_uInt16 i;
818 size_t nItems = pSet->mpItems.size();
819 std::vector< ImplSplitItem* >& rItems = pSet->mpItems;
821 if ( pWindow->IsReallyVisible() && pWindow->IsUpdateMode() && pWindow->mbInvalidate )
823 for ( i = 0; i < nItems; i++ )
825 if ( rItems[i]->mnSplitSize )
827 // invalidate all, if applicable or only a small part
828 if ( (rItems[i]->mnOldSplitPos != rItems[i]->mnSplitPos) ||
829 (rItems[i]->mnOldSplitSize != rItems[i]->mnSplitSize) ||
830 (rItems[i]->mnOldWidth != rItems[i]->mnWidth) ||
831 (rItems[i]->mnOldHeight != rItems[i]->mnHeight) )
833 Rectangle aRect;
835 // invalidate old rectangle
836 if ( bRows )
838 aRect.Left() = rItems[i]->mnLeft;
839 aRect.Right() = rItems[i]->mnLeft+rItems[i]->mnOldWidth-1;
840 aRect.Top() = rItems[i]->mnOldSplitPos;
841 aRect.Bottom() = aRect.Top() + rItems[i]->mnOldSplitSize;
843 else
845 aRect.Top() = rItems[i]->mnTop;
846 aRect.Bottom() = rItems[i]->mnTop+rItems[i]->mnOldHeight-1;
847 aRect.Left() = rItems[i]->mnOldSplitPos;
848 aRect.Right() = aRect.Left() + rItems[i]->mnOldSplitSize;
850 pWindow->Invalidate( aRect );
851 // invalidate new rectangle
852 if ( bRows )
854 aRect.Left() = rItems[i]->mnLeft;
855 aRect.Right() = rItems[i]->mnLeft+rItems[i]->mnWidth-1;
856 aRect.Top() = rItems[i]->mnSplitPos;
857 aRect.Bottom() = aRect.Top() + rItems[i]->mnSplitSize;
859 else
861 aRect.Top() = rItems[i]->mnTop;
862 aRect.Bottom() = rItems[i]->mnTop+rItems[i]->mnHeight-1;
863 aRect.Left() = rItems[i]->mnSplitPos;
864 aRect.Right() = aRect.Left() + rItems[i]->mnSplitSize;
866 pWindow->Invalidate( aRect );
868 // invalidate complete set, as these areas
869 // are not cluttered by windows
870 if ( rItems[i]->mpSet && rItems[i]->mpSet->mpItems.empty() )
872 aRect.Left() = rItems[i]->mnLeft;
873 aRect.Top() = rItems[i]->mnTop;
874 aRect.Right() = rItems[i]->mnLeft+rItems[i]->mnWidth-1;
875 aRect.Bottom() = rItems[i]->mnTop+rItems[i]->mnHeight-1;
876 pWindow->Invalidate( aRect );
883 // position windows
884 for ( i = 0; i < nItems; i++ )
886 if ( rItems[i]->mpSet )
888 bool bTempHide = bHide;
889 if ( !rItems[i]->mnWidth || !rItems[i]->mnHeight )
890 bTempHide = true;
891 ImplCalcSet2( pWindow, rItems[i]->mpSet, bTempHide,
892 !(rItems[i]->mnBits & SplitWindowItemFlags::ColSet) );
894 else
896 if ( rItems[i]->mnWidth && rItems[i]->mnHeight && !bHide )
898 Point aPos( rItems[i]->mnLeft, rItems[i]->mnTop );
899 Size aSize( rItems[i]->mnWidth, rItems[i]->mnHeight );
900 rItems[i]->mpWindow->SetPosSizePixel( aPos, aSize );
902 else
903 rItems[i]->mpWindow->Hide();
907 // show windows and reset flag
908 for ( i = 0; i < nItems; i++ )
910 if ( rItems[i]->mpWindow && rItems[i]->mnWidth && rItems[i]->mnHeight && !bHide )
911 rItems[i]->mpWindow->Show();
915 static void ImplCalcLogSize( std::vector< ImplSplitItem* > rItems, size_t nItems )
917 // update original sizes
918 size_t i;
919 long nRelSize = 0;
920 long nPerSize = 0;
922 for ( i = 0; i < nItems; i++ )
924 if ( rItems[i]->mnBits & SplitWindowItemFlags::RelativeSize )
925 nRelSize += rItems[i]->mnPixSize;
926 else if ( rItems[i]->mnBits & SplitWindowItemFlags::PercentSize )
927 nPerSize += rItems[i]->mnPixSize;
929 nPerSize += nRelSize;
930 for ( i = 0; i < nItems; i++ )
932 if ( rItems[i]->mnBits & SplitWindowItemFlags::RelativeSize )
934 if ( nRelSize )
935 rItems[i]->mnSize = (rItems[i]->mnPixSize+(nRelSize/2))/nRelSize;
936 else
937 rItems[i]->mnSize = 1;
939 else if ( rItems[i]->mnBits & SplitWindowItemFlags::PercentSize )
941 if ( nPerSize )
942 rItems[i]->mnSize = (rItems[i]->mnPixSize*100)/nPerSize;
943 else
944 rItems[i]->mnSize = 1;
946 else
947 rItems[i]->mnSize = rItems[i]->mnPixSize;
951 void SplitWindow::ImplDrawBack(vcl::RenderContext& rRenderContext, const Rectangle& rRect,
952 const Wallpaper* pWall, const Bitmap* pBitmap)
954 if (pBitmap)
956 Point aPos = rRect.TopLeft();
957 Size aBmpSize = pBitmap->GetSizePixel();
958 rRenderContext.Push(PushFlags::CLIPREGION);
959 rRenderContext.IntersectClipRegion(rRect);
962 aPos.X() = rRect.Left();
965 rRenderContext.DrawBitmap(aPos, *pBitmap);
966 aPos.X() += aBmpSize.Width();
968 while (aPos.X() < rRect.Right());
969 aPos.Y() += aBmpSize.Height();
971 while (aPos.Y() < rRect.Bottom());
972 rRenderContext.Pop();
974 else
976 rRenderContext.DrawWallpaper(rRect, *pWall);
980 void SplitWindow::ImplDrawBack(vcl::RenderContext& rRenderContext, ImplSplitSet* pSet)
982 sal_uInt16 i;
983 size_t nItems = pSet->mpItems.size();
984 std::vector< ImplSplitItem* >& rItems = pSet->mpItems;
986 // also draw background for mainset
987 if (pSet->mnId == 0)
989 if (pSet->mpBitmap)
991 Rectangle aRect(mnLeftBorder, mnTopBorder,
992 mnDX - mnRightBorder - 1,
993 mnDY - mnBottomBorder - 1);
995 ImplDrawBack(rRenderContext, aRect, pSet->mpWallpaper, pSet->mpBitmap);
999 for (i = 0; i < nItems; i++)
1001 pSet = rItems[i]->mpSet;
1002 if (pSet)
1004 if (pSet->mpBitmap || pSet->mpWallpaper)
1006 Point aPoint(rItems[i]->mnLeft, rItems[i]->mnTop);
1007 Size aSize(rItems[i]->mnWidth, rItems[i]->mnHeight);
1008 Rectangle aRect(aPoint, aSize);
1009 ImplDrawBack(rRenderContext, aRect, pSet->mpWallpaper, pSet->mpBitmap);
1014 for (i = 0; i < nItems; i++)
1016 if (rItems[i]->mpSet)
1017 ImplDrawBack(rRenderContext, rItems[i]->mpSet);
1021 static void ImplDrawSplit(vcl::RenderContext& rRenderContext, ImplSplitSet* pSet, bool bRows, bool bFlat, bool bDown = true)
1023 if (pSet->mpItems.empty())
1024 return;
1026 sal_uInt16 i;
1027 size_t nItems = pSet->mpItems.size();
1028 long nPos;
1029 long nTop;
1030 long nBottom;
1031 std::vector< ImplSplitItem* >& rItems = pSet->mpItems;
1032 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
1034 for (i = 0; i < nItems-1; i++)
1036 if (rItems[i]->mnSplitSize)
1038 nPos = rItems[i]->mnSplitPos;
1040 long nItemSplitSize = rItems[i]->mnSplitSize;
1041 long nSplitSize = pSet->mnSplitSize;
1042 if (bRows)
1044 nTop = rItems[i]->mnLeft;
1045 nBottom = rItems[i]->mnLeft+rItems[i]->mnWidth-1;
1047 if (bFlat)
1048 nPos--;
1050 if (bDown || (nItemSplitSize >= nSplitSize))
1052 rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
1053 rRenderContext.DrawLine(Point(nTop, nPos + 1), Point(nBottom, nPos + 1));
1055 nPos += nSplitSize-2;
1056 if (bFlat)
1057 nPos+=2;
1058 if ((!bDown && (nItemSplitSize >= 2)) ||
1059 (bDown && (nItemSplitSize >= nSplitSize - 1)))
1061 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
1062 rRenderContext.DrawLine(Point(nTop, nPos), Point(nBottom, nPos));
1064 if (!bFlat)
1066 nPos++;
1067 if (!bDown || (nItemSplitSize >= nSplitSize))
1069 rRenderContext.SetLineColor(rStyleSettings.GetDarkShadowColor());
1070 rRenderContext.DrawLine(Point(nTop, nPos), Point(nBottom, nPos));
1074 else
1076 nTop = rItems[i]->mnTop;
1077 nBottom = rItems[i]->mnTop+pSet->mpItems[i]->mnHeight-1;
1079 if (bFlat)
1080 nPos--;
1081 if (bDown || (nItemSplitSize >= nSplitSize))
1083 rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
1084 rRenderContext.DrawLine(Point(nPos + 1, nTop), Point(nPos+1, nBottom));
1086 nPos += pSet->mnSplitSize - 2;
1087 if (bFlat)
1088 nPos += 2;
1089 if ((!bDown && (nItemSplitSize >= 2)) ||
1090 (bDown && (nItemSplitSize >= nSplitSize - 1)))
1092 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
1093 rRenderContext.DrawLine(Point(nPos, nTop), Point(nPos, nBottom));
1095 if( !bFlat )
1097 nPos++;
1098 if (!bDown || (nItemSplitSize >= nSplitSize))
1100 rRenderContext.SetLineColor(rStyleSettings.GetDarkShadowColor());
1101 rRenderContext.DrawLine(Point(nPos, nTop), Point(nPos, nBottom));
1108 for (i = 0; i < nItems; i++)
1110 if (rItems[i]->mpSet && rItems[i]->mnWidth && rItems[i]->mnHeight)
1112 ImplDrawSplit(rRenderContext, rItems[i]->mpSet, !(rItems[i]->mnBits & SplitWindowItemFlags::ColSet), bFlat);
1117 sal_uInt16 SplitWindow::ImplTestSplit( ImplSplitSet* pSet, const Point& rPos,
1118 long& rMouseOff, ImplSplitSet** ppFoundSet, sal_uInt16& rFoundPos,
1119 bool bRows, bool /*bDown*/ )
1121 if ( pSet->mpItems.empty() )
1122 return 0;
1124 sal_uInt16 i;
1125 sal_uInt16 nSplitTest;
1126 size_t nItems = pSet->mpItems.size();
1127 long nMPos1;
1128 long nMPos2;
1129 long nPos;
1130 long nTop;
1131 long nBottom;
1132 std::vector< ImplSplitItem* >& rItems = pSet->mpItems;
1134 if ( bRows )
1136 nMPos1 = rPos.X();
1137 nMPos2 = rPos.Y();
1139 else
1141 nMPos1 = rPos.Y();
1142 nMPos2 = rPos.X();
1145 for ( i = 0; i < nItems-1; i++ )
1147 if ( rItems[i]->mnSplitSize )
1149 if ( bRows )
1151 nTop = rItems[i]->mnLeft;
1152 nBottom = rItems[i]->mnLeft+rItems[i]->mnWidth-1;
1154 else
1156 nTop = rItems[i]->mnTop;
1157 nBottom = rItems[i]->mnTop+rItems[i]->mnHeight-1;
1159 nPos = rItems[i]->mnSplitPos;
1161 if ( (nMPos1 >= nTop) && (nMPos1 <= nBottom) &&
1162 (nMPos2 >= nPos) && (nMPos2 <= nPos+rItems[i]->mnSplitSize) )
1164 if ( !rItems[i]->mbFixed && !rItems[i+1]->mbFixed )
1166 rMouseOff = nMPos2-nPos;
1167 *ppFoundSet = pSet;
1168 rFoundPos = i;
1169 if ( bRows )
1170 return SPLIT_VERT;
1171 else
1172 return SPLIT_HORZ;
1174 else
1175 return SPLIT_NOSPLIT;
1180 for ( i = 0; i < nItems; i++ )
1182 if ( rItems[i]->mpSet )
1184 nSplitTest = ImplTestSplit( rItems[i]->mpSet, rPos,
1185 rMouseOff, ppFoundSet, rFoundPos,
1186 !(rItems[i]->mnBits & SplitWindowItemFlags::ColSet) );
1187 if ( nSplitTest )
1188 return nSplitTest;
1192 return 0;
1195 sal_uInt16 SplitWindow::ImplTestSplit( SplitWindow* pWindow, const Point& rPos,
1196 long& rMouseOff, ImplSplitSet** ppFoundSet, sal_uInt16& rFoundPos )
1198 // Resizable SplitWindow should be treated different
1199 if ( pWindow->mnWinStyle & WB_SIZEABLE )
1201 long nTPos;
1202 long nPos;
1203 long nBorder;
1205 if ( pWindow->mbHorz )
1207 if ( pWindow->mbBottomRight )
1209 nBorder = pWindow->mnBottomBorder;
1210 nPos = 0;
1212 else
1214 nBorder = pWindow->mnTopBorder;
1215 nPos = pWindow->mnDY-nBorder;
1217 nTPos = rPos.Y();
1219 else
1221 if ( pWindow->mbBottomRight )
1223 nBorder = pWindow->mnRightBorder;
1224 nPos = 0;
1226 else
1228 nBorder = pWindow->mnLeftBorder;
1229 nPos = pWindow->mnDX-nBorder;
1231 nTPos = rPos.X();
1233 long nSplitSize = pWindow->mpMainSet->mnSplitSize-2;
1234 if ( pWindow->mbAutoHide || pWindow->mbFadeOut )
1235 nSplitSize += SPLITWIN_SPLITSIZEEXLN;
1236 if ( !pWindow->mbBottomRight )
1237 nPos -= nSplitSize;
1238 if ( (nTPos >= nPos) && (nTPos <= nPos+nSplitSize+nBorder) )
1240 rMouseOff = nTPos-nPos;
1241 *ppFoundSet = pWindow->mpMainSet;
1242 if ( !pWindow->mpMainSet->mpItems.empty() )
1243 rFoundPos = pWindow->mpMainSet->mpItems.size() - 1;
1244 else
1245 rFoundPos = 0;
1246 if ( pWindow->mbHorz )
1247 return SPLIT_VERT | SPLIT_WINDOW;
1248 else
1249 return SPLIT_HORZ | SPLIT_WINDOW;
1253 return ImplTestSplit( pWindow->mpMainSet, rPos, rMouseOff, ppFoundSet, rFoundPos,
1254 pWindow->mbHorz, !pWindow->mbBottomRight );
1257 void SplitWindow::ImplDrawSplitTracking(const Point& rPos)
1259 Rectangle aRect;
1261 if (mnSplitTest & SPLIT_HORZ)
1263 aRect.Top() = maDragRect.Top();
1264 aRect.Bottom() = maDragRect.Bottom();
1265 aRect.Left() = rPos.X();
1266 aRect.Right() = aRect.Left() + mpSplitSet->mnSplitSize - 1;
1267 if (!(mnWinStyle & WB_NOSPLITDRAW))
1268 aRect.Right()--;
1269 if ((mnSplitTest & SPLIT_WINDOW) && (mbAutoHide || mbFadeOut))
1271 aRect.Left() += SPLITWIN_SPLITSIZEEXLN;
1272 aRect.Right() += SPLITWIN_SPLITSIZEEXLN;
1275 else
1277 aRect.Left() = maDragRect.Left();
1278 aRect.Right() = maDragRect.Right();
1279 aRect.Top() = rPos.Y();
1280 aRect.Bottom() = aRect.Top() + mpSplitSet->mnSplitSize - 1;
1281 if (!(mnWinStyle & WB_NOSPLITDRAW))
1282 aRect.Bottom()--;
1283 if ((mnSplitTest & SPLIT_WINDOW) && (mbAutoHide || mbFadeOut))
1285 aRect.Top() += SPLITWIN_SPLITSIZEEXLN;
1286 aRect.Bottom() += SPLITWIN_SPLITSIZEEXLN;
1289 ShowTracking(aRect, ShowTrackFlags::Split);
1292 void SplitWindow::ImplInit( vcl::Window* pParent, WinBits nStyle )
1294 ImplSplitSet* pNewSet = new ImplSplitSet();
1296 mpMainSet = pNewSet;
1297 mpBaseSet = pNewSet;
1298 mpSplitSet = nullptr;
1299 mpLastSizes = nullptr;
1300 mnDX = 0;
1301 mnDY = 0;
1302 mnLeftBorder = 0;
1303 mnTopBorder = 0;
1304 mnRightBorder = 0;
1305 mnBottomBorder = 0;
1306 mnMaxSize = 0;
1307 mnMouseOff = 0;
1308 meAlign = WindowAlign::Top;
1309 mnWinStyle = nStyle;
1310 mnSplitTest = 0;
1311 mnSplitPos = 0;
1312 mnMouseModifier = 0;
1313 mnMStartPos = 0;
1314 mnMSplitPos = 0;
1315 mbDragFull = false;
1316 mbHorz = true;
1317 mbBottomRight = false;
1318 mbCalc = false;
1319 mbRecalc = true;
1320 mbInvalidate = true;
1321 mbAutoHide = false;
1322 mbFadeIn = false;
1323 mbFadeOut = false;
1324 mbAutoHideIn = false;
1325 mbAutoHideDown = false;
1326 mbFadeInDown = false;
1327 mbFadeOutDown = false;
1328 mbAutoHidePressed = false;
1329 mbFadeInPressed = false;
1330 mbFadeOutPressed = false;
1331 mbFadeNoButtonMode = false;
1333 if ( nStyle & WB_NOSPLITDRAW )
1335 pNewSet->mnSplitSize -= 2;
1336 mbInvalidate = false;
1339 if ( nStyle & WB_BORDER )
1341 ImplCalcBorder( meAlign, false/*bNoAlign*/, mnLeftBorder, mnTopBorder,
1342 mnRightBorder, mnBottomBorder );
1344 else
1346 mnLeftBorder = 0;
1347 mnTopBorder = 0;
1348 mnRightBorder = 0;
1349 mnBottomBorder = 0;
1352 DockingWindow::ImplInit( pParent, (nStyle | WB_CLIPCHILDREN) & ~(WB_BORDER | WB_SIZEABLE) );
1354 ImplInitSettings();
1357 void SplitWindow::ImplInitSettings()
1359 // If a bitmap was set for MainSet, we should not delete the background.
1360 // If MainSet has a Wallpaper, this is the background,
1361 // otherwise it is the standard colour
1362 if ( mpMainSet->mpBitmap )
1363 SetBackground();
1364 else if ( mpMainSet->mpWallpaper )
1365 SetBackground( *mpMainSet->mpWallpaper );
1366 else
1368 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1370 Color aColor;
1371 if ( IsControlBackground() )
1372 aColor = GetControlBackground();
1373 else if ( Window::GetStyle() & WB_3DLOOK )
1374 aColor = rStyleSettings.GetFaceColor();
1375 else
1376 aColor = rStyleSettings.GetWindowColor();
1377 SetBackground( aColor );
1381 SplitWindow::SplitWindow( vcl::Window* pParent, WinBits nStyle ) :
1382 DockingWindow( WINDOW_SPLITWINDOW )
1384 ImplInit( pParent, nStyle );
1385 DockingWindow::SetIdleDebugName( "vcl::SplitWindow maLayoutIdle" );
1388 SplitWindow::~SplitWindow()
1390 disposeOnce();
1393 void SplitWindow::dispose()
1395 // delete Sets
1396 if (mpMainSet) {
1397 delete mpMainSet ;
1398 mpMainSet = nullptr; //NULL for base-class callbacks during destruction
1400 DockingWindow::dispose();
1403 void SplitWindow::ImplSetWindowSize( long nDelta )
1405 if ( !nDelta )
1406 return;
1408 Size aSize = GetSizePixel();
1409 switch ( meAlign )
1411 case WindowAlign::Top:
1412 aSize.Height() += nDelta;
1413 SetSizePixel( aSize );
1414 break;
1415 case WindowAlign::Bottom:
1417 maDragRect.Top() += nDelta;
1418 Point aPos = GetPosPixel();
1419 aPos.Y() -= nDelta;
1420 aSize.Height() += nDelta;
1421 SetPosSizePixel( aPos, aSize );
1422 break;
1424 case WindowAlign::Left:
1425 aSize.Width() += nDelta;
1426 SetSizePixel( aSize );
1427 break;
1428 case WindowAlign::Right:
1429 default:
1431 maDragRect.Left() += nDelta;
1432 Point aPos = GetPosPixel();
1433 aPos.X() -= nDelta;
1434 aSize.Width() += nDelta;
1435 SetPosSizePixel( aPos, aSize );
1436 break;
1440 SplitResize();
1443 Size SplitWindow::CalcLayoutSizePixel( const Size& aNewSize )
1445 Size aSize( aNewSize );
1446 long nSplitSize = mpMainSet->mnSplitSize-2;
1448 if ( mbAutoHide || mbFadeOut )
1449 nSplitSize += SPLITWIN_SPLITSIZEEXLN;
1451 // if the window is sizeable and if it does not contain a relative window,
1452 // the size is determined according to MainSet
1453 if ( mnWinStyle & WB_SIZEABLE )
1455 long nCalcSize = 0;
1456 sal_uInt16 i;
1458 for ( i = 0; i < mpMainSet->mpItems.size(); i++ )
1460 if ( mpMainSet->mpItems[i]->mnBits & (SplitWindowItemFlags::RelativeSize | SplitWindowItemFlags::PercentSize) )
1461 break;
1462 else
1463 nCalcSize += mpMainSet->mpItems[i]->mnSize;
1466 if ( i == mpMainSet->mpItems.size() )
1468 long nDelta = 0;
1469 Point aPos = GetPosPixel();
1470 long nCurSize;
1472 if ( mbHorz )
1473 nCurSize = aNewSize.Height()-mnTopBorder-mnBottomBorder;
1474 else
1475 nCurSize = aNewSize.Width()-mnLeftBorder-mnRightBorder;
1476 nCurSize -= nSplitSize;
1477 nCurSize -= (mpMainSet->mpItems.size()-1)*mpMainSet->mnSplitSize;
1479 nDelta = nCalcSize-nCurSize;
1480 if ( !nDelta )
1481 return aSize;
1483 switch ( meAlign )
1485 case WindowAlign::Top:
1486 aSize.Height() += nDelta;
1487 break;
1488 case WindowAlign::Bottom:
1489 aPos.Y() -= nDelta;
1490 aSize.Height() += nDelta;
1491 break;
1492 case WindowAlign::Left:
1493 aSize.Width() += nDelta;
1494 break;
1495 case WindowAlign::Right:
1496 default:
1497 aPos.X() -= nDelta;
1498 aSize.Width() += nDelta;
1499 break;
1504 return aSize;
1507 void SplitWindow::ImplCalcLayout()
1509 if ( !mbCalc || !mbRecalc || mpMainSet->mpItems.empty() )
1510 return;
1512 long nSplitSize = mpMainSet->mnSplitSize-2;
1513 if ( mbAutoHide || mbFadeOut )
1514 nSplitSize += SPLITWIN_SPLITSIZEEXLN;
1516 // if the window is sizeable and if it does not contain a relative window,
1517 // the size is determined according to MainSet
1518 if ( mnWinStyle & WB_SIZEABLE )
1520 long nCalcSize = 0;
1521 sal_uInt16 i;
1523 for ( i = 0; i < mpMainSet->mpItems.size(); i++ )
1525 if ( mpMainSet->mpItems[i]->mnBits & (SplitWindowItemFlags::RelativeSize | SplitWindowItemFlags::PercentSize) )
1526 break;
1527 else
1528 nCalcSize += mpMainSet->mpItems[i]->mnSize;
1531 if ( i == mpMainSet->mpItems.size() )
1533 long nCurSize;
1534 if ( mbHorz )
1535 nCurSize = mnDY-mnTopBorder-mnBottomBorder;
1536 else
1537 nCurSize = mnDX-mnLeftBorder-mnRightBorder;
1538 nCurSize -= nSplitSize;
1539 nCurSize -= (mpMainSet->mpItems.size()-1)*mpMainSet->mnSplitSize;
1541 mbRecalc = false;
1542 ImplSetWindowSize( nCalcSize-nCurSize );
1543 mbRecalc = true;
1547 if ( (mnDX <= 0) || (mnDY <= 0) )
1548 return;
1550 // pre-calculate sizes/position
1551 long nL;
1552 long nT;
1553 long nW;
1554 long nH;
1556 if ( mbHorz )
1558 if ( mbBottomRight )
1559 nT = mnDY-mnBottomBorder;
1560 else
1561 nT = mnTopBorder;
1562 nL = mnLeftBorder;
1564 else
1566 if ( mbBottomRight )
1567 nL = mnDX-mnRightBorder;
1568 else
1569 nL = mnLeftBorder;
1570 nT = mnTopBorder;
1572 nW = mnDX-mnLeftBorder-mnRightBorder;
1573 nH = mnDY-mnTopBorder-mnBottomBorder;
1574 if ( mnWinStyle & WB_SIZEABLE )
1576 if ( mbHorz )
1577 nH -= nSplitSize;
1578 else
1579 nW -= nSplitSize;
1582 // calculate sets recursive
1583 ImplCalcSet( mpMainSet, nL, nT, nW, nH, mbHorz, !mbBottomRight );
1584 ImplCalcSet2( this, mpMainSet, false, mbHorz, !mbBottomRight );
1585 mbCalc = false;
1588 void SplitWindow::ImplUpdate()
1590 mbCalc = true;
1592 if ( IsReallyShown() && IsUpdateMode() && mbRecalc )
1594 if ( !mpMainSet->mpItems.empty() )
1595 ImplCalcLayout();
1596 else
1597 Invalidate();
1601 void SplitWindow::ImplSplitMousePos( Point& rMousePos )
1603 if ( mnSplitTest & SPLIT_HORZ )
1605 rMousePos.X() -= mnMouseOff;
1606 if ( rMousePos.X() < maDragRect.Left() )
1607 rMousePos.X() = maDragRect.Left();
1608 else if ( rMousePos.X()+mpSplitSet->mnSplitSize+1 > maDragRect.Right() )
1609 rMousePos.X() = maDragRect.Right()-mpSplitSet->mnSplitSize+1;
1610 // store in screen coordinates due to FullDrag
1611 mnMSplitPos = OutputToScreenPixel( rMousePos ).X();
1613 else
1615 rMousePos.Y() -= mnMouseOff;
1616 if ( rMousePos.Y() < maDragRect.Top() )
1617 rMousePos.Y() = maDragRect.Top();
1618 else if ( rMousePos.Y()+mpSplitSet->mnSplitSize+1 > maDragRect.Bottom() )
1619 rMousePos.Y() = maDragRect.Bottom()-mpSplitSet->mnSplitSize+1;
1620 mnMSplitPos = OutputToScreenPixel( rMousePos ).Y();
1624 void SplitWindow::ImplGetButtonRect( Rectangle& rRect, long nEx, bool bTest ) const
1626 long nSplitSize = mpMainSet->mnSplitSize-1;
1627 if ( mbAutoHide || mbFadeOut || mbFadeIn )
1628 nSplitSize += SPLITWIN_SPLITSIZEEX;
1630 long nButtonSize = 0;
1631 if ( mbFadeIn )
1632 nButtonSize += SPLITWIN_SPLITSIZEFADE+1;
1633 if ( mbFadeOut )
1634 nButtonSize += SPLITWIN_SPLITSIZEFADE+1;
1635 if ( mbAutoHide )
1636 nButtonSize += SPLITWIN_SPLITSIZEAUTOHIDE+1;
1637 long nCenterEx = 0;
1638 if ( mbHorz )
1639 nCenterEx += ((mnDX-mnLeftBorder-mnRightBorder)-nButtonSize)/2;
1640 else
1641 nCenterEx += ((mnDY-mnTopBorder-mnBottomBorder)-nButtonSize)/2;
1642 if ( nCenterEx > 0 )
1643 nEx += nCenterEx;
1645 switch ( meAlign )
1647 case WindowAlign::Top:
1648 rRect.Left() = mnLeftBorder+nEx;
1649 rRect.Top() = mnDY-mnBottomBorder-nSplitSize;
1650 rRect.Right() = rRect.Left()+SPLITWIN_SPLITSIZEAUTOHIDE;
1651 rRect.Bottom() = mnDY-mnBottomBorder-1;
1652 if ( bTest )
1654 rRect.Top() -= mnTopBorder;
1655 rRect.Bottom() += mnBottomBorder;
1657 break;
1658 case WindowAlign::Bottom:
1659 rRect.Left() = mnLeftBorder+nEx;
1660 rRect.Top() = mnTopBorder;
1661 rRect.Right() = rRect.Left()+SPLITWIN_SPLITSIZEAUTOHIDE;
1662 rRect.Bottom() = mnTopBorder+nSplitSize-1;
1663 if ( bTest )
1665 rRect.Top() -= mnTopBorder;
1666 rRect.Bottom() += mnBottomBorder;
1668 break;
1669 case WindowAlign::Left:
1670 rRect.Left() = mnDX-mnRightBorder-nSplitSize;
1671 rRect.Top() = mnTopBorder+nEx;
1672 rRect.Right() = mnDX-mnRightBorder-1;
1673 rRect.Bottom() = rRect.Top()+SPLITWIN_SPLITSIZEAUTOHIDE;
1674 if ( bTest )
1676 rRect.Left() -= mnLeftBorder;
1677 rRect.Right() += mnRightBorder;
1679 break;
1680 case WindowAlign::Right:
1681 rRect.Left() = mnLeftBorder;
1682 rRect.Top() = mnTopBorder+nEx;
1683 rRect.Right() = mnLeftBorder+nSplitSize-1;
1684 rRect.Bottom() = rRect.Top()+SPLITWIN_SPLITSIZEAUTOHIDE;
1685 if ( bTest )
1687 rRect.Left() -= mnLeftBorder;
1688 rRect.Right() += mnRightBorder;
1690 break;
1694 void SplitWindow::ImplGetAutoHideRect( Rectangle& rRect, bool bTest ) const
1696 Rectangle aRect;
1698 if ( mbAutoHide )
1700 long nEx = 0;
1701 if ( mbFadeIn || mbFadeOut )
1702 nEx = SPLITWIN_SPLITSIZEFADE+1;
1703 ImplGetButtonRect( aRect, nEx, bTest && mbFadeIn );
1706 rRect = aRect;
1709 void SplitWindow::ImplGetFadeInRect( Rectangle& rRect, bool bTest ) const
1711 Rectangle aRect;
1713 if ( mbFadeIn )
1714 ImplGetButtonRect( aRect, 0, bTest );
1716 rRect = aRect;
1719 void SplitWindow::ImplGetFadeOutRect( Rectangle& rRect, bool ) const
1721 Rectangle aRect;
1723 if ( mbFadeOut )
1724 ImplGetButtonRect( aRect, 0, false );
1726 rRect = aRect;
1729 void SplitWindow::ImplDrawButtonRect(vcl::RenderContext& rRenderContext, const Rectangle& rRect, long nSize)
1731 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
1733 if ( mbHorz )
1735 long nLeft = rRect.Left();
1736 long nRight = rRect.Right();
1737 long nCenter = rRect.Center().Y();
1738 long nEx1 = nLeft+((rRect.GetWidth()-nSize)/2)-2;
1739 long nEx2 = nEx1+nSize+3;
1740 rRenderContext.SetLineColor( rStyleSettings.GetLightColor() );
1741 rRenderContext.DrawLine( Point( rRect.Left(), rRect.Top() ), Point( rRect.Left(), rRect.Bottom() ) );
1742 rRenderContext.DrawLine( Point( rRect.Left(), rRect.Top() ), Point( rRect.Right(), rRect.Top() ) );
1743 rRenderContext.SetLineColor( rStyleSettings.GetShadowColor() );
1744 rRenderContext.DrawLine( Point( rRect.Right(), rRect.Top() ), Point( rRect.Right(), rRect.Bottom() ) );
1745 rRenderContext.DrawLine( Point( rRect.Left(), rRect.Bottom() ), Point( rRect.Right(), rRect.Bottom() ) );
1746 long i = nLeft+2;
1747 while ( i < nRight-3 )
1749 if ( (i < nEx1) || (i > nEx2 ) )
1751 rRenderContext.DrawPixel( Point( i, nCenter-2 ), rStyleSettings.GetLightColor() );
1752 rRenderContext.DrawPixel( Point( i+1, nCenter-2+1 ), rStyleSettings.GetShadowColor() );
1754 i++;
1755 if ( (i < nEx1) || ((i > nEx2 ) && (i < nRight-3)) )
1757 rRenderContext.DrawPixel( Point( i, nCenter+2 ), rStyleSettings.GetLightColor() );
1758 rRenderContext.DrawPixel( Point( i+1, nCenter+2+1 ), rStyleSettings.GetShadowColor() );
1760 i += 2;
1763 else
1765 long nTop = rRect.Top();
1766 long nBottom = rRect.Bottom();
1767 long nCenter = rRect.Center().X();
1768 long nEx1 = nTop+((rRect.GetHeight()-nSize)/2)-2;
1769 long nEx2 = nEx1+nSize+3;
1770 rRenderContext.SetLineColor( rStyleSettings.GetLightColor() );
1771 rRenderContext.DrawLine( Point( rRect.Left(), rRect.Top() ), Point( rRect.Right(), rRect.Top() ) );
1772 rRenderContext.DrawLine( Point( rRect.Left(), rRect.Top() ), Point( rRect.Left(), rRect.Bottom() ) );
1773 rRenderContext.SetLineColor( rStyleSettings.GetShadowColor() );
1774 rRenderContext.DrawLine( Point( rRect.Right(), rRect.Top() ), Point( rRect.Right(), rRect.Bottom() ) );
1775 rRenderContext.DrawLine( Point( rRect.Left(), rRect.Bottom() ), Point( rRect.Right(), rRect.Bottom() ) );
1776 long i = nTop+2;
1777 while ( i < nBottom-3 )
1779 if ( (i < nEx1) || (i > nEx2 ) )
1781 rRenderContext.DrawPixel( Point( nCenter-2, i ), rStyleSettings.GetLightColor() );
1782 rRenderContext.DrawPixel( Point( nCenter-2+1, i+1 ), rStyleSettings.GetShadowColor() );
1784 i++;
1785 if ( (i < nEx1) || ((i > nEx2 ) && (i < nBottom-3)) )
1787 rRenderContext.DrawPixel( Point( nCenter+2, i ), rStyleSettings.GetLightColor() );
1788 rRenderContext.DrawPixel( Point( nCenter+2+1, i+1 ), rStyleSettings.GetShadowColor() );
1790 i += 2;
1795 void SplitWindow::ImplDrawAutoHide(vcl::RenderContext& rRenderContext)
1797 if (mbAutoHide)
1799 Rectangle aTempRect;
1800 ImplGetAutoHideRect( aTempRect );
1802 // load ImageListe, if not available
1803 ImplSVData* pSVData = ImplGetSVData();
1804 ImageList* pImageList;
1805 if (mbHorz)
1807 if (!pSVData->maCtrlData.mpSplitHPinImgList)
1809 ResMgr* pResMgr = ImplGetResMgr();
1810 if (pResMgr)
1812 Color aNonAlphaMask( 0x00, 0x00, 0xFF );
1813 pSVData->maCtrlData.mpSplitHPinImgList = new ImageList;
1814 pSVData->maCtrlData.mpSplitHPinImgList->InsertFromHorizontalBitmap
1815 ( ResId( SV_RESID_BITMAP_SPLITHPIN, *pResMgr ), 4, &aNonAlphaMask );
1818 pImageList = pSVData->maCtrlData.mpSplitHPinImgList;
1820 else
1822 if (!pSVData->maCtrlData.mpSplitVPinImgList)
1824 ResMgr* pResMgr = ImplGetResMgr();
1825 pSVData->maCtrlData.mpSplitVPinImgList = new ImageList;
1826 if (pResMgr)
1828 Color aNonAlphaMask( 0x00, 0x00, 0xFF );
1829 pSVData->maCtrlData.mpSplitVPinImgList->InsertFromHorizontalBitmap(
1830 ResId( SV_RESID_BITMAP_SPLITVPIN, *pResMgr ), 4, &aNonAlphaMask);
1833 pImageList = pSVData->maCtrlData.mpSplitVPinImgList;
1836 if (!pImageList)
1837 return;
1839 // retrieve and return image
1840 sal_uInt16 nId;
1841 if (mbAutoHidePressed)
1843 if (mbAutoHideIn)
1844 nId = 3;
1845 else
1846 nId = 4;
1848 else
1850 if (mbAutoHideIn)
1851 nId = 1;
1852 else
1853 nId = 2;
1856 Image aImage = pImageList->GetImage( nId );
1857 Size aImageSize = aImage.GetSizePixel();
1858 Point aPos(aTempRect.Left() + ((aTempRect.GetWidth() - aImageSize.Width()) / 2),
1859 aTempRect.Top() + ((aTempRect.GetHeight() - aImageSize.Height()) / 2));
1860 long nSize;
1861 if (mbHorz)
1862 nSize = aImageSize.Width();
1863 else
1864 nSize = aImageSize.Height();
1865 ImplDrawButtonRect(rRenderContext, aTempRect, nSize);
1866 rRenderContext.DrawImage(aPos, aImage);
1870 void SplitWindow::ImplDrawGrip(vcl::RenderContext& rRenderContext, const Rectangle& rRect, bool bHorizontal, bool bLeft)
1872 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
1874 Color aColor;
1876 if (rRect.IsInside(GetPointerPosPixel()))
1878 vcl::RenderTools::DrawSelectionBackground(rRenderContext, *this, rRect, 2, false, false, false);
1880 aColor = rStyleSettings.GetDarkShadowColor();
1882 else
1884 rRenderContext.SetLineColor(rStyleSettings.GetDarkShadowColor());
1885 rRenderContext.SetFillColor(rStyleSettings.GetDarkShadowColor());
1887 rRenderContext.DrawRect(rRect);
1889 aColor = rStyleSettings.GetFaceColor();
1892 AntialiasingFlags nAA = rRenderContext.GetAntialiasing();
1893 rRenderContext.SetAntialiasing(nAA | AntialiasingFlags::PixelSnapHairline | AntialiasingFlags::EnableB2dDraw);
1895 long nWidth = rRect.getWidth();
1896 long nWidthHalf = nWidth / 2;
1897 long nHeight = rRect.getHeight();
1898 long nHeightHalf = nHeight / 2;
1900 long nLeft = rRect.Left();
1901 long nRight = rRect.Right();
1902 long nTop = rRect.Top();
1903 long nBottom = rRect.Bottom();
1904 long nMargin = 1;
1906 rRenderContext.SetLineColor(aColor);
1907 rRenderContext.SetFillColor(aColor);
1909 tools::Polygon aPoly(3);
1911 if (bHorizontal)
1913 long nCenter = nLeft + nWidthHalf;
1915 if (bLeft)
1917 aPoly.SetPoint(Point(nCenter, nTop + nMargin), 0);
1918 aPoly.SetPoint(Point(nCenter - nHeightHalf, nBottom - nMargin), 1);
1919 aPoly.SetPoint(Point(nCenter - nHeightHalf, nBottom - nMargin), 2);
1921 else
1923 aPoly.SetPoint(Point(nCenter, nBottom - nMargin), 0);
1924 aPoly.SetPoint(Point(nCenter - nHeightHalf, nTop + nMargin), 1);
1925 aPoly.SetPoint(Point(nCenter + nHeightHalf, nTop + nMargin), 2);
1927 rRenderContext.DrawPolygon(aPoly);
1929 else
1931 long nCenter = nTop + nHeightHalf;
1933 if (bLeft)
1935 aPoly.SetPoint(Point(nLeft + nMargin, nCenter), 0);
1936 aPoly.SetPoint(Point(nRight - nMargin, nCenter - nWidthHalf), 1);
1937 aPoly.SetPoint(Point(nRight - nMargin, nCenter + nWidthHalf), 2);
1939 else
1941 aPoly.SetPoint(Point(nRight - nMargin, nCenter), 0);
1942 aPoly.SetPoint(Point(nLeft + nMargin, nCenter - nWidthHalf), 1);
1943 aPoly.SetPoint(Point(nLeft + nMargin, nCenter + nWidthHalf), 2);
1945 rRenderContext.DrawPolygon(aPoly);
1948 rRenderContext.SetAntialiasing(nAA);
1951 void SplitWindow::ImplDrawFadeIn(vcl::RenderContext& rRenderContext)
1953 if (mbFadeIn)
1955 Rectangle aTempRect;
1956 ImplGetFadeInRect(aTempRect);
1958 bool bLeft = true;
1959 switch (meAlign)
1961 case WindowAlign::Top:
1962 case WindowAlign::Left:
1963 bLeft = false;
1964 break;
1965 case WindowAlign::Bottom:
1966 case WindowAlign::Right:
1967 default:
1968 bLeft = true;
1969 break;
1972 ImplDrawGrip(rRenderContext, aTempRect, (meAlign == WindowAlign::Top) || (meAlign == WindowAlign::Bottom), bLeft);
1976 void SplitWindow::ImplDrawFadeOut(vcl::RenderContext& rRenderContext)
1978 if (mbFadeOut)
1980 Rectangle aTempRect;
1981 ImplGetFadeOutRect(aTempRect);
1983 bool bLeft = true;
1984 switch (meAlign)
1986 case WindowAlign::Bottom:
1987 case WindowAlign::Right:
1988 bLeft = false;
1989 break;
1990 case WindowAlign::Top:
1991 case WindowAlign::Left:
1992 default:
1993 bLeft = true;
1994 break;
1997 ImplDrawGrip(rRenderContext, aTempRect, (meAlign == WindowAlign::Top) || (meAlign == WindowAlign::Bottom), bLeft);
2001 void SplitWindow::ImplStartSplit( const MouseEvent& rMEvt )
2003 Point aMousePosPixel = rMEvt.GetPosPixel();
2004 mnSplitTest = ImplTestSplit( this, aMousePosPixel, mnMouseOff, &mpSplitSet, mnSplitPos );
2006 if ( mnSplitTest && !(mnSplitTest & SPLIT_NOSPLIT) )
2008 ImplSplitItem* pSplitItem;
2009 long nCurMaxSize;
2010 sal_uInt16 nTemp;
2011 bool bPropSmaller;
2013 mnMouseModifier = rMEvt.GetModifier();
2014 if ( !(mnMouseModifier & KEY_SHIFT) || (static_cast<sal_uInt16>(mnSplitPos+1) >= mpSplitSet->mpItems.size()) )
2015 bPropSmaller = false;
2016 else
2017 bPropSmaller = true;
2019 // here we can set the maximum size
2020 StartSplit();
2022 if ( mnMaxSize )
2023 nCurMaxSize = mnMaxSize;
2024 else
2026 Size aSize = GetParent()->GetOutputSizePixel();
2027 if ( mbHorz )
2028 nCurMaxSize = aSize.Height();
2029 else
2030 nCurMaxSize = aSize.Width();
2033 if ( !mpSplitSet->mpItems.empty() )
2035 bool bDown = true;
2036 if ( (mpSplitSet == mpMainSet) && mbBottomRight )
2037 bDown = false;
2039 pSplitItem = mpSplitSet->mpItems[mnSplitPos];
2040 maDragRect.Left() = pSplitItem->mnLeft;
2041 maDragRect.Top() = pSplitItem->mnTop;
2042 maDragRect.Right() = pSplitItem->mnLeft+pSplitItem->mnWidth-1;
2043 maDragRect.Bottom() = pSplitItem->mnTop+pSplitItem->mnHeight-1;
2045 if ( mnSplitTest & SPLIT_HORZ )
2047 if ( bDown )
2048 maDragRect.Right() += mpSplitSet->mnSplitSize;
2049 else
2050 maDragRect.Left() -= mpSplitSet->mnSplitSize;
2052 else
2054 if ( bDown )
2055 maDragRect.Bottom() += mpSplitSet->mnSplitSize;
2056 else
2057 maDragRect.Top() -= mpSplitSet->mnSplitSize;
2060 if ( mnSplitPos )
2062 nTemp = mnSplitPos;
2063 while ( nTemp )
2065 pSplitItem = mpSplitSet->mpItems[nTemp-1];
2066 if ( pSplitItem->mbFixed )
2067 break;
2068 else
2070 if ( mnSplitTest & SPLIT_HORZ )
2072 if ( bDown )
2073 maDragRect.Left() -= pSplitItem->mnPixSize;
2074 else
2075 maDragRect.Right() += pSplitItem->mnPixSize;
2077 else
2079 if ( bDown )
2080 maDragRect.Top() -= pSplitItem->mnPixSize;
2081 else
2082 maDragRect.Bottom() += pSplitItem->mnPixSize;
2085 nTemp--;
2089 if ( (mpSplitSet == mpMainSet) && (mnWinStyle & WB_SIZEABLE) && !bPropSmaller )
2091 if ( bDown )
2093 if ( mbHorz )
2094 maDragRect.Bottom() += nCurMaxSize-mnDY-mnTopBorder;
2095 else
2096 maDragRect.Right() += nCurMaxSize-mnDX-mnLeftBorder;
2098 else
2100 if ( mbHorz )
2101 maDragRect.Top() -= nCurMaxSize-mnDY-mnBottomBorder;
2102 else
2103 maDragRect.Left() -= nCurMaxSize-mnDX-mnRightBorder;
2106 else
2108 nTemp = mnSplitPos+1;
2109 while ( nTemp < mpSplitSet->mpItems.size() )
2111 pSplitItem = mpSplitSet->mpItems[nTemp];
2112 if ( pSplitItem->mbFixed )
2113 break;
2114 else
2116 if ( mnSplitTest & SPLIT_HORZ )
2118 if ( bDown )
2119 maDragRect.Right() += pSplitItem->mnPixSize;
2120 else
2121 maDragRect.Left() -= pSplitItem->mnPixSize;
2123 else
2125 if ( bDown )
2126 maDragRect.Bottom() += pSplitItem->mnPixSize;
2127 else
2128 maDragRect.Top() -= pSplitItem->mnPixSize;
2131 nTemp++;
2135 else
2137 maDragRect.Left() = mnLeftBorder;
2138 maDragRect.Top() = mnTopBorder;
2139 maDragRect.Right() = mnDX-mnRightBorder-1;
2140 maDragRect.Bottom() = mnDY-mnBottomBorder-1;
2141 if ( mbHorz )
2143 if ( mbBottomRight )
2144 maDragRect.Top() -= nCurMaxSize-mnDY-mnBottomBorder;
2145 else
2146 maDragRect.Bottom() += nCurMaxSize-mnDY-mnTopBorder;
2148 else
2150 if ( mbBottomRight )
2151 maDragRect.Left() -= nCurMaxSize-mnDX-mnRightBorder;
2152 else
2153 maDragRect.Right() += nCurMaxSize-mnDX-mnLeftBorder;
2157 StartTracking();
2159 mbDragFull = bool(GetSettings().GetStyleSettings().GetDragFullOptions() & DragFullOptions::Split);
2161 ImplSplitMousePos( aMousePosPixel );
2163 if (!mbDragFull)
2165 ImplDrawSplitTracking(aMousePosPixel);
2167 else
2169 std::vector< ImplSplitItem* >& rItems = mpSplitSet->mpItems;
2170 sal_uInt16 nItems = mpSplitSet->mpItems.size();
2171 mpLastSizes = new long[nItems*2];
2172 for ( sal_uInt16 i = 0; i < nItems; i++ )
2174 mpLastSizes[i*2] = rItems[i]->mnSize;
2175 mpLastSizes[i*2+1] = rItems[i]->mnPixSize;
2178 mnMStartPos = mnMSplitPos;
2180 PointerStyle eStyle = PointerStyle::Arrow;
2181 if ( mnSplitTest & SPLIT_HORZ )
2182 eStyle = PointerStyle::HSplit;
2183 else if ( mnSplitTest & SPLIT_VERT )
2184 eStyle = PointerStyle::VSplit;
2186 Pointer aPtr( eStyle );
2187 SetPointer( aPtr );
2191 void SplitWindow::StartSplit()
2195 void SplitWindow::Split()
2197 maSplitHdl.Call( this );
2200 void SplitWindow::SplitResize()
2204 void SplitWindow::AutoHide()
2208 void SplitWindow::FadeIn()
2212 void SplitWindow::FadeOut()
2216 void SplitWindow::MouseButtonDown( const MouseEvent& rMEvt )
2218 if ( !rMEvt.IsLeft() || rMEvt.IsMod2() )
2220 DockingWindow::MouseButtonDown( rMEvt );
2221 return;
2224 Point aMousePosPixel = rMEvt.GetPosPixel();
2225 Rectangle aTestRect;
2227 mbFadeNoButtonMode = false;
2228 ImplGetAutoHideRect( aTestRect, true );
2229 if ( aTestRect.IsInside( aMousePosPixel ) )
2231 mbAutoHideDown = true;
2232 mbAutoHidePressed = true;
2233 Invalidate();
2235 else
2237 ImplGetFadeOutRect( aTestRect, true );
2238 if ( aTestRect.IsInside( aMousePosPixel ) )
2240 mbFadeOutDown = true;
2241 mbFadeOutPressed = true;
2242 Invalidate();
2244 else
2246 ImplGetFadeInRect( aTestRect, true );
2247 if ( aTestRect.IsInside( aMousePosPixel ) )
2249 mbFadeInDown = true;
2250 mbFadeInPressed = true;
2251 Invalidate();
2253 else if ( !aTestRect.IsEmpty() && !(mnWinStyle & WB_SIZEABLE) )
2255 mbFadeNoButtonMode = true;
2256 FadeIn();
2257 return;
2262 if ( mbAutoHideDown || mbFadeInDown || mbFadeOutDown )
2263 StartTracking();
2264 else
2265 ImplStartSplit( rMEvt );
2268 void SplitWindow::MouseMove( const MouseEvent& rMEvt )
2270 if ( !IsTracking() )
2272 Point aPos = rMEvt.GetPosPixel();
2273 long nTemp;
2274 ImplSplitSet* pTempSplitSet;
2275 sal_uInt16 nTempSplitPos;
2276 sal_uInt16 nSplitTest = ImplTestSplit( this, aPos, nTemp, &pTempSplitSet, nTempSplitPos );
2277 PointerStyle eStyle = PointerStyle::Arrow;
2278 Rectangle aAutoHideRect;
2279 Rectangle aFadeInRect;
2280 Rectangle aFadeOutRect;
2282 ImplGetAutoHideRect( aAutoHideRect );
2283 ImplGetFadeInRect( aFadeInRect );
2284 ImplGetFadeOutRect( aFadeOutRect );
2285 if ( !aAutoHideRect.IsInside( aPos ) &&
2286 !aFadeInRect.IsInside( aPos ) &&
2287 !aFadeOutRect.IsInside( aPos ) )
2289 if ( nSplitTest && !(nSplitTest & SPLIT_NOSPLIT) )
2291 if ( nSplitTest & SPLIT_HORZ )
2292 eStyle = PointerStyle::HSplit;
2293 else if ( nSplitTest & SPLIT_VERT )
2294 eStyle = PointerStyle::VSplit;
2298 Pointer aPtr( eStyle );
2299 SetPointer( aPtr );
2303 void SplitWindow::Tracking( const TrackingEvent& rTEvt )
2305 Point aMousePosPixel = rTEvt.GetMouseEvent().GetPosPixel();
2307 if ( mbAutoHideDown )
2309 if ( rTEvt.IsTrackingEnded() )
2311 mbAutoHideDown = false;
2312 if ( mbAutoHidePressed )
2314 mbAutoHidePressed = false;
2316 if ( !rTEvt.IsTrackingCanceled() )
2318 mbAutoHideIn = !mbAutoHideIn;
2319 Invalidate();
2320 AutoHide();
2322 else
2323 Invalidate();
2326 else
2328 Rectangle aTestRect;
2329 ImplGetAutoHideRect( aTestRect, true );
2330 bool bNewPressed = aTestRect.IsInside( aMousePosPixel );
2331 if ( bNewPressed != mbAutoHidePressed )
2333 mbAutoHidePressed = bNewPressed;
2334 Invalidate();
2338 else if ( mbFadeInDown )
2340 if ( rTEvt.IsTrackingEnded() )
2342 mbFadeInDown = false;
2343 if ( mbFadeInPressed )
2345 mbFadeInPressed = false;
2346 Invalidate();
2348 if ( !rTEvt.IsTrackingCanceled() )
2349 FadeIn();
2352 else
2354 Rectangle aTestRect;
2355 ImplGetFadeInRect( aTestRect, true );
2356 bool bNewPressed = aTestRect.IsInside( aMousePosPixel );
2357 if ( bNewPressed != mbFadeInPressed )
2359 mbFadeInPressed = bNewPressed;
2360 Invalidate();
2364 else if ( mbFadeOutDown )
2366 if ( rTEvt.IsTrackingEnded() )
2368 mbFadeOutDown = false;
2369 if ( mbFadeOutPressed )
2371 mbFadeOutPressed = false;
2372 Invalidate();
2374 if ( !rTEvt.IsTrackingCanceled() )
2375 FadeOut();
2378 else
2380 Rectangle aTestRect;
2381 ImplGetFadeOutRect( aTestRect, true );
2382 bool bNewPressed = aTestRect.IsInside( aMousePosPixel );
2383 if ( !bNewPressed )
2385 mbFadeOutPressed = bNewPressed;
2386 Invalidate();
2388 // We need a mouseevent with a position inside the button for the
2389 // ImplStartSplit function!
2390 MouseEvent aOrgMEvt = rTEvt.GetMouseEvent();
2391 MouseEvent aNewMEvt = MouseEvent( aTestRect.Center(), aOrgMEvt.GetClicks(),
2392 aOrgMEvt.GetMode(), aOrgMEvt.GetButtons(),
2393 aOrgMEvt.GetModifier() );
2395 ImplStartSplit( aNewMEvt );
2396 mbFadeOutDown = false;
2400 else
2402 ImplSplitMousePos( aMousePosPixel );
2403 bool bSplit = true;
2404 if ( mbDragFull )
2406 if ( rTEvt.IsTrackingEnded() )
2408 if ( rTEvt.IsTrackingCanceled() )
2410 std::vector< ImplSplitItem* >& rItems = mpSplitSet->mpItems;
2411 size_t nItems = rItems.size();
2412 for ( size_t i = 0; i < nItems; i++ )
2414 rItems[i]->mnSize = mpLastSizes[i*2];
2415 rItems[i]->mnPixSize = mpLastSizes[i*2+1];
2417 ImplUpdate();
2418 Split();
2420 bSplit = false;
2423 else
2425 if ( rTEvt.IsTrackingEnded() )
2427 HideTracking();
2428 bSplit = !rTEvt.IsTrackingCanceled();
2430 else
2432 ImplDrawSplitTracking(aMousePosPixel);
2433 bSplit = false;
2437 if ( bSplit )
2439 bool bPropSmaller = (mnMouseModifier & KEY_SHIFT) != 0;
2440 bool bPropGreater = (mnMouseModifier & KEY_MOD1) != 0;
2441 long nDelta = mnMSplitPos-mnMStartPos;
2443 if ( (mnSplitTest & SPLIT_WINDOW) && mpMainSet->mpItems.empty() )
2445 if ( (mpSplitSet == mpMainSet) && mbBottomRight )
2446 nDelta *= -1;
2447 ImplSetWindowSize( nDelta );
2449 else
2451 long nNewSize = mpSplitSet->mpItems[mnSplitPos]->mnPixSize;
2452 if ( (mpSplitSet == mpMainSet) && mbBottomRight )
2453 nNewSize -= nDelta;
2454 else
2455 nNewSize += nDelta;
2456 SplitItem( mpSplitSet->mpItems[mnSplitPos]->mnId, nNewSize,
2457 bPropSmaller, bPropGreater );
2460 Split();
2462 if ( mbDragFull )
2464 Update();
2465 mnMStartPos = mnMSplitPos;
2469 if ( rTEvt.IsTrackingEnded() )
2471 delete [] mpLastSizes;
2472 mpLastSizes = nullptr;
2473 mpSplitSet = nullptr;
2474 mnMouseOff = 0;
2475 mnMStartPos = 0;
2476 mnMSplitPos = 0;
2477 mnMouseModifier = 0;
2478 mnSplitTest = 0;
2479 mnSplitPos = 0;
2484 bool SplitWindow::PreNotify( NotifyEvent& rNEvt )
2486 const MouseEvent* pMouseEvt = nullptr;
2488 if( (rNEvt.GetType() == MouseNotifyEvent::MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != nullptr )
2490 if( !pMouseEvt->GetButtons() && !pMouseEvt->IsSynthetic() && !pMouseEvt->IsModifierChanged() )
2492 // trigger redraw if mouse over state has changed
2493 Rectangle aFadeInRect;
2494 Rectangle aFadeOutRect;
2495 ImplGetFadeInRect( aFadeInRect );
2496 ImplGetFadeOutRect( aFadeOutRect );
2498 if ( aFadeInRect.IsInside( GetPointerPosPixel() ) != aFadeInRect.IsInside( GetLastPointerPosPixel() ) )
2499 Invalidate( aFadeInRect );
2500 if ( aFadeOutRect.IsInside( GetPointerPosPixel() ) != aFadeOutRect.IsInside( GetLastPointerPosPixel() ) )
2501 Invalidate( aFadeOutRect );
2503 if( pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow() )
2505 Invalidate( aFadeInRect );
2506 Invalidate( aFadeOutRect );
2510 return Window::PreNotify( rNEvt );
2513 void SplitWindow::Paint(vcl::RenderContext& rRenderContext, const Rectangle&)
2515 if (mnWinStyle & WB_BORDER)
2516 ImplDrawBorder(rRenderContext);
2518 ImplDrawBorderLine(rRenderContext);
2519 ImplDrawFadeOut(rRenderContext);
2520 ImplDrawFadeIn(rRenderContext);
2521 ImplDrawAutoHide(rRenderContext);
2523 // draw FrameSet-backgrounds
2524 ImplDrawBack(rRenderContext, mpMainSet);
2526 // draw splitter
2527 if (!(mnWinStyle & WB_NOSPLITDRAW))
2529 bool bFlat = (GetStyle() & WB_FLATSPLITDRAW) == WB_FLATSPLITDRAW;
2530 ImplDrawSplit(rRenderContext, mpMainSet, mbHorz, bFlat, !mbBottomRight);
2534 void SplitWindow::Resize()
2536 Size aSize = GetOutputSizePixel();
2537 mnDX = aSize.Width();
2538 mnDY = aSize.Height();
2540 ImplUpdate();
2541 Invalidate();
2544 void SplitWindow::RequestHelp( const HelpEvent& rHEvt )
2546 // no keyboard help for splitwin
2547 if ( rHEvt.GetMode() & (HelpEventMode::BALLOON | HelpEventMode::QUICK) && !rHEvt.KeyboardActivated() )
2549 Point aMousePosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() );
2550 Rectangle aHelpRect;
2551 sal_uInt16 nHelpResId = 0;
2553 ImplGetAutoHideRect( aHelpRect, true );
2554 if ( aHelpRect.IsInside( aMousePosPixel ) )
2556 if ( mbAutoHideIn )
2557 nHelpResId = SV_HELPTEXT_SPLITFIXED;
2558 else
2559 nHelpResId = SV_HELPTEXT_SPLITFLOATING;
2561 else
2563 ImplGetFadeInRect( aHelpRect, true );
2564 if ( aHelpRect.IsInside( aMousePosPixel ) )
2565 nHelpResId = SV_HELPTEXT_FADEIN;
2566 else
2568 ImplGetFadeOutRect( aHelpRect, true );
2569 if ( aHelpRect.IsInside( aMousePosPixel ) )
2570 nHelpResId = SV_HELPTEXT_FADEOUT;
2574 // get rectangle
2575 if ( nHelpResId )
2577 Point aPt = OutputToScreenPixel( aHelpRect.TopLeft() );
2578 aHelpRect.Left() = aPt.X();
2579 aHelpRect.Top() = aPt.Y();
2580 aPt = OutputToScreenPixel( aHelpRect.BottomRight() );
2581 aHelpRect.Right() = aPt.X();
2582 aHelpRect.Bottom() = aPt.Y();
2584 // get and draw text
2585 OUString aStr;
2586 ResMgr* pResMgr = ImplGetResMgr();
2587 if( pResMgr )
2588 aStr = ResId( nHelpResId, *pResMgr ).toString();
2589 if ( rHEvt.GetMode() & HelpEventMode::BALLOON )
2590 Help::ShowBalloon( this, aHelpRect.Center(), aHelpRect, aStr );
2591 else
2592 Help::ShowQuickHelp( this, aHelpRect, aStr );
2593 return;
2597 DockingWindow::RequestHelp( rHEvt );
2600 void SplitWindow::StateChanged( StateChangedType nType )
2602 switch ( nType )
2604 case StateChangedType::InitShow:
2605 if ( IsUpdateMode() )
2606 ImplCalcLayout();
2607 break;
2608 case StateChangedType::UpdateMode:
2609 if ( IsUpdateMode() && IsReallyShown() )
2610 ImplCalcLayout();
2611 break;
2612 case StateChangedType::ControlBackground:
2613 ImplInitSettings();
2614 Invalidate();
2615 break;
2616 default:;
2619 DockingWindow::StateChanged( nType );
2622 void SplitWindow::DataChanged( const DataChangedEvent& rDCEvt )
2624 if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
2625 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
2627 ImplInitSettings();
2628 Invalidate();
2630 else
2631 DockingWindow::DataChanged( rDCEvt );
2634 void SplitWindow::InsertItem( sal_uInt16 nId, vcl::Window* pWindow, long nSize,
2635 sal_uInt16 nPos, sal_uInt16 nIntoSetId,
2636 SplitWindowItemFlags nBits )
2638 #ifdef DBG_UTIL
2639 sal_uInt16 nDbgDummy;
2640 SAL_WARN_IF( ImplFindItem( mpMainSet, nId, nDbgDummy ), "vcl", "SplitWindow::InsertItem() - Id already exists" );
2641 #endif
2643 // Size has to be at least 1.
2644 if ( nSize < 1 )
2645 nSize = 1;
2647 ImplSplitSet* pSet = ImplFindSet( mpMainSet, nIntoSetId );
2648 #ifdef DBG_UTIL
2649 SAL_WARN_IF( !pSet, "vcl", "SplitWindow::InsertItem() - Set not exists" );
2650 #endif
2651 if(!pSet)
2653 return;
2656 // Don't insert further than the end
2657 if ( nPos > pSet->mpItems.size() )
2658 nPos = pSet->mpItems.size();
2660 // Create new item
2661 ImplSplitItem* pItem = new ImplSplitItem();
2662 pItem->mnSize = nSize;
2663 pItem->mnPixSize = 0;
2664 pItem->mnId = nId;
2665 pItem->mnBits = nBits;
2666 pItem->mnMinSize=-1;
2667 pItem->mnMaxSize=-1;
2669 if ( pWindow )
2671 // New VclPtr reference
2672 pItem->mpWindow = pWindow;
2673 pItem->mpOrgParent = pWindow->GetParent();
2675 // Attach window to SplitWindow.
2676 pWindow->Hide();
2677 pWindow->SetParent( this );
2679 else
2681 ImplSplitSet * pNewSet = new ImplSplitSet();
2682 pNewSet->mnId = nId;
2683 pNewSet->mnSplitSize = pSet->mnSplitSize;
2685 pItem->mpSet = pNewSet;
2688 // Insert in set
2689 pSet->mpItems.insert( pSet->mpItems.begin() + nPos, pItem );
2690 pSet->mbCalcPix = true;
2692 ImplUpdate();
2695 void SplitWindow::InsertItem( sal_uInt16 nId, long nSize,
2696 sal_uInt16 nPos, sal_uInt16 nIntoSetId,
2697 SplitWindowItemFlags nBits )
2699 InsertItem( nId, nullptr, nSize, nPos, nIntoSetId, nBits );
2702 void SplitWindow::RemoveItem( sal_uInt16 nId )
2704 #ifdef DBG_UTIL
2705 sal_uInt16 nDbgDummy;
2706 SAL_WARN_IF( !ImplFindItem( mpMainSet, nId, nDbgDummy ), "vcl", "SplitWindow::RemoveItem() - Id not found" );
2707 #endif
2709 // search set
2710 sal_uInt16 nPos;
2711 ImplSplitSet* pSet = ImplFindItem( mpMainSet, nId, nPos );
2713 if (!pSet)
2714 return;
2716 ImplSplitItem* pItem = pSet->mpItems[nPos];
2717 VclPtr<vcl::Window> pWindow = pItem->mpWindow;
2718 VclPtr<vcl::Window> pOrgParent = pItem->mpOrgParent;
2720 // delete set if required
2721 if ( !pWindow ) {
2722 delete pItem->mpSet ;
2723 pItem->mpSet = nullptr;
2726 // remove item
2727 pSet->mbCalcPix = true;
2728 pSet->mpItems.erase( pSet->mpItems.begin() + nPos );
2730 ImplUpdate();
2732 // to have the least amounts of paints delete window only here
2733 if ( pWindow )
2735 // restore window
2736 pWindow->Hide();
2737 pWindow->SetParent( pOrgParent );
2740 // Clear and delete
2741 delete pItem;
2742 pWindow.clear();
2743 pOrgParent.clear();
2746 void SplitWindow::Clear()
2748 // delete all sets
2749 delete mpMainSet ;
2751 // create Main-Set again
2752 mpMainSet = new ImplSplitSet();
2753 if ( mnWinStyle & WB_NOSPLITDRAW )
2754 mpMainSet->mnSplitSize -= 2;
2755 mpBaseSet = mpMainSet;
2757 // and invalidate again
2758 ImplUpdate();
2761 void SplitWindow::SplitItem( sal_uInt16 nId, long nNewSize,
2762 bool bPropSmall, bool bPropGreat )
2764 sal_uInt16 nPos;
2765 ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
2767 if (!pSet)
2768 return;
2770 size_t nItems = pSet->mpItems.size();
2771 std::vector< ImplSplitItem* >& rItems = pSet->mpItems;
2773 // When there is an explicit minimum or maximum size then move nNewSize
2774 // into that range (when it is not yet already in it.)
2775 nNewSize = ValidateSize(nNewSize, rItems[nPos]);
2777 if ( mbCalc )
2779 rItems[nPos]->mnSize = nNewSize;
2780 return;
2783 long nDelta = nNewSize-rItems[nPos]->mnPixSize;
2784 if ( !nDelta )
2785 return;
2787 // calculate area, which could be affected by splitting
2788 sal_uInt16 nMin = 0;
2789 sal_uInt16 nMax = nItems;
2790 for (size_t i = 0; i < nItems; ++i)
2792 if ( rItems[i]->mbFixed )
2794 if ( i < nPos )
2795 nMin = i+1;
2796 else
2797 nMax = i;
2801 // treat TopSet different if the window is sizeable
2802 bool bSmall = true;
2803 bool bGreat = true;
2804 if ( (pSet == mpMainSet) && (mnWinStyle & WB_SIZEABLE) )
2806 if ( nPos < pSet->mpItems.size()-1 )
2808 if ( !((bPropSmall && bPropGreat) ||
2809 ((nDelta > 0) && bPropSmall) ||
2810 ((nDelta < 0) && bPropGreat)) )
2812 if ( nDelta < 0 )
2813 bGreat = false;
2814 else
2815 bSmall = false;
2818 else
2820 if ( nDelta < 0 )
2821 bGreat = false;
2822 else
2823 bSmall = false;
2826 else if ( nPos >= nMax )
2828 bSmall = false;
2829 bGreat = false;
2831 else if ( nPos && (nPos >= pSet->mpItems.size()-1) )
2833 nPos--;
2834 nDelta *= -1;
2835 bool bTemp = bPropSmall;
2836 bPropSmall = bPropGreat;
2837 bPropGreat = bTemp;
2840 sal_uInt16 n;
2841 // now splitt the windows
2842 if ( nDelta < 0 )
2844 if ( bGreat )
2846 if ( bPropGreat )
2848 long nTempDelta = nDelta;
2851 n = nPos+1;
2854 if ( nTempDelta )
2856 rItems[n]->mnPixSize++;
2857 nTempDelta++;
2859 n++;
2861 while ( n < nMax );
2863 while ( nTempDelta );
2865 else
2866 rItems[nPos+1]->mnPixSize -= nDelta;
2869 if ( bSmall )
2871 if ( bPropSmall )
2875 n = nPos+1;
2878 if ( nDelta && rItems[n-1]->mnPixSize )
2880 rItems[n-1]->mnPixSize--;
2881 nDelta++;
2884 n--;
2886 while ( n > nMin );
2888 while ( nDelta );
2890 else
2892 n = nPos+1;
2895 if ( rItems[n-1]->mnPixSize+nDelta < 0 )
2897 nDelta += rItems[n-1]->mnPixSize;
2898 rItems[n-1]->mnPixSize = 0;
2900 else
2902 rItems[n-1]->mnPixSize += nDelta;
2903 break;
2905 n--;
2907 while ( n > nMin );
2911 else
2913 if ( bGreat )
2915 if ( bPropGreat )
2917 long nTempDelta = nDelta;
2920 n = nPos+1;
2923 if ( nTempDelta )
2925 rItems[n-1]->mnPixSize++;
2926 nTempDelta--;
2928 n--;
2930 while ( n > nMin );
2932 while ( nTempDelta );
2934 else
2935 rItems[nPos]->mnPixSize += nDelta;
2938 if ( bSmall )
2940 if ( bPropSmall )
2944 n = nPos+1;
2947 if ( nDelta && rItems[n]->mnPixSize )
2949 rItems[n]->mnPixSize--;
2950 nDelta--;
2953 n++;
2955 while ( n < nMax );
2957 while ( nDelta );
2959 else
2961 n = nPos+1;
2964 if ( rItems[n]->mnPixSize-nDelta < 0 )
2966 nDelta -= rItems[n]->mnPixSize;
2967 rItems[n]->mnPixSize = 0;
2969 else
2971 rItems[n]->mnPixSize -= nDelta;
2972 break;
2974 n++;
2976 while ( n < nMax );
2981 // update original sizes
2982 ImplCalcLogSize( rItems, nItems );
2984 ImplUpdate();
2987 void SplitWindow::SetItemSize( sal_uInt16 nId, long nNewSize )
2989 sal_uInt16 nPos;
2990 ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
2991 ImplSplitItem* pItem;
2993 if ( !pSet )
2994 return;
2996 // check if size is changed
2997 pItem = pSet->mpItems[nPos];
2998 if ( pItem->mnSize != nNewSize )
3000 // set new size and re-calculate
3001 pItem->mnSize = nNewSize;
3002 pSet->mbCalcPix = true;
3003 ImplUpdate();
3007 long SplitWindow::GetItemSize( sal_uInt16 nId ) const
3009 sal_uInt16 nPos;
3010 ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
3012 if ( pSet )
3013 return pSet->mpItems[nPos]->mnSize;
3014 else
3015 return 0;
3018 long SplitWindow::GetItemSize( sal_uInt16 nId, SplitWindowItemFlags nBits ) const
3020 sal_uInt16 nPos;
3021 ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
3023 if ( pSet )
3025 if ( nBits == pSet->mpItems[nPos]->mnBits )
3026 return pSet->mpItems[nPos]->mnSize;
3027 else
3029 const_cast<SplitWindow*>(this)->ImplCalcLayout();
3031 long nRelSize = 0;
3032 long nPerSize = 0;
3033 size_t nItems;
3034 SplitWindowItemFlags nTempBits;
3035 sal_uInt16 i;
3036 nItems = pSet->mpItems.size();
3037 std::vector< ImplSplitItem* >& rItems = pSet->mpItems;
3038 for ( i = 0; i < nItems; i++ )
3040 if ( i == nPos )
3041 nTempBits = nBits;
3042 else
3043 nTempBits = rItems[i]->mnBits;
3044 if ( nTempBits & SplitWindowItemFlags::RelativeSize )
3045 nRelSize += rItems[i]->mnPixSize;
3046 else if ( nTempBits & SplitWindowItemFlags::PercentSize )
3047 nPerSize += rItems[i]->mnPixSize;
3049 nPerSize += nRelSize;
3050 if ( nBits & SplitWindowItemFlags::RelativeSize )
3052 if ( nRelSize )
3053 return (rItems[nPos]->mnPixSize+(nRelSize/2))/nRelSize;
3054 else
3055 return 1;
3057 else if ( nBits & SplitWindowItemFlags::PercentSize )
3059 if ( nPerSize )
3060 return (rItems[nPos]->mnPixSize*100)/nPerSize;
3061 else
3062 return 1;
3064 else
3065 return rItems[nPos]->mnPixSize;
3068 else
3069 return 0;
3072 void SplitWindow::SetItemSizeRange (sal_uInt16 nId, const Range& rRange)
3074 sal_uInt16 nPos;
3075 ImplSplitSet* pSet = ImplFindItem(mpBaseSet, nId, nPos);
3077 if (pSet != nullptr)
3079 pSet->mpItems[nPos]->mnMinSize = rRange.Min();
3080 pSet->mpItems[nPos]->mnMaxSize = rRange.Max();
3084 sal_uInt16 SplitWindow::GetSet( sal_uInt16 nId ) const
3086 sal_uInt16 nPos;
3087 ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
3089 if ( pSet )
3090 return pSet->mnId;
3091 else
3092 return 0;
3095 bool SplitWindow::IsItemValid( sal_uInt16 nId ) const
3097 sal_uInt16 nPos;
3098 ImplSplitSet* pSet = mpBaseSet ? ImplFindItem(mpBaseSet, nId, nPos) : nullptr;
3100 if ( pSet )
3101 return true;
3102 else
3103 return false;
3106 sal_uInt16 SplitWindow::GetItemId( vcl::Window* pWindow ) const
3108 return ImplFindItem( mpBaseSet, pWindow );
3111 sal_uInt16 SplitWindow::GetItemId( const Point& rPos ) const
3113 return ImplFindItem( mpBaseSet, rPos, mbHorz, !mbBottomRight );
3116 sal_uInt16 SplitWindow::GetItemPos( sal_uInt16 nId, sal_uInt16 nSetId ) const
3118 ImplSplitSet* pSet = ImplFindSet( mpBaseSet, nSetId );
3119 sal_uInt16 nPos = SPLITWINDOW_ITEM_NOTFOUND;
3121 if ( pSet )
3123 for ( size_t i = 0; i < pSet->mpItems.size(); i++ )
3125 if ( pSet->mpItems[i]->mnId == nId )
3127 nPos = i;
3128 break;
3133 return nPos;
3136 sal_uInt16 SplitWindow::GetItemId( sal_uInt16 nPos ) const
3138 ImplSplitSet* pSet = ImplFindSet( mpBaseSet, 0/*nSetId*/ );
3139 if ( pSet && (nPos < pSet->mpItems.size()) )
3140 return pSet->mpItems[nPos]->mnId;
3141 else
3142 return 0;
3145 sal_uInt16 SplitWindow::GetItemCount( sal_uInt16 nSetId ) const
3147 ImplSplitSet* pSet = ImplFindSet( mpBaseSet, nSetId );
3148 if ( pSet )
3149 return pSet->mpItems.size();
3150 else
3151 return 0;
3154 void SplitWindow::ImplNewAlign()
3156 switch ( meAlign )
3158 case WindowAlign::Top:
3159 mbHorz = true;
3160 mbBottomRight = false;
3161 break;
3162 case WindowAlign::Bottom:
3163 mbHorz = true;
3164 mbBottomRight = true;
3165 break;
3166 case WindowAlign::Left:
3167 mbHorz = false;
3168 mbBottomRight = false;
3169 break;
3170 case WindowAlign::Right:
3171 mbHorz = false;
3172 mbBottomRight = true;
3173 break;
3176 if ( mnWinStyle & WB_BORDER )
3178 ImplCalcBorder( meAlign, false/*bNoAlign*/, mnLeftBorder, mnTopBorder,
3179 mnRightBorder, mnBottomBorder );
3182 if ( IsReallyVisible() && IsUpdateMode() )
3183 Invalidate();
3184 ImplUpdate();
3187 void SplitWindow::SetAlign( WindowAlign eNewAlign )
3189 if ( meAlign != eNewAlign )
3191 meAlign = eNewAlign;
3192 ImplNewAlign();
3196 void SplitWindow::ShowAutoHideButton( bool bShow )
3198 mbAutoHide = bShow;
3199 ImplUpdate();
3202 void SplitWindow::ShowFadeInHideButton()
3204 mbFadeIn = true;
3205 ImplUpdate();
3208 void SplitWindow::ShowFadeOutButton()
3210 mbFadeOut = true;
3211 ImplUpdate();
3214 void SplitWindow::SetAutoHideState( bool bAutoHide )
3216 mbAutoHideIn = bAutoHide;
3217 if ( IsReallyVisible() )
3219 Rectangle aRect;
3220 ImplGetAutoHideRect( aRect );
3221 Invalidate( aRect );
3225 long SplitWindow::GetFadeInSize() const
3227 long n = 0;
3229 if ( mbHorz )
3230 n = mnTopBorder+mnBottomBorder;
3231 else
3232 n = mnLeftBorder+mnRightBorder;
3234 return n+SPLITWIN_SPLITSIZE+SPLITWIN_SPLITSIZEEX-2;
3237 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */