1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include <string.h>
21
22 #include <sal/log.hxx>
23
24 #include <vcl/event.hxx>
25 #include <vcl/wall.hxx>
26 #include <vcl/help.hxx>
27 #include <vcl/splitwin.hxx>
28 #include <vcl/settings.hxx>
29 #include <vcl/ptrstyle.hxx>
30
31 #include <svdata.hxx>
32 #include <strings.hrc>
33
34
35 #define SPLITWIN_SPLITSIZE 4
36 #define SPLITWIN_SPLITSIZEEX 4
37 #define SPLITWIN_SPLITSIZEEXLN 7
38 #define SPLITWIN_SPLITSIZEAUTOHIDE 72
39 #define SPLITWIN_SPLITSIZEFADE 72
40
41 #define SPLIT_HORZ (sal_uInt16(0x0001))
42 #define SPLIT_VERT (sal_uInt16(0x0002))
43 #define SPLIT_WINDOW (sal_uInt16(0x0004))
44 #define SPLIT_NOSPLIT (sal_uInt16(0x8000))
45
46 class ImplSplitItem
47 {
48 public:
49 ImplSplitItem();
50
51 long mnSize;
52 long mnPixSize;
53 long mnLeft;
54 long mnTop;
55 long mnWidth;
56 long mnHeight;
57 long mnSplitPos;
58 long mnSplitSize;
59 long mnOldSplitPos;
60 long mnOldSplitSize;
61 long mnOldWidth;
62 long mnOldHeight;
63 std::unique_ptr<ImplSplitSet> mpSet;
64 VclPtr<vcl::Window> mpWindow;
65 VclPtr<vcl::Window> mpOrgParent;
66 sal_uInt16 mnId;
67 SplitWindowItemFlags mnBits;
68 bool mbFixed;
69 bool mbSubSize;
70 /// Minimal width or height of the item. -1 means no restriction.
71 long mnMinSize;
72 /// Maximal width or height of the item. -1 means no restriction.
73 long mnMaxSize;
74 };
75
76
77 class ImplSplitSet
78 {
79 public:
80 ImplSplitSet();
81 ~ImplSplitSet();
82
83 std::vector< ImplSplitItem > mvItems;
84 std::unique_ptr<Wallpaper> mpWallpaper;
85 long mnLastSize;
86 long mnSplitSize;
87 sal_uInt16 mnId;
88 bool mbCalcPix;
89 };
90
ImplSplitItem()91 ImplSplitItem::ImplSplitItem()
92 : mnSize(0)
93 , mnPixSize(0)
94 , mnLeft(0)
95 , mnTop(0)
96 , mnWidth(0)
97 , mnHeight(0)
98 , mnSplitPos(0)
99 , mnSplitSize(0)
100 , mnOldSplitPos(0)
101 , mnOldSplitSize(0)
102 , mnOldWidth(0)
103 , mnOldHeight(0)
104 , mnId(0)
105 , mnBits(SplitWindowItemFlags::NONE)
106 , mbFixed(false)
107 , mbSubSize(false)
108 , mnMinSize(-1)
109 , mnMaxSize(-1)
110 {
111 }
112
ImplSplitSet()113 ImplSplitSet::ImplSplitSet() :
114 mnLastSize( 0 ),
115 mnSplitSize( SPLITWIN_SPLITSIZE ),
116 mnId( 0 ),
117 mbCalcPix( true )
118 {
119 }
120
~ImplSplitSet()121 ImplSplitSet::~ImplSplitSet()
122 {
123 mpWallpaper.reset();
124 }
125
126 /** Check whether the given size is inside the valid range defined by
127 [rItem.mnMinSize,rItem.mnMaxSize]. When it is not inside it then return
128 the upper or lower bound, respectively. Otherwise return the given size
129 unmodified.
130 Note that either mnMinSize and/or mnMaxSize can be -1 in which case the
131 size has not lower or upper bound.
132 */
133 namespace {
ValidateSize(const long nSize,const ImplSplitItem & rItem)134 long ValidateSize (const long nSize, const ImplSplitItem & rItem)
135 {
136 if (rItem.mnMinSize>=0 && nSize<rItem.mnMinSize)
137 return rItem.mnMinSize;
138 else if (rItem.mnMaxSize>0 && nSize>rItem.mnMaxSize)
139 return rItem.mnMaxSize;
140 else
141 return nSize;
142 }
143 }
144
ImplCalcBorder(WindowAlign eAlign,long & rLeft,long & rTop,long & rRight,long & rBottom)145 static void ImplCalcBorder( WindowAlign eAlign,
146 long& rLeft, long& rTop,
147 long& rRight, long& rBottom )
148 {
149 switch ( eAlign )
150 {
151 case WindowAlign::Top:
152 rLeft = 2;
153 rTop = 2;
154 rRight = 2;
155 rBottom = 0;
156 break;
157 case WindowAlign::Left:
158 rLeft = 0;
159 rTop = 2;
160 rRight = 2;
161 rBottom = 2;
162 break;
163 case WindowAlign::Bottom:
164 rLeft = 2;
165 rTop = 0;
166 rRight = 2;
167 rBottom = 2;
168 break;
169 default:
170 rLeft = 0;
171 rTop = 2;
172 rRight = 2;
173 rBottom = 2;
174 break;
175 }
176 }
177
ImplDrawBorder(vcl::RenderContext & rRenderContext)178 void SplitWindow::ImplDrawBorder(vcl::RenderContext& rRenderContext)
179 {
180 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
181 long nDX = mnDX;
182 long nDY = mnDY;
183
184 switch (meAlign)
185 {
186 case WindowAlign::Bottom:
187 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
188 rRenderContext.DrawLine(Point(0, 0), Point(nDX - 1, 0));
189 rRenderContext.DrawLine(Point(0, nDY - 2), Point(nDX - 1, nDY - 2));
190
191 rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
192 rRenderContext.DrawLine(Point(0, 1), Point(nDX - 1, 1));
193 rRenderContext.DrawLine(Point(0, nDY - 1), Point(nDX - 1, nDY - 1));
194 break;
195 case WindowAlign::Top:
196 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
197 rRenderContext.DrawLine(Point(0, nDY - 2), Point(nDX - 1, nDY - 2));
198 rRenderContext.DrawLine(Point(0, 0), Point(nDX - 1, 0));
199
200 rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
201 rRenderContext.DrawLine(Point(0, nDY - 1), Point(nDX - 1, nDY - 1));
202 rRenderContext.DrawLine(Point(0, 1), Point(nDX - 1, 1));
203 break;
204 case WindowAlign::Left:
205 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
206 rRenderContext.DrawLine(Point(nDX - 2, 0), Point(nDX - 2, nDY - 2));
207 rRenderContext.DrawLine(Point(0, 0), Point(nDX - 1, 0));
208 rRenderContext.DrawLine(Point(0, nDY - 2), Point(nDX - 2, nDY - 2));
209
210 rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
211 rRenderContext.DrawLine(Point(nDX - 1, 0), Point(nDX - 1, nDY - 1));
212 rRenderContext.DrawLine(Point(0, 1), Point(nDX - 3, 1));
213 rRenderContext.DrawLine(Point(0, nDY - 1), Point(nDX - 2, nDY - 1));
214 break;
215 default:
216 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
217 rRenderContext.DrawLine(Point(0, 0), Point( 0, nDY - 2));
218 rRenderContext.DrawLine(Point(0, 0), Point( nDX - 1, 0));
219 rRenderContext.DrawLine(Point(0, nDY - 2), Point(nDX - 1, nDY - 2));
220
221 rRenderContext.SetLineColor( rStyleSettings.GetLightColor());
222 rRenderContext.DrawLine(Point(1, 1), Point(1, nDY - 3));
223 rRenderContext.DrawLine(Point(1, 1), Point(nDX - 1, 1));
224 rRenderContext.DrawLine(Point(0, nDY - 1), Point(nDX - 1, nDY - 1));
225 }
226 }
227
ImplDrawBorderLine(vcl::RenderContext & rRenderContext)228 void SplitWindow::ImplDrawBorderLine(vcl::RenderContext& rRenderContext)
229 {
230 if (mbFadeOut)
231 {
232 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
233 long nDX = mnDX;
234 long nDY = mnDY;
235
236 switch (meAlign)
237 {
238 case WindowAlign::Left:
239 rRenderContext.SetLineColor( rStyleSettings.GetShadowColor() );
240 rRenderContext.DrawLine( Point( nDX-SPLITWIN_SPLITSIZEEXLN-1, 1 ), Point( nDX-SPLITWIN_SPLITSIZEEXLN-1, nDY-2 ) );
241
242 rRenderContext.SetLineColor( rStyleSettings.GetLightColor() );
243 rRenderContext.DrawLine( Point( nDX-SPLITWIN_SPLITSIZEEXLN, 1 ), Point( nDX-SPLITWIN_SPLITSIZEEXLN, nDY-3 ) );
244 break;
245 case WindowAlign::Right:
246 rRenderContext.SetLineColor( rStyleSettings.GetShadowColor() );
247 rRenderContext.DrawLine( Point( SPLITWIN_SPLITSIZEEXLN-1, 0 ), Point( SPLITWIN_SPLITSIZEEXLN-1, nDY-2 ) );
248
249 rRenderContext.SetLineColor( rStyleSettings.GetLightColor() );
250 rRenderContext.DrawLine( Point( SPLITWIN_SPLITSIZEEXLN, 1 ), Point( SPLITWIN_SPLITSIZEEXLN, nDY-3 ) );
251 break;
252 case WindowAlign::Top:
253 rRenderContext.SetLineColor( rStyleSettings.GetShadowColor() );
254 rRenderContext.DrawLine( Point( 0, nDY-SPLITWIN_SPLITSIZEEXLN-1 ), Point( nDX-1, nDY-SPLITWIN_SPLITSIZEEXLN-1 ) );
255
256 rRenderContext.SetLineColor( rStyleSettings.GetLightColor() );
257 rRenderContext.DrawLine( Point( 0, nDY-SPLITWIN_SPLITSIZEEXLN ), Point( nDX-1, nDY-SPLITWIN_SPLITSIZEEXLN ) );
258 break;
259 case WindowAlign::Bottom:
260 rRenderContext.SetLineColor( rStyleSettings.GetShadowColor() );
261 rRenderContext.DrawLine( Point( 0, 5 ), Point( nDX-1, 5 ) );
262
263 rRenderContext.SetLineColor( rStyleSettings.GetLightColor() );
264 rRenderContext.DrawLine( Point( 0, SPLITWIN_SPLITSIZEEXLN ), Point( nDX-1, SPLITWIN_SPLITSIZEEXLN ) );
265 break;
266 }
267 }
268 }
269
ImplFindSet(ImplSplitSet * pSet,sal_uInt16 nId)270 static ImplSplitSet* ImplFindSet( ImplSplitSet* pSet, sal_uInt16 nId )
271 {
272 if ( pSet->mnId == nId )
273 return pSet;
274
275 std::vector< ImplSplitItem >& rItems = pSet->mvItems;
276
277 for ( const auto& rItem : rItems )
278 {
279 if ( rItem.mnId == nId )
280 return rItem.mpSet.get();
281 }
282
283 for ( auto& rItem : rItems )
284 {
285 if ( rItem.mpSet )
286 {
287 ImplSplitSet* pFindSet = ImplFindSet( rItem.mpSet.get(), nId );
288 if ( pFindSet )
289 return pFindSet;
290 }
291 }
292
293 return nullptr;
294 }
295
ImplFindItem(ImplSplitSet * pSet,sal_uInt16 nId,sal_uInt16 & rPos)296 static ImplSplitSet* ImplFindItem( ImplSplitSet* pSet, sal_uInt16 nId, sal_uInt16& rPos )
297 {
298 size_t nItems = pSet->mvItems.size();
299 std::vector< ImplSplitItem >& rItems = pSet->mvItems;
300
301 for ( size_t i = 0; i < nItems; i++ )
302 {
303 if ( rItems[i].mnId == nId )
304 {
305 rPos = i;
306 return pSet;
307 }
308 }
309
310 for ( auto& rItem : rItems )
311 {
312 if ( rItem.mpSet )
313 {
314 ImplSplitSet* pFindSet = ImplFindItem( rItem.mpSet.get(), nId, rPos );
315 if ( pFindSet )
316 return pFindSet;
317 }
318 }
319
320 return nullptr;
321 }
322
ImplFindItem(ImplSplitSet * pSet,vcl::Window * pWindow)323 static sal_uInt16 ImplFindItem( ImplSplitSet* pSet, vcl::Window* pWindow )
324 {
325 std::vector< ImplSplitItem >& rItems = pSet->mvItems;
326
327 for ( auto& rItem : rItems )
328 {
329 if ( rItem.mpWindow == pWindow )
330 return rItem.mnId;
331 else
332 {
333 if ( rItem.mpSet )
334 {
335 sal_uInt16 nId = ImplFindItem( rItem.mpSet.get(), pWindow );
336 if ( nId )
337 return nId;
338 }
339 }
340 }
341
342 return 0;
343 }
344
ImplFindItem(ImplSplitSet * pSet,const Point & rPos,bool bRows,bool bDown=true)345 static sal_uInt16 ImplFindItem( ImplSplitSet* pSet, const Point& rPos,
346 bool bRows, bool bDown = true )
347 {
348 std::vector< ImplSplitItem >& rItems = pSet->mvItems;
349
350 for ( auto& rItem : rItems )
351 {
352 if ( rItem.mnWidth && rItem.mnHeight )
353 {
354 Point aPoint( rItem.mnLeft, rItem.mnTop );
355 Size aSize( rItem.mnWidth, rItem.mnHeight );
356 tools::Rectangle aRect( aPoint, aSize );
357 if ( bRows )
358 {
359 if ( bDown )
360 aRect.AdjustBottom(pSet->mnSplitSize );
361 else
362 aRect.AdjustTop( -(pSet->mnSplitSize) );
363 }
364 else
365 {
366 if ( bDown )
367 aRect.AdjustRight(pSet->mnSplitSize );
368 else
369 aRect.AdjustLeft( -(pSet->mnSplitSize) );
370 }
371
372 if ( aRect.IsInside( rPos ) )
373 {
374 if ( rItem.mpSet && !rItem.mpSet->mvItems.empty() )
375 {
376 return ImplFindItem( rItem.mpSet.get(), rPos,
377 !(rItem.mnBits & SplitWindowItemFlags::ColSet) );
378 }
379 else
380 return rItem.mnId;
381 }
382 }
383 }
384
385 return 0;
386 }
387
ImplCalcSet(ImplSplitSet * pSet,long nSetLeft,long nSetTop,long nSetWidth,long nSetHeight,bool bRows,bool bDown=true)388 static void ImplCalcSet( ImplSplitSet* pSet,
389 long nSetLeft, long nSetTop,
390 long nSetWidth, long nSetHeight,
391 bool bRows, bool bDown = true )
392 {
393 if ( pSet->mvItems.empty() )
394 return;
395
396 sal_uInt16 nMins;
397 sal_uInt16 nCalcItems;
398 size_t nItems = pSet->mvItems.size();
399 sal_uInt16 nAbsItems;
400 long nCalcSize;
401 long nPos;
402 long nMaxPos;
403 std::vector< ImplSplitItem >& rItems = pSet->mvItems;
404 bool bEmpty;
405
406 // calculate sizes
407 if ( bRows )
408 nCalcSize = nSetHeight;
409 else
410 nCalcSize = nSetWidth;
411 nCalcSize -= (rItems.size()-1)*pSet->mnSplitSize;
412 if ( pSet->mbCalcPix || (pSet->mnLastSize != nCalcSize) )
413 {
414 long nPercentFactor = 10;
415 long nRelCount = 0;
416 long nPercent = 0;
417 long nRelPercent = 0;
418 long nAbsSize = 0;
419 long nCurSize = 0;
420 for ( const auto& rItem : rItems )
421 {
422 if ( rItem.mnBits & SplitWindowItemFlags::RelativeSize )
423 nRelCount += rItem.mnSize;
424 else if ( rItem.mnBits & SplitWindowItemFlags::PercentSize )
425 nPercent += rItem.mnSize;
426 else
427 nAbsSize += rItem.mnSize;
428 }
429 // map relative values to percentages (percentage here one tenth of a percent)
430 nPercent *= nPercentFactor;
431 if ( nRelCount )
432 {
433 long nRelPercentBase = 1000;
434 while ( (nRelCount > nRelPercentBase) && (nPercentFactor < 100000) )
435 {
436 nRelPercentBase *= 10;
437 nPercentFactor *= 10;
438 }
439 if ( nPercent < nRelPercentBase )
440 {
441 nRelPercent = (nRelPercentBase-nPercent)/nRelCount;
442 nPercent += nRelPercent*nRelCount;
443 }
444 else
445 nRelPercent = 0;
446 }
447 if ( !nPercent )
448 nPercent = 1;
449 long nSizeDelta = nCalcSize-nAbsSize;
450 for ( auto& rItem : rItems )
451 {
452 if ( rItem.mnBits & SplitWindowItemFlags::RelativeSize )
453 {
454 if ( nSizeDelta <= 0 )
455 rItem.mnPixSize = 0;
456 else
457 rItem.mnPixSize = (nSizeDelta*rItem.mnSize*nRelPercent)/nPercent;
458 }
459 else if ( rItem.mnBits & SplitWindowItemFlags::PercentSize )
460 {
461 if ( nSizeDelta <= 0 )
462 rItem.mnPixSize = 0;
463 else
464 rItem.mnPixSize = (nSizeDelta*rItem.mnSize*nPercentFactor)/nPercent;
465 }
466 else
467 rItem.mnPixSize = rItem.mnSize;
468 nCurSize += rItem.mnPixSize;
469 }
470
471 pSet->mbCalcPix = false;
472 pSet->mnLastSize = nCalcSize;
473
474 // adapt window
475 nSizeDelta = nCalcSize-nCurSize;
476 if ( nSizeDelta )
477 {
478 nAbsItems = 0;
479 long nSizeWinSize = 0;
480
481 // first resize absolute items relative
482 for ( const auto& rItem : rItems )
483 {
484 if ( !(rItem.mnBits & (SplitWindowItemFlags::RelativeSize | SplitWindowItemFlags::PercentSize)) )
485 {
486 nAbsItems++;
487 nSizeWinSize += rItem.mnPixSize;
488 }
489 }
490 // do not compensate rounding errors here
491 if ( (nAbsItems < static_cast<sal_uInt16>(std::abs( nSizeDelta ))) && nSizeWinSize )
492 {
493 long nNewSizeWinSize = 0;
494
495 for ( auto& rItem : rItems )
496 {
497 if ( !(rItem.mnBits & (SplitWindowItemFlags::RelativeSize | SplitWindowItemFlags::PercentSize)) )
498 {
499 rItem.mnPixSize += (nSizeDelta*rItem.mnPixSize)/nSizeWinSize;
500 nNewSizeWinSize += rItem.mnPixSize;
501 }
502 }
503
504 nSizeDelta -= nNewSizeWinSize-nSizeWinSize;
505 }
506
507 // compensate rounding errors now
508 sal_uInt16 j = 0;
509 nMins = 0;
510 while ( nSizeDelta && (nItems != nMins) )
511 {
512 // determine which items we can calculate
513 nCalcItems = 0;
514 while ( !nCalcItems )
515 {
516 for ( auto& rItem : rItems )
517 {
518 rItem.mbSubSize = false;
519
520 if ( j >= 2 )
521 rItem.mbSubSize = true;
522 else
523 {
524 if ( (nSizeDelta > 0) || rItem.mnPixSize )
525 {
526 if ( j >= 1 )
527 rItem.mbSubSize = true;
528 else
529 {
530 if ( (j == 0) && (rItem.mnBits & (SplitWindowItemFlags::RelativeSize | SplitWindowItemFlags::PercentSize)) )
531 rItem.mbSubSize = true;
532 }
533 }
534 }
535
536 if ( rItem.mbSubSize )
537 nCalcItems++;
538 }
539
540 j++;
541 }
542
543 // subtract size of individual items
544 long nErrorSum = nSizeDelta % nCalcItems;
545 long nCurSizeDelta = nSizeDelta / nCalcItems;
546 nMins = 0;
547 for ( auto& rItem : rItems )
548 {
549 if ( rItem.mbSubSize )
550 {
551 long* pSize = &(rItem.mnPixSize);
552 long nTempErr;
553
554 if ( nErrorSum )
555 {
556 if ( nErrorSum < 0 )
557 nTempErr = -1;
558 else
559 nTempErr = 1;
560 }
561 else
562 nTempErr = 0;
563
564 if ( (*pSize+nCurSizeDelta+nTempErr) <= 0 )
565 {
566 long nTemp = *pSize;
567 if ( nTemp )
568 {
569 *pSize -= nTemp;
570 nSizeDelta += nTemp;
571 }
572 nMins++;
573 }
574 else
575 {
576 *pSize += nCurSizeDelta;
577 nSizeDelta -= nCurSizeDelta;
578 if ( nTempErr && (*pSize || (nTempErr > 0)) )
579 {
580 *pSize += nTempErr;
581 nSizeDelta -= nTempErr;
582 nErrorSum -= nTempErr;
583 }
584 }
585 }
586 }
587 }
588 }
589 }
590
591 // calculate maximum size
592 if ( bRows )
593 {
594 nPos = nSetTop;
595 if ( !bDown )
596 nMaxPos = nSetTop-nSetHeight;
597 else
598 nMaxPos = nSetTop+nSetHeight;
599 }
600 else
601 {
602 nPos = nSetLeft;
603 if ( !bDown )
604 nMaxPos = nSetLeft-nSetWidth;
605 else
606 nMaxPos = nSetLeft+nSetWidth;
607 }
608
609 // order windows and adept values
610 for ( size_t i = 0; i < nItems; i++ )
611 {
612 rItems[i].mnOldSplitPos = rItems[i].mnSplitPos;
613 rItems[i].mnOldSplitSize = rItems[i].mnSplitSize;
614 rItems[i].mnOldWidth = rItems[i].mnWidth;
615 rItems[i].mnOldHeight = rItems[i].mnHeight;
616
617 bEmpty = false;
618 if ( bDown )
619 {
620 if ( nPos+rItems[i].mnPixSize > nMaxPos )
621 bEmpty = true;
622 }
623 else
624 {
625 nPos -= rItems[i].mnPixSize;
626 if ( nPos < nMaxPos )
627 bEmpty = true;
628 }
629
630 if ( bEmpty )
631 {
632 rItems[i].mnWidth = 0;
633 rItems[i].mnHeight = 0;
634 rItems[i].mnSplitSize = 0;
635 }
636 else
637 {
638 if ( bRows )
639 {
640 rItems[i].mnLeft = nSetLeft;
641 rItems[i].mnTop = nPos;
642 rItems[i].mnWidth = nSetWidth;
643 rItems[i].mnHeight = rItems[i].mnPixSize;
644 }
645 else
646 {
647 rItems[i].mnLeft = nPos;
648 rItems[i].mnTop = nSetTop;
649 rItems[i].mnWidth = rItems[i].mnPixSize;
650 rItems[i].mnHeight = nSetHeight;
651 }
652
653 if ( i > nItems-1 )
654 rItems[i].mnSplitSize = 0;
655 else
656 {
657 rItems[i].mnSplitSize = pSet->mnSplitSize;
658 if ( bDown )
659 {
660 rItems[i].mnSplitPos = nPos+rItems[i].mnPixSize;
661 if ( rItems[i].mnSplitPos+rItems[i].mnSplitSize > nMaxPos )
662 rItems[i].mnSplitSize = nMaxPos-rItems[i].mnSplitPos;
663 }
664 else
665 {
666 rItems[i].mnSplitPos = nPos-pSet->mnSplitSize;
667 if ( rItems[i].mnSplitPos < nMaxPos )
668 rItems[i].mnSplitSize = rItems[i].mnSplitPos+pSet->mnSplitSize-nMaxPos;
669 }
670 }
671 }
672
673 if ( !bDown )
674 nPos -= pSet->mnSplitSize;
675 else
676 nPos += rItems[i].mnPixSize+pSet->mnSplitSize;
677 }
678
679 // calculate Sub-Set's
680 for ( auto& rItem : rItems )
681 {
682 if ( rItem.mpSet && rItem.mnWidth && rItem.mnHeight )
683 {
684 ImplCalcSet( rItem.mpSet.get(),
685 rItem.mnLeft, rItem.mnTop,
686 rItem.mnWidth, rItem.mnHeight,
687 !(rItem.mnBits & SplitWindowItemFlags::ColSet) );
688 }
689 }
690
691 // set fixed
692 for ( auto& rItem : rItems )
693 {
694 rItem.mbFixed = false;
695 if ( rItem.mnBits & SplitWindowItemFlags::Fixed )
696 rItem.mbFixed = true;
697 else
698 {
699 // this item is also fixed if Child-Set is available,
700 // if a child is fixed
701 if ( rItem.mpSet )
702 {
703 for ( auto const & j: rItem.mpSet->mvItems )
704 {
705 if ( j.mbFixed )
706 {
707 rItem.mbFixed = true;
708 break;
709 }
710 }
711 }
712 }
713 }
714 }
715
ImplCalcSet2(SplitWindow * pWindow,ImplSplitSet * pSet,bool bHide,bool bRows)716 void SplitWindow::ImplCalcSet2( SplitWindow* pWindow, ImplSplitSet* pSet, bool bHide,
717 bool bRows )
718 {
719 std::vector< ImplSplitItem >& rItems = pSet->mvItems;
720
721 if ( pWindow->IsReallyVisible() && pWindow->IsUpdateMode() && pWindow->mbInvalidate )
722 {
723 for ( const auto& rItem : rItems )
724 {
725 if ( rItem.mnSplitSize )
726 {
727 // invalidate all, if applicable or only a small part
728 if ( (rItem.mnOldSplitPos != rItem.mnSplitPos) ||
729 (rItem.mnOldSplitSize != rItem.mnSplitSize) ||
730 (rItem.mnOldWidth != rItem.mnWidth) ||
731 (rItem.mnOldHeight != rItem.mnHeight) )
732 {
733 tools::Rectangle aRect;
734
735 // invalidate old rectangle
736 if ( bRows )
737 {
738 aRect.SetLeft( rItem.mnLeft );
739 aRect.SetRight( rItem.mnLeft+rItem.mnOldWidth-1 );
740 aRect.SetTop( rItem.mnOldSplitPos );
741 aRect.SetBottom( aRect.Top() + rItem.mnOldSplitSize );
742 }
743 else
744 {
745 aRect.SetTop( rItem.mnTop );
746 aRect.SetBottom( rItem.mnTop+rItem.mnOldHeight-1 );
747 aRect.SetLeft( rItem.mnOldSplitPos );
748 aRect.SetRight( aRect.Left() + rItem.mnOldSplitSize );
749 }
750 pWindow->Invalidate( aRect );
751 // invalidate new rectangle
752 if ( bRows )
753 {
754 aRect.SetLeft( rItem.mnLeft );
755 aRect.SetRight( rItem.mnLeft+rItem.mnWidth-1 );
756 aRect.SetTop( rItem.mnSplitPos );
757 aRect.SetBottom( aRect.Top() + rItem.mnSplitSize );
758 }
759 else
760 {
761 aRect.SetTop( rItem.mnTop );
762 aRect.SetBottom( rItem.mnTop+rItem.mnHeight-1 );
763 aRect.SetLeft( rItem.mnSplitPos );
764 aRect.SetRight( aRect.Left() + rItem.mnSplitSize );
765 }
766 pWindow->Invalidate( aRect );
767
768 // invalidate complete set, as these areas
769 // are not cluttered by windows
770 if ( rItem.mpSet && rItem.mpSet->mvItems.empty() )
771 {
772 aRect.SetLeft( rItem.mnLeft );
773 aRect.SetTop( rItem.mnTop );
774 aRect.SetRight( rItem.mnLeft+rItem.mnWidth-1 );
775 aRect.SetBottom( rItem.mnTop+rItem.mnHeight-1 );
776 pWindow->Invalidate( aRect );
777 }
778 }
779 }
780 }
781 }
782
783 // position windows
784 for ( auto& rItem : rItems )
785 {
786 if ( rItem.mpSet )
787 {
788 bool bTempHide = bHide;
789 if ( !rItem.mnWidth || !rItem.mnHeight )
790 bTempHide = true;
791 ImplCalcSet2( pWindow, rItem.mpSet.get(), bTempHide,
792 !(rItem.mnBits & SplitWindowItemFlags::ColSet) );
793 }
794 else
795 {
796 if ( rItem.mnWidth && rItem.mnHeight && !bHide )
797 {
798 Point aPos( rItem.mnLeft, rItem.mnTop );
799 Size aSize( rItem.mnWidth, rItem.mnHeight );
800 rItem.mpWindow->SetPosSizePixel( aPos, aSize );
801 }
802 else
803 rItem.mpWindow->Hide();
804 }
805 }
806
807 // show windows and reset flag
808 for ( auto& rItem : rItems )
809 {
810 if ( rItem.mpWindow && rItem.mnWidth && rItem.mnHeight && !bHide )
811 rItem.mpWindow->Show();
812 }
813 }
814
ImplCalcLogSize(std::vector<ImplSplitItem> & rItems,size_t nItems)815 static void ImplCalcLogSize( std::vector< ImplSplitItem > & rItems, size_t nItems )
816 {
817 // update original sizes
818 size_t i;
819 long nRelSize = 0;
820 long nPerSize = 0;
821
822 for ( i = 0; i < nItems; i++ )
823 {
824 if ( rItems[i].mnBits & SplitWindowItemFlags::RelativeSize )
825 nRelSize += rItems[i].mnPixSize;
826 else if ( rItems[i].mnBits & SplitWindowItemFlags::PercentSize )
827 nPerSize += rItems[i].mnPixSize;
828 }
829 nPerSize += nRelSize;
830 for ( i = 0; i < nItems; i++ )
831 {
832 if ( rItems[i].mnBits & SplitWindowItemFlags::RelativeSize )
833 {
834 if ( nRelSize )
835 rItems[i].mnSize = (rItems[i].mnPixSize+(nRelSize/2))/nRelSize;
836 else
837 rItems[i].mnSize = 1;
838 }
839 else if ( rItems[i].mnBits & SplitWindowItemFlags::PercentSize )
840 {
841 if ( nPerSize )
842 rItems[i].mnSize = (rItems[i].mnPixSize*100)/nPerSize;
843 else
844 rItems[i].mnSize = 1;
845 }
846 else
847 rItems[i].mnSize = rItems[i].mnPixSize;
848 }
849 }
850
ImplDrawBack(vcl::RenderContext & rRenderContext,ImplSplitSet * pSet)851 void SplitWindow::ImplDrawBack(vcl::RenderContext& rRenderContext, ImplSplitSet* pSet)
852 {
853 std::vector< ImplSplitItem >& rItems = pSet->mvItems;
854
855 for ( const auto& rItem : rItems )
856 {
857 pSet = rItem.mpSet.get();
858 if (pSet && pSet->mpWallpaper)
859 {
860 Point aPoint(rItem.mnLeft, rItem.mnTop);
861 Size aSize(rItem.mnWidth, rItem.mnHeight);
862 tools::Rectangle aRect(aPoint, aSize);
863 rRenderContext.DrawWallpaper(aRect, *pSet->mpWallpaper);
864 }
865 }
866
867 for ( auto& rItem : rItems )
868 {
869 if (rItem.mpSet)
870 ImplDrawBack(rRenderContext, rItem.mpSet.get());
871 }
872 }
873
ImplDrawSplit(vcl::RenderContext & rRenderContext,ImplSplitSet * pSet,bool bRows,bool bDown)874 static void ImplDrawSplit(vcl::RenderContext& rRenderContext, ImplSplitSet* pSet, bool bRows, bool bDown)
875 {
876 if (pSet->mvItems.empty())
877 return;
878
879 size_t nItems = pSet->mvItems.size();
880 long nPos;
881 long nTop;
882 long nBottom;
883 std::vector< ImplSplitItem >& rItems = pSet->mvItems;
884 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
885
886 for (size_t i = 0; i < nItems-1; i++)
887 {
888 if (rItems[i].mnSplitSize)
889 {
890 nPos = rItems[i].mnSplitPos;
891
892 long nItemSplitSize = rItems[i].mnSplitSize;
893 long nSplitSize = pSet->mnSplitSize;
894 if (bRows)
895 {
896 nTop = rItems[i].mnLeft;
897 nBottom = rItems[i].mnLeft+rItems[i].mnWidth-1;
898
899 if (bDown || (nItemSplitSize >= nSplitSize))
900 {
901 rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
902 rRenderContext.DrawLine(Point(nTop, nPos + 1), Point(nBottom, nPos + 1));
903 }
904 nPos += nSplitSize-2;
905 if ((!bDown && (nItemSplitSize >= 2)) ||
906 (bDown && (nItemSplitSize >= nSplitSize - 1)))
907 {
908 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
909 rRenderContext.DrawLine(Point(nTop, nPos), Point(nBottom, nPos));
910 }
911 nPos++;
912 if (!bDown || (nItemSplitSize >= nSplitSize))
913 {
914 rRenderContext.SetLineColor(rStyleSettings.GetDarkShadowColor());
915 rRenderContext.DrawLine(Point(nTop, nPos), Point(nBottom, nPos));
916 }
917 }
918 else
919 {
920 nTop = rItems[i].mnTop;
921 nBottom = rItems[i].mnTop+pSet->mvItems[i].mnHeight-1;
922
923 if (bDown || (nItemSplitSize >= nSplitSize))
924 {
925 rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
926 rRenderContext.DrawLine(Point(nPos + 1, nTop), Point(nPos+1, nBottom));
927 }
928 nPos += pSet->mnSplitSize - 2;
929 if ((!bDown && (nItemSplitSize >= 2)) ||
930 (bDown && (nItemSplitSize >= nSplitSize - 1)))
931 {
932 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
933 rRenderContext.DrawLine(Point(nPos, nTop), Point(nPos, nBottom));
934 }
935 nPos++;
936 if (!bDown || (nItemSplitSize >= nSplitSize))
937 {
938 rRenderContext.SetLineColor(rStyleSettings.GetDarkShadowColor());
939 rRenderContext.DrawLine(Point(nPos, nTop), Point(nPos, nBottom));
940 }
941 }
942 }
943 }
944
945 for ( auto& rItem : rItems )
946 {
947 if (rItem.mpSet && rItem.mnWidth && rItem.mnHeight)
948 {
949 ImplDrawSplit(rRenderContext, rItem.mpSet.get(), !(rItem.mnBits & SplitWindowItemFlags::ColSet), true/*bDown*/);
950 }
951 }
952 }
953
ImplTestSplit(ImplSplitSet * pSet,const Point & rPos,long & rMouseOff,ImplSplitSet ** ppFoundSet,sal_uInt16 & rFoundPos,bool bRows)954 sal_uInt16 SplitWindow::ImplTestSplit( ImplSplitSet* pSet, const Point& rPos,
955 long& rMouseOff, ImplSplitSet** ppFoundSet, sal_uInt16& rFoundPos,
956 bool bRows )
957 {
958 if ( pSet->mvItems.empty() )
959 return 0;
960
961 sal_uInt16 nSplitTest;
962 size_t nItems = pSet->mvItems.size();
963 long nMPos1;
964 long nMPos2;
965 long nPos;
966 long nTop;
967 long nBottom;
968 std::vector< ImplSplitItem >& rItems = pSet->mvItems;
969
970 if ( bRows )
971 {
972 nMPos1 = rPos.X();
973 nMPos2 = rPos.Y();
974 }
975 else
976 {
977 nMPos1 = rPos.Y();
978 nMPos2 = rPos.X();
979 }
980
981 for ( size_t i = 0; i < nItems-1; i++ )
982 {
983 if ( rItems[i].mnSplitSize )
984 {
985 if ( bRows )
986 {
987 nTop = rItems[i].mnLeft;
988 nBottom = rItems[i].mnLeft+rItems[i].mnWidth-1;
989 }
990 else
991 {
992 nTop = rItems[i].mnTop;
993 nBottom = rItems[i].mnTop+rItems[i].mnHeight-1;
994 }
995 nPos = rItems[i].mnSplitPos;
996
997 if ( (nMPos1 >= nTop) && (nMPos1 <= nBottom) &&
998 (nMPos2 >= nPos) && (nMPos2 <= nPos+rItems[i].mnSplitSize) )
999 {
1000 if ( !rItems[i].mbFixed && !rItems[i+1].mbFixed )
1001 {
1002 rMouseOff = nMPos2-nPos;
1003 *ppFoundSet = pSet;
1004 rFoundPos = i;
1005 if ( bRows )
1006 return SPLIT_VERT;
1007 else
1008 return SPLIT_HORZ;
1009 }
1010 else
1011 return SPLIT_NOSPLIT;
1012 }
1013 }
1014 }
1015
1016 for ( auto& rItem : rItems )
1017 {
1018 if ( rItem.mpSet )
1019 {
1020 nSplitTest = ImplTestSplit( rItem.mpSet.get(), rPos,
1021 rMouseOff, ppFoundSet, rFoundPos,
1022 !(rItem.mnBits & SplitWindowItemFlags::ColSet) );
1023 if ( nSplitTest )
1024 return nSplitTest;
1025 }
1026 }
1027
1028 return 0;
1029 }
1030
ImplTestSplit(const SplitWindow * pWindow,const Point & rPos,long & rMouseOff,ImplSplitSet ** ppFoundSet,sal_uInt16 & rFoundPos)1031 sal_uInt16 SplitWindow::ImplTestSplit( const SplitWindow* pWindow, const Point& rPos,
1032 long& rMouseOff, ImplSplitSet** ppFoundSet, sal_uInt16& rFoundPos )
1033 {
1034 // Resizable SplitWindow should be treated different
1035 if ( pWindow->mnWinStyle & WB_SIZEABLE )
1036 {
1037 long nTPos;
1038 long nPos;
1039 long nBorder;
1040
1041 if ( pWindow->mbHorz )
1042 {
1043 if ( pWindow->mbBottomRight )
1044 {
1045 nBorder = pWindow->mnBottomBorder;
1046 nPos = 0;
1047 }
1048 else
1049 {
1050 nBorder = pWindow->mnTopBorder;
1051 nPos = pWindow->mnDY-nBorder;
1052 }
1053 nTPos = rPos.Y();
1054 }
1055 else
1056 {
1057 if ( pWindow->mbBottomRight )
1058 {
1059 nBorder = pWindow->mnRightBorder;
1060 nPos = 0;
1061 }
1062 else
1063 {
1064 nBorder = pWindow->mnLeftBorder;
1065 nPos = pWindow->mnDX-nBorder;
1066 }
1067 nTPos = rPos.X();
1068 }
1069 long nSplitSize = pWindow->mpMainSet->mnSplitSize-2;
1070 if (pWindow->mbFadeOut)
1071 nSplitSize += SPLITWIN_SPLITSIZEEXLN;
1072 if ( !pWindow->mbBottomRight )
1073 nPos -= nSplitSize;
1074 if ( (nTPos >= nPos) && (nTPos <= nPos+nSplitSize+nBorder) )
1075 {
1076 rMouseOff = nTPos-nPos;
1077 *ppFoundSet = pWindow->mpMainSet.get();
1078 if ( !pWindow->mpMainSet->mvItems.empty() )
1079 rFoundPos = pWindow->mpMainSet->mvItems.size() - 1;
1080 else
1081 rFoundPos = 0;
1082 if ( pWindow->mbHorz )
1083 return SPLIT_VERT | SPLIT_WINDOW;
1084 else
1085 return SPLIT_HORZ | SPLIT_WINDOW;
1086 }
1087 }
1088
1089 return ImplTestSplit( pWindow->mpMainSet.get(), rPos, rMouseOff, ppFoundSet, rFoundPos,
1090 pWindow->mbHorz );
1091 }
1092
ImplDrawSplitTracking(const Point & rPos)1093 void SplitWindow::ImplDrawSplitTracking(const Point& rPos)
1094 {
1095 tools::Rectangle aRect;
1096
1097 if (mnSplitTest & SPLIT_HORZ)
1098 {
1099 aRect.SetTop( maDragRect.Top() );
1100 aRect.SetBottom( maDragRect.Bottom() );
1101 aRect.SetLeft( rPos.X() );
1102 aRect.SetRight( aRect.Left() + mpSplitSet->mnSplitSize - 1 );
1103 if (!(mnWinStyle & WB_NOSPLITDRAW))
1104 aRect.AdjustRight( -1 );
1105 if ((mnSplitTest & SPLIT_WINDOW) && mbFadeOut)
1106 {
1107 aRect.AdjustLeft(SPLITWIN_SPLITSIZEEXLN );
1108 aRect.AdjustRight(SPLITWIN_SPLITSIZEEXLN );
1109 }
1110 }
1111 else
1112 {
1113 aRect.SetLeft( maDragRect.Left() );
1114 aRect.SetRight( maDragRect.Right() );
1115 aRect.SetTop( rPos.Y() );
1116 aRect.SetBottom( aRect.Top() + mpSplitSet->mnSplitSize - 1 );
1117 if (!(mnWinStyle & WB_NOSPLITDRAW))
1118 aRect.AdjustBottom( -1 );
1119 if ((mnSplitTest & SPLIT_WINDOW) && mbFadeOut)
1120 {
1121 aRect.AdjustTop(SPLITWIN_SPLITSIZEEXLN );
1122 aRect.AdjustBottom(SPLITWIN_SPLITSIZEEXLN );
1123 }
1124 }
1125 ShowTracking(aRect, ShowTrackFlags::Split);
1126 }
1127
ImplInit(vcl::Window * pParent,WinBits nStyle)1128 void SplitWindow::ImplInit( vcl::Window* pParent, WinBits nStyle )
1129 {
1130 mpMainSet.reset(new ImplSplitSet());
1131 mpBaseSet = mpMainSet.get();
1132 mpSplitSet = nullptr;
1133 mpLastSizes = nullptr;
1134 mnDX = 0;
1135 mnDY = 0;
1136 mnLeftBorder = 0;
1137 mnTopBorder = 0;
1138 mnRightBorder = 0;
1139 mnBottomBorder = 0;
1140 mnMaxSize = 0;
1141 mnMouseOff = 0;
1142 meAlign = WindowAlign::Top;
1143 mnWinStyle = nStyle;
1144 mnSplitTest = 0;
1145 mnSplitPos = 0;
1146 mnMouseModifier = 0;
1147 mnMStartPos = 0;
1148 mnMSplitPos = 0;
1149 mbDragFull = false;
1150 mbHorz = true;
1151 mbBottomRight = false;
1152 mbCalc = false;
1153 mbRecalc = true;
1154 mbInvalidate = true;
1155 mbFadeIn = false;
1156 mbFadeOut = false;
1157 mbFadeInDown = false;
1158 mbFadeOutDown = false;
1159 mbFadeInPressed = false;
1160 mbFadeOutPressed = false;
1161 mbFadeNoButtonMode = false;
1162
1163 if ( nStyle & WB_NOSPLITDRAW )
1164 {
1165 mpMainSet->mnSplitSize -= 2;
1166 mbInvalidate = false;
1167 }
1168
1169 if ( nStyle & WB_BORDER )
1170 {
1171 ImplCalcBorder( meAlign, mnLeftBorder, mnTopBorder,
1172 mnRightBorder, mnBottomBorder );
1173 }
1174 else
1175 {
1176 mnLeftBorder = 0;
1177 mnTopBorder = 0;
1178 mnRightBorder = 0;
1179 mnBottomBorder = 0;
1180 }
1181
1182 DockingWindow::ImplInit( pParent, (nStyle | WB_CLIPCHILDREN) & ~(WB_BORDER | WB_SIZEABLE) );
1183
1184 ImplInitSettings();
1185 }
1186
ImplInitSettings()1187 void SplitWindow::ImplInitSettings()
1188 {
1189 // If MainSet has a Wallpaper, this is the background,
1190 // otherwise it is the standard colour
1191 if ( mpMainSet->mpWallpaper )
1192 SetBackground( *mpMainSet->mpWallpaper );
1193 else
1194 {
1195 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1196
1197 Color aColor;
1198 if ( IsControlBackground() )
1199 aColor = GetControlBackground();
1200 else if ( Window::GetStyle() & WB_3DLOOK )
1201 aColor = rStyleSettings.GetFaceColor();
1202 else
1203 aColor = rStyleSettings.GetWindowColor();
1204 SetBackground( aColor );
1205 }
1206 }
1207
SplitWindow(vcl::Window * pParent,WinBits nStyle)1208 SplitWindow::SplitWindow( vcl::Window* pParent, WinBits nStyle ) :
1209 DockingWindow( WindowType::SPLITWINDOW )
1210 {
1211 ImplInit( pParent, nStyle );
1212 DockingWindow::SetIdleDebugName( "vcl::SplitWindow maLayoutIdle" );
1213 }
1214
~SplitWindow()1215 SplitWindow::~SplitWindow()
1216 {
1217 disposeOnce();
1218 }
1219
dispose()1220 void SplitWindow::dispose()
1221 {
1222 // delete Sets
1223 mpMainSet.reset();
1224 DockingWindow::dispose();
1225 }
1226
ImplSetWindowSize(long nDelta)1227 void SplitWindow::ImplSetWindowSize( long nDelta )
1228 {
1229 if ( !nDelta )
1230 return;
1231
1232 Size aSize = GetSizePixel();
1233 switch ( meAlign )
1234 {
1235 case WindowAlign::Top:
1236 aSize.AdjustHeight(nDelta );
1237 SetSizePixel( aSize );
1238 break;
1239 case WindowAlign::Bottom:
1240 {
1241 maDragRect.AdjustTop(nDelta );
1242 Point aPos = GetPosPixel();
1243 aPos.AdjustY( -nDelta );
1244 aSize.AdjustHeight(nDelta );
1245 SetPosSizePixel( aPos, aSize );
1246 break;
1247 }
1248 case WindowAlign::Left:
1249 aSize.AdjustWidth(nDelta );
1250 SetSizePixel( aSize );
1251 break;
1252 case WindowAlign::Right:
1253 default:
1254 {
1255 maDragRect.AdjustLeft(nDelta );
1256 Point aPos = GetPosPixel();
1257 aPos.AdjustX( -nDelta );
1258 aSize.AdjustWidth(nDelta );
1259 SetPosSizePixel( aPos, aSize );
1260 break;
1261 }
1262 }
1263
1264 SplitResize();
1265 }
1266
CalcLayoutSizePixel(const Size & aNewSize)1267 Size SplitWindow::CalcLayoutSizePixel( const Size& aNewSize )
1268 {
1269 Size aSize( aNewSize );
1270 long nSplitSize = mpMainSet->mnSplitSize-2;
1271
1272 if (mbFadeOut)
1273 nSplitSize += SPLITWIN_SPLITSIZEEXLN;
1274
1275 // if the window is sizeable and if it does not contain a relative window,
1276 // the size is determined according to MainSet
1277 if ( mnWinStyle & WB_SIZEABLE )
1278 {
1279 long nCalcSize = 0;
1280 std::vector< ImplSplitItem* >::size_type i;
1281
1282 for ( i = 0; i < mpMainSet->mvItems.size(); i++ )
1283 {
1284 if ( mpMainSet->mvItems[i].mnBits & (SplitWindowItemFlags::RelativeSize | SplitWindowItemFlags::PercentSize) )
1285 break;
1286 else
1287 nCalcSize += mpMainSet->mvItems[i].mnSize;
1288 }
1289
1290 if ( i == mpMainSet->mvItems.size() )
1291 {
1292 long nDelta = 0;
1293 long nCurSize;
1294
1295 if ( mbHorz )
1296 nCurSize = aNewSize.Height()-mnTopBorder-mnBottomBorder;
1297 else
1298 nCurSize = aNewSize.Width()-mnLeftBorder-mnRightBorder;
1299 nCurSize -= nSplitSize;
1300 nCurSize -= (mpMainSet->mvItems.size()-1)*mpMainSet->mnSplitSize;
1301
1302 nDelta = nCalcSize-nCurSize;
1303 if ( !nDelta )
1304 return aSize;
1305
1306 switch ( meAlign )
1307 {
1308 case WindowAlign::Top:
1309 aSize.AdjustHeight(nDelta );
1310 break;
1311 case WindowAlign::Bottom:
1312 aSize.AdjustHeight(nDelta );
1313 break;
1314 case WindowAlign::Left:
1315 aSize.AdjustWidth(nDelta );
1316 break;
1317 case WindowAlign::Right:
1318 default:
1319 aSize.AdjustWidth(nDelta );
1320 break;
1321 }
1322 }
1323 }
1324
1325 return aSize;
1326 }
1327
ImplCalcLayout()1328 void SplitWindow::ImplCalcLayout()
1329 {
1330 if ( !mbCalc || !mbRecalc || mpMainSet->mvItems.empty() )
1331 return;
1332
1333 long nSplitSize = mpMainSet->mnSplitSize-2;
1334 if (mbFadeOut)
1335 nSplitSize += SPLITWIN_SPLITSIZEEXLN;
1336
1337 // if the window is sizeable and if it does not contain a relative window,
1338 // the size is determined according to MainSet
1339 if ( mnWinStyle & WB_SIZEABLE )
1340 {
1341 long nCalcSize = 0;
1342 std::vector<ImplSplitItem *>::size_type i;
1343
1344 for ( i = 0; i < mpMainSet->mvItems.size(); i++ )
1345 {
1346 if ( mpMainSet->mvItems[i].mnBits & (SplitWindowItemFlags::RelativeSize | SplitWindowItemFlags::PercentSize) )
1347 break;
1348 else
1349 nCalcSize += mpMainSet->mvItems[i].mnSize;
1350 }
1351
1352 if ( i == mpMainSet->mvItems.size() )
1353 {
1354 long nCurSize;
1355 if ( mbHorz )
1356 nCurSize = mnDY-mnTopBorder-mnBottomBorder;
1357 else
1358 nCurSize = mnDX-mnLeftBorder-mnRightBorder;
1359 nCurSize -= nSplitSize;
1360 nCurSize -= (mpMainSet->mvItems.size()-1)*mpMainSet->mnSplitSize;
1361
1362 mbRecalc = false;
1363 ImplSetWindowSize( nCalcSize-nCurSize );
1364 mbRecalc = true;
1365 }
1366 }
1367
1368 if ( (mnDX <= 0) || (mnDY <= 0) )
1369 return;
1370
1371 // pre-calculate sizes/position
1372 long nL;
1373 long nT;
1374 long nW;
1375 long nH;
1376
1377 if ( mbHorz )
1378 {
1379 if ( mbBottomRight )
1380 nT = mnDY-mnBottomBorder;
1381 else
1382 nT = mnTopBorder;
1383 nL = mnLeftBorder;
1384 }
1385 else
1386 {
1387 if ( mbBottomRight )
1388 nL = mnDX-mnRightBorder;
1389 else
1390 nL = mnLeftBorder;
1391 nT = mnTopBorder;
1392 }
1393 nW = mnDX-mnLeftBorder-mnRightBorder;
1394 nH = mnDY-mnTopBorder-mnBottomBorder;
1395 if ( mnWinStyle & WB_SIZEABLE )
1396 {
1397 if ( mbHorz )
1398 nH -= nSplitSize;
1399 else
1400 nW -= nSplitSize;
1401 }
1402
1403 // calculate sets recursive
1404 ImplCalcSet( mpMainSet.get(), nL, nT, nW, nH, mbHorz, !mbBottomRight );
1405 ImplCalcSet2( this, mpMainSet.get(), false, mbHorz );
1406 mbCalc = false;
1407 }
1408
ImplUpdate()1409 void SplitWindow::ImplUpdate()
1410 {
1411 mbCalc = true;
1412
1413 if ( IsReallyShown() && IsUpdateMode() && mbRecalc )
1414 {
1415 if ( !mpMainSet->mvItems.empty() )
1416 ImplCalcLayout();
1417 else
1418 Invalidate();
1419 }
1420 }
1421
ImplSplitMousePos(Point & rMousePos)1422 void SplitWindow::ImplSplitMousePos( Point& rMousePos )
1423 {
1424 if ( mnSplitTest & SPLIT_HORZ )
1425 {
1426 rMousePos.AdjustX( -mnMouseOff );
1427 if ( rMousePos.X() < maDragRect.Left() )
1428 rMousePos.setX( maDragRect.Left() );
1429 else if ( rMousePos.X()+mpSplitSet->mnSplitSize+1 > maDragRect.Right() )
1430 rMousePos.setX( maDragRect.Right()-mpSplitSet->mnSplitSize+1 );
1431 // store in screen coordinates due to FullDrag
1432 mnMSplitPos = OutputToScreenPixel( rMousePos ).X();
1433 }
1434 else
1435 {
1436 rMousePos.AdjustY( -mnMouseOff );
1437 if ( rMousePos.Y() < maDragRect.Top() )
1438 rMousePos.setY( maDragRect.Top() );
1439 else if ( rMousePos.Y()+mpSplitSet->mnSplitSize+1 > maDragRect.Bottom() )
1440 rMousePos.setY( maDragRect.Bottom()-mpSplitSet->mnSplitSize+1 );
1441 mnMSplitPos = OutputToScreenPixel( rMousePos ).Y();
1442 }
1443 }
1444
ImplGetButtonRect(tools::Rectangle & rRect,bool bTest) const1445 void SplitWindow::ImplGetButtonRect( tools::Rectangle& rRect, bool bTest ) const
1446 {
1447 long nSplitSize = mpMainSet->mnSplitSize-1;
1448 if (mbFadeOut || mbFadeIn)
1449 nSplitSize += SPLITWIN_SPLITSIZEEX;
1450
1451 long nButtonSize = 0;
1452 if ( mbFadeIn )
1453 nButtonSize += SPLITWIN_SPLITSIZEFADE+1;
1454 if ( mbFadeOut )
1455 nButtonSize += SPLITWIN_SPLITSIZEFADE+1;
1456 long nCenterEx = 0;
1457 if ( mbHorz )
1458 nCenterEx += ((mnDX-mnLeftBorder-mnRightBorder)-nButtonSize)/2;
1459 else
1460 nCenterEx += ((mnDY-mnTopBorder-mnBottomBorder)-nButtonSize)/2;
1461 long nEx = 0;
1462 if ( nCenterEx > 0 )
1463 nEx += nCenterEx;
1464
1465 switch ( meAlign )
1466 {
1467 case WindowAlign::Top:
1468 rRect.SetLeft( mnLeftBorder+nEx );
1469 rRect.SetTop( mnDY-mnBottomBorder-nSplitSize );
1470 rRect.SetRight( rRect.Left()+SPLITWIN_SPLITSIZEAUTOHIDE );
1471 rRect.SetBottom( mnDY-mnBottomBorder-1 );
1472 if ( bTest )
1473 {
1474 rRect.AdjustTop( -mnTopBorder );
1475 rRect.AdjustBottom(mnBottomBorder );
1476 }
1477 break;
1478 case WindowAlign::Bottom:
1479 rRect.SetLeft( mnLeftBorder+nEx );
1480 rRect.SetTop( mnTopBorder );
1481 rRect.SetRight( rRect.Left()+SPLITWIN_SPLITSIZEAUTOHIDE );
1482 rRect.SetBottom( mnTopBorder+nSplitSize-1 );
1483 if ( bTest )
1484 {
1485 rRect.AdjustTop( -mnTopBorder );
1486 rRect.AdjustBottom(mnBottomBorder );
1487 }
1488 break;
1489 case WindowAlign::Left:
1490 rRect.SetLeft( mnDX-mnRightBorder-nSplitSize );
1491 rRect.SetTop( mnTopBorder+nEx );
1492 rRect.SetRight( mnDX-mnRightBorder-1 );
1493 rRect.SetBottom( rRect.Top()+SPLITWIN_SPLITSIZEAUTOHIDE );
1494 if ( bTest )
1495 {
1496 rRect.AdjustLeft( -mnLeftBorder );
1497 rRect.AdjustRight(mnRightBorder );
1498 }
1499 break;
1500 case WindowAlign::Right:
1501 rRect.SetLeft( mnLeftBorder );
1502 rRect.SetTop( mnTopBorder+nEx );
1503 rRect.SetRight( mnLeftBorder+nSplitSize-1 );
1504 rRect.SetBottom( rRect.Top()+SPLITWIN_SPLITSIZEAUTOHIDE );
1505 if ( bTest )
1506 {
1507 rRect.AdjustLeft( -mnLeftBorder );
1508 rRect.AdjustRight(mnRightBorder );
1509 }
1510 break;
1511 }
1512 }
1513
ImplGetFadeInRect(tools::Rectangle & rRect,bool bTest) const1514 void SplitWindow::ImplGetFadeInRect( tools::Rectangle& rRect, bool bTest ) const
1515 {
1516 tools::Rectangle aRect;
1517
1518 if ( mbFadeIn )
1519 ImplGetButtonRect( aRect, bTest );
1520
1521 rRect = aRect;
1522 }
1523
ImplGetFadeOutRect(tools::Rectangle & rRect) const1524 void SplitWindow::ImplGetFadeOutRect( tools::Rectangle& rRect ) const
1525 {
1526 tools::Rectangle aRect;
1527
1528 if ( mbFadeOut )
1529 ImplGetButtonRect( aRect, false );
1530
1531 rRect = aRect;
1532 }
1533
ImplDrawGrip(vcl::RenderContext & rRenderContext,const tools::Rectangle & rRect,bool bHorizontal,bool bLeft)1534 void SplitWindow::ImplDrawGrip(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect, bool bHorizontal, bool bLeft)
1535 {
1536 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
1537
1538 Color aColor;
1539
1540 if (rRect.IsInside(GetPointerPosPixel()))
1541 {
1542 vcl::RenderTools::DrawSelectionBackground(rRenderContext, *this, rRect, 2, false, false, false);
1543
1544 aColor = rStyleSettings.GetDarkShadowColor();
1545 }
1546 else
1547 {
1548 rRenderContext.SetLineColor(rStyleSettings.GetDarkShadowColor());
1549 rRenderContext.SetFillColor(rStyleSettings.GetDarkShadowColor());
1550
1551 rRenderContext.DrawRect(rRect);
1552
1553 aColor = rStyleSettings.GetFaceColor();
1554 }
1555
1556 AntialiasingFlags nAA = rRenderContext.GetAntialiasing();
1557 rRenderContext.SetAntialiasing(nAA | AntialiasingFlags::PixelSnapHairline | AntialiasingFlags::EnableB2dDraw);
1558
1559 long nWidth = rRect.getWidth();
1560 long nWidthHalf = nWidth / 2;
1561 long nHeight = rRect.getHeight();
1562 long nHeightHalf = nHeight / 2;
1563
1564 long nLeft = rRect.Left();
1565 long nRight = rRect.Right();
1566 long nTop = rRect.Top();
1567 long nBottom = rRect.Bottom();
1568 long nMargin = 1;
1569
1570 rRenderContext.SetLineColor(aColor);
1571 rRenderContext.SetFillColor(aColor);
1572
1573 tools::Polygon aPoly(3);
1574
1575 if (bHorizontal)
1576 {
1577 long nCenter = nLeft + nWidthHalf;
1578
1579 if (bLeft)
1580 {
1581 aPoly.SetPoint(Point(nCenter, nTop + nMargin), 0);
1582 aPoly.SetPoint(Point(nCenter - nHeightHalf, nBottom - nMargin), 1);
1583 aPoly.SetPoint(Point(nCenter - nHeightHalf, nBottom - nMargin), 2);
1584 }
1585 else
1586 {
1587 aPoly.SetPoint(Point(nCenter, nBottom - nMargin), 0);
1588 aPoly.SetPoint(Point(nCenter - nHeightHalf, nTop + nMargin), 1);
1589 aPoly.SetPoint(Point(nCenter + nHeightHalf, nTop + nMargin), 2);
1590 }
1591 rRenderContext.DrawPolygon(aPoly);
1592 }
1593 else
1594 {
1595 long nCenter = nTop + nHeightHalf;
1596
1597 if (bLeft)
1598 {
1599 aPoly.SetPoint(Point(nLeft + nMargin, nCenter), 0);
1600 aPoly.SetPoint(Point(nRight - nMargin, nCenter - nWidthHalf), 1);
1601 aPoly.SetPoint(Point(nRight - nMargin, nCenter + nWidthHalf), 2);
1602 }
1603 else
1604 {
1605 aPoly.SetPoint(Point(nRight - nMargin, nCenter), 0);
1606 aPoly.SetPoint(Point(nLeft + nMargin, nCenter - nWidthHalf), 1);
1607 aPoly.SetPoint(Point(nLeft + nMargin, nCenter + nWidthHalf), 2);
1608 }
1609 rRenderContext.DrawPolygon(aPoly);
1610 }
1611
1612 rRenderContext.SetAntialiasing(nAA);
1613 }
1614
ImplDrawFadeIn(vcl::RenderContext & rRenderContext)1615 void SplitWindow::ImplDrawFadeIn(vcl::RenderContext& rRenderContext)
1616 {
1617 if (mbFadeIn)
1618 {
1619 tools::Rectangle aTempRect;
1620 ImplGetFadeInRect(aTempRect);
1621
1622 bool bLeft = true;
1623 switch (meAlign)
1624 {
1625 case WindowAlign::Top:
1626 case WindowAlign::Left:
1627 bLeft = false;
1628 break;
1629 case WindowAlign::Bottom:
1630 case WindowAlign::Right:
1631 default:
1632 bLeft = true;
1633 break;
1634 }
1635
1636 ImplDrawGrip(rRenderContext, aTempRect, (meAlign == WindowAlign::Top) || (meAlign == WindowAlign::Bottom), bLeft);
1637 }
1638 }
1639
ImplDrawFadeOut(vcl::RenderContext & rRenderContext)1640 void SplitWindow::ImplDrawFadeOut(vcl::RenderContext& rRenderContext)
1641 {
1642 if (mbFadeOut)
1643 {
1644 tools::Rectangle aTempRect;
1645 ImplGetFadeOutRect(aTempRect);
1646
1647 bool bLeft = true;
1648 switch (meAlign)
1649 {
1650 case WindowAlign::Bottom:
1651 case WindowAlign::Right:
1652 bLeft = false;
1653 break;
1654 case WindowAlign::Top:
1655 case WindowAlign::Left:
1656 default:
1657 bLeft = true;
1658 break;
1659 }
1660
1661 ImplDrawGrip(rRenderContext, aTempRect, (meAlign == WindowAlign::Top) || (meAlign == WindowAlign::Bottom), bLeft);
1662 }
1663 }
1664
ImplStartSplit(const MouseEvent & rMEvt)1665 void SplitWindow::ImplStartSplit( const MouseEvent& rMEvt )
1666 {
1667 Point aMousePosPixel = rMEvt.GetPosPixel();
1668 mnSplitTest = ImplTestSplit( this, aMousePosPixel, mnMouseOff, &mpSplitSet, mnSplitPos );
1669
1670 if ( !mnSplitTest || (mnSplitTest & SPLIT_NOSPLIT) )
1671 return;
1672
1673 ImplSplitItem* pSplitItem;
1674 long nCurMaxSize;
1675 bool bPropSmaller;
1676
1677 mnMouseModifier = rMEvt.GetModifier();
1678 bPropSmaller = (mnMouseModifier & KEY_SHIFT) && (static_cast<sal_uInt16>(mnSplitPos+1) < mpSplitSet->mvItems.size());
1679
1680 // here we can set the maximum size
1681 StartSplit();
1682
1683 if ( mnMaxSize )
1684 nCurMaxSize = mnMaxSize;
1685 else
1686 {
1687 Size aSize = GetParent()->GetOutputSizePixel();
1688 if ( mbHorz )
1689 nCurMaxSize = aSize.Height();
1690 else
1691 nCurMaxSize = aSize.Width();
1692 }
1693
1694 if ( !mpSplitSet->mvItems.empty() )
1695 {
1696 bool bDown = true;
1697 if ( (mpSplitSet == mpMainSet.get()) && mbBottomRight )
1698 bDown = false;
1699
1700 pSplitItem = &mpSplitSet->mvItems[mnSplitPos];
1701 maDragRect.SetLeft( pSplitItem->mnLeft );
1702 maDragRect.SetTop( pSplitItem->mnTop );
1703 maDragRect.SetRight( pSplitItem->mnLeft+pSplitItem->mnWidth-1 );
1704 maDragRect.SetBottom( pSplitItem->mnTop+pSplitItem->mnHeight-1 );
1705
1706 if ( mnSplitTest & SPLIT_HORZ )
1707 {
1708 if ( bDown )
1709 maDragRect.AdjustRight(mpSplitSet->mnSplitSize );
1710 else
1711 maDragRect.AdjustLeft( -(mpSplitSet->mnSplitSize) );
1712 }
1713 else
1714 {
1715 if ( bDown )
1716 maDragRect.AdjustBottom(mpSplitSet->mnSplitSize );
1717 else
1718 maDragRect.AdjustTop( -(mpSplitSet->mnSplitSize) );
1719 }
1720
1721 if ( mnSplitPos )
1722 {
1723 long nTemp = mnSplitPos;
1724 while ( nTemp )
1725 {
1726 pSplitItem = &mpSplitSet->mvItems[nTemp-1];
1727 if ( pSplitItem->mbFixed )
1728 break;
1729 else
1730 {
1731 if ( mnSplitTest & SPLIT_HORZ )
1732 {
1733 if ( bDown )
1734 maDragRect.AdjustLeft( -(pSplitItem->mnPixSize) );
1735 else
1736 maDragRect.AdjustRight(pSplitItem->mnPixSize );
1737 }
1738 else
1739 {
1740 if ( bDown )
1741 maDragRect.AdjustTop( -(pSplitItem->mnPixSize) );
1742 else
1743 maDragRect.AdjustBottom(pSplitItem->mnPixSize );
1744 }
1745 }
1746 nTemp--;
1747 }
1748 }
1749
1750 if ( (mpSplitSet == mpMainSet.get()) && (mnWinStyle & WB_SIZEABLE) && !bPropSmaller )
1751 {
1752 if ( bDown )
1753 {
1754 if ( mbHorz )
1755 maDragRect.AdjustBottom(nCurMaxSize-mnDY-mnTopBorder );
1756 else
1757 maDragRect.AdjustRight(nCurMaxSize-mnDX-mnLeftBorder );
1758 }
1759 else
1760 {
1761 if ( mbHorz )
1762 maDragRect.AdjustTop( -(nCurMaxSize-mnDY-mnBottomBorder) );
1763 else
1764 maDragRect.AdjustLeft( -(nCurMaxSize-mnDX-mnRightBorder) );
1765 }
1766 }
1767 else
1768 {
1769 std::vector<ImplSplitItem *>::size_type nTemp = mnSplitPos+1;
1770 while ( nTemp < mpSplitSet->mvItems.size() )
1771 {
1772 pSplitItem = &mpSplitSet->mvItems[nTemp];
1773 if ( pSplitItem->mbFixed )
1774 break;
1775 else
1776 {
1777 if ( mnSplitTest & SPLIT_HORZ )
1778 {
1779 if ( bDown )
1780 maDragRect.AdjustRight(pSplitItem->mnPixSize );
1781 else
1782 maDragRect.AdjustLeft( -(pSplitItem->mnPixSize) );
1783 }
1784 else
1785 {
1786 if ( bDown )
1787 maDragRect.AdjustBottom(pSplitItem->mnPixSize );
1788 else
1789 maDragRect.AdjustTop( -(pSplitItem->mnPixSize) );
1790 }
1791 }
1792 nTemp++;
1793 }
1794 }
1795 }
1796 else
1797 {
1798 maDragRect.SetLeft( mnLeftBorder );
1799 maDragRect.SetTop( mnTopBorder );
1800 maDragRect.SetRight( mnDX-mnRightBorder-1 );
1801 maDragRect.SetBottom( mnDY-mnBottomBorder-1 );
1802 if ( mbHorz )
1803 {
1804 if ( mbBottomRight )
1805 maDragRect.AdjustTop( -(nCurMaxSize-mnDY-mnBottomBorder) );
1806 else
1807 maDragRect.AdjustBottom(nCurMaxSize-mnDY-mnTopBorder );
1808 }
1809 else
1810 {
1811 if ( mbBottomRight )
1812 maDragRect.AdjustLeft( -(nCurMaxSize-mnDX-mnRightBorder) );
1813 else
1814 maDragRect.AdjustRight(nCurMaxSize-mnDX-mnLeftBorder );
1815 }
1816 }
1817
1818 StartTracking();
1819
1820 mbDragFull = bool(GetSettings().GetStyleSettings().GetDragFullOptions() & DragFullOptions::Split);
1821
1822 ImplSplitMousePos( aMousePosPixel );
1823
1824 if (!mbDragFull)
1825 {
1826 ImplDrawSplitTracking(aMousePosPixel);
1827 }
1828 else
1829 {
1830 std::vector< ImplSplitItem >& rItems = mpSplitSet->mvItems;
1831 sal_uInt16 nItems = mpSplitSet->mvItems.size();
1832 mpLastSizes = new long[nItems*2];
1833 for ( sal_uInt16 i = 0; i < nItems; i++ )
1834 {
1835 mpLastSizes[i*2] = rItems[i].mnSize;
1836 mpLastSizes[i*2+1] = rItems[i].mnPixSize;
1837 }
1838 }
1839 mnMStartPos = mnMSplitPos;
1840
1841 PointerStyle eStyle = PointerStyle::Arrow;
1842 if ( mnSplitTest & SPLIT_HORZ )
1843 eStyle = PointerStyle::HSplit;
1844 else if ( mnSplitTest & SPLIT_VERT )
1845 eStyle = PointerStyle::VSplit;
1846
1847 SetPointer( eStyle );
1848 }
1849
StartSplit()1850 void SplitWindow::StartSplit()
1851 {
1852 }
1853
Split()1854 void SplitWindow::Split()
1855 {
1856 maSplitHdl.Call( this );
1857 }
1858
SplitResize()1859 void SplitWindow::SplitResize()
1860 {
1861 }
1862
FadeIn()1863 void SplitWindow::FadeIn()
1864 {
1865 }
1866
FadeOut()1867 void SplitWindow::FadeOut()
1868 {
1869 }
1870
MouseButtonDown(const MouseEvent & rMEvt)1871 void SplitWindow::MouseButtonDown( const MouseEvent& rMEvt )
1872 {
1873 if ( !rMEvt.IsLeft() || rMEvt.IsMod2() )
1874 {
1875 DockingWindow::MouseButtonDown( rMEvt );
1876 return;
1877 }
1878
1879 Point aMousePosPixel = rMEvt.GetPosPixel();
1880 tools::Rectangle aTestRect;
1881
1882 mbFadeNoButtonMode = false;
1883
1884 ImplGetFadeOutRect( aTestRect );
1885 if ( aTestRect.IsInside( aMousePosPixel ) )
1886 {
1887 mbFadeOutDown = true;
1888 mbFadeOutPressed = true;
1889 Invalidate();
1890 }
1891 else
1892 {
1893 ImplGetFadeInRect( aTestRect, true );
1894 if ( aTestRect.IsInside( aMousePosPixel ) )
1895 {
1896 mbFadeInDown = true;
1897 mbFadeInPressed = true;
1898 Invalidate();
1899 }
1900 else if ( !aTestRect.IsEmpty() && !(mnWinStyle & WB_SIZEABLE) )
1901 {
1902 mbFadeNoButtonMode = true;
1903 FadeIn();
1904 return;
1905 }
1906 }
1907
1908 if ( mbFadeInDown || mbFadeOutDown )
1909 StartTracking();
1910 else
1911 ImplStartSplit( rMEvt );
1912 }
1913
MouseMove(const MouseEvent & rMEvt)1914 void SplitWindow::MouseMove( const MouseEvent& rMEvt )
1915 {
1916 if ( IsTracking() )
1917 return;
1918
1919 Point aPos = rMEvt.GetPosPixel();
1920 long nTemp;
1921 ImplSplitSet* pTempSplitSet;
1922 sal_uInt16 nTempSplitPos;
1923 sal_uInt16 nSplitTest = ImplTestSplit( this, aPos, nTemp, &pTempSplitSet, nTempSplitPos );
1924 PointerStyle eStyle = PointerStyle::Arrow;
1925 tools::Rectangle aFadeInRect;
1926 tools::Rectangle aFadeOutRect;
1927
1928 ImplGetFadeInRect( aFadeInRect );
1929 ImplGetFadeOutRect( aFadeOutRect );
1930 if ( !aFadeInRect.IsInside( aPos ) &&
1931 !aFadeOutRect.IsInside( aPos ) )
1932 {
1933 if ( nSplitTest && !(nSplitTest & SPLIT_NOSPLIT) )
1934 {
1935 if ( nSplitTest & SPLIT_HORZ )
1936 eStyle = PointerStyle::HSplit;
1937 else if ( nSplitTest & SPLIT_VERT )
1938 eStyle = PointerStyle::VSplit;
1939 }
1940 }
1941
1942 SetPointer( eStyle );
1943 }
1944
Tracking(const TrackingEvent & rTEvt)1945 void SplitWindow::Tracking( const TrackingEvent& rTEvt )
1946 {
1947 Point aMousePosPixel = rTEvt.GetMouseEvent().GetPosPixel();
1948
1949 if ( mbFadeInDown )
1950 {
1951 if ( rTEvt.IsTrackingEnded() )
1952 {
1953 mbFadeInDown = false;
1954 if ( mbFadeInPressed )
1955 {
1956 mbFadeInPressed = false;
1957 Invalidate();
1958
1959 if ( !rTEvt.IsTrackingCanceled() )
1960 FadeIn();
1961 }
1962 }
1963 else
1964 {
1965 tools::Rectangle aTestRect;
1966 ImplGetFadeInRect( aTestRect, true );
1967 bool bNewPressed = aTestRect.IsInside( aMousePosPixel );
1968 if ( bNewPressed != mbFadeInPressed )
1969 {
1970 mbFadeInPressed = bNewPressed;
1971 Invalidate();
1972 }
1973 }
1974 }
1975 else if ( mbFadeOutDown )
1976 {
1977 if ( rTEvt.IsTrackingEnded() )
1978 {
1979 mbFadeOutDown = false;
1980 if ( mbFadeOutPressed )
1981 {
1982 mbFadeOutPressed = false;
1983 Invalidate();
1984
1985 if ( !rTEvt.IsTrackingCanceled() )
1986 FadeOut();
1987 }
1988 }
1989 else
1990 {
1991 tools::Rectangle aTestRect;
1992 ImplGetFadeOutRect( aTestRect );
1993 bool bNewPressed = aTestRect.IsInside( aMousePosPixel );
1994 if ( !bNewPressed )
1995 {
1996 mbFadeOutPressed = bNewPressed;
1997 Invalidate();
1998
1999 // We need a mouseevent with a position inside the button for the
2000 // ImplStartSplit function!
2001 MouseEvent aOrgMEvt = rTEvt.GetMouseEvent();
2002 MouseEvent aNewMEvt( aTestRect.Center(), aOrgMEvt.GetClicks(),
2003 aOrgMEvt.GetMode(), aOrgMEvt.GetButtons(),
2004 aOrgMEvt.GetModifier() );
2005
2006 ImplStartSplit( aNewMEvt );
2007 mbFadeOutDown = false;
2008 }
2009 }
2010 }
2011 else
2012 {
2013 ImplSplitMousePos( aMousePosPixel );
2014 bool bSplit = true;
2015 if ( mbDragFull )
2016 {
2017 if ( rTEvt.IsTrackingEnded() )
2018 {
2019 if ( rTEvt.IsTrackingCanceled() )
2020 {
2021 std::vector< ImplSplitItem >& rItems = mpSplitSet->mvItems;
2022 size_t nItems = rItems.size();
2023 for ( size_t i = 0; i < nItems; i++ )
2024 {
2025 rItems[i].mnSize = mpLastSizes[i*2];
2026 rItems[i].mnPixSize = mpLastSizes[i*2+1];
2027 }
2028 ImplUpdate();
2029 Split();
2030 }
2031 bSplit = false;
2032 }
2033 }
2034 else
2035 {
2036 if ( rTEvt.IsTrackingEnded() )
2037 {
2038 HideTracking();
2039 bSplit = !rTEvt.IsTrackingCanceled();
2040 }
2041 else
2042 {
2043 ImplDrawSplitTracking(aMousePosPixel);
2044 bSplit = false;
2045 }
2046 }
2047
2048 if ( bSplit )
2049 {
2050 bool bPropSmaller = (mnMouseModifier & KEY_SHIFT) != 0;
2051 bool bPropGreater = (mnMouseModifier & KEY_MOD1) != 0;
2052 long nDelta = mnMSplitPos-mnMStartPos;
2053
2054 if ( (mnSplitTest & SPLIT_WINDOW) && mpMainSet->mvItems.empty() )
2055 {
2056 if ( (mpSplitSet == mpMainSet.get()) && mbBottomRight )
2057 nDelta *= -1;
2058 ImplSetWindowSize( nDelta );
2059 }
2060 else
2061 {
2062 long nNewSize = mpSplitSet->mvItems[mnSplitPos].mnPixSize;
2063 if ( (mpSplitSet == mpMainSet.get()) && mbBottomRight )
2064 nNewSize -= nDelta;
2065 else
2066 nNewSize += nDelta;
2067 SplitItem( mpSplitSet->mvItems[mnSplitPos].mnId, nNewSize,
2068 bPropSmaller, bPropGreater );
2069 }
2070
2071 Split();
2072
2073 if ( mbDragFull )
2074 {
2075 Update();
2076 mnMStartPos = mnMSplitPos;
2077 }
2078 }
2079
2080 if ( rTEvt.IsTrackingEnded() )
2081 {
2082 delete [] mpLastSizes;
2083 mpLastSizes = nullptr;
2084 mpSplitSet = nullptr;
2085 mnMouseOff = 0;
2086 mnMStartPos = 0;
2087 mnMSplitPos = 0;
2088 mnMouseModifier = 0;
2089 mnSplitTest = 0;
2090 mnSplitPos = 0;
2091 }
2092 }
2093 }
2094
PreNotify(NotifyEvent & rNEvt)2095 bool SplitWindow::PreNotify( NotifyEvent& rNEvt )
2096 {
2097 const MouseEvent* pMouseEvt = nullptr;
2098
2099 if( (rNEvt.GetType() == MouseNotifyEvent::MOUSEMOVE) && (pMouseEvt = rNEvt.GetMouseEvent()) != nullptr )
2100 {
2101 if( !pMouseEvt->GetButtons() && !pMouseEvt->IsSynthetic() && !pMouseEvt->IsModifierChanged() )
2102 {
2103 // trigger redraw if mouse over state has changed
2104 tools::Rectangle aFadeInRect;
2105 tools::Rectangle aFadeOutRect;
2106 ImplGetFadeInRect( aFadeInRect );
2107 ImplGetFadeOutRect( aFadeOutRect );
2108
2109 if ( aFadeInRect.IsInside( GetPointerPosPixel() ) != aFadeInRect.IsInside( GetLastPointerPosPixel() ) )
2110 Invalidate( aFadeInRect );
2111 if ( aFadeOutRect.IsInside( GetPointerPosPixel() ) != aFadeOutRect.IsInside( GetLastPointerPosPixel() ) )
2112 Invalidate( aFadeOutRect );
2113
2114 if( pMouseEvt->IsLeaveWindow() || pMouseEvt->IsEnterWindow() )
2115 {
2116 Invalidate( aFadeInRect );
2117 Invalidate( aFadeOutRect );
2118 }
2119 }
2120 }
2121 return Window::PreNotify( rNEvt );
2122 }
2123
Paint(vcl::RenderContext & rRenderContext,const tools::Rectangle &)2124 void SplitWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
2125 {
2126 if (mnWinStyle & WB_BORDER)
2127 ImplDrawBorder(rRenderContext);
2128
2129 ImplDrawBorderLine(rRenderContext);
2130 ImplDrawFadeOut(rRenderContext);
2131 ImplDrawFadeIn(rRenderContext);
2132
2133 // draw FrameSet-backgrounds
2134 ImplDrawBack(rRenderContext, mpMainSet.get());
2135
2136 // draw splitter
2137 if (!(mnWinStyle & WB_NOSPLITDRAW))
2138 {
2139 ImplDrawSplit(rRenderContext, mpMainSet.get(), mbHorz, !mbBottomRight);
2140 }
2141 }
2142
Resize()2143 void SplitWindow::Resize()
2144 {
2145 Size aSize = GetOutputSizePixel();
2146 mnDX = aSize.Width();
2147 mnDY = aSize.Height();
2148
2149 ImplUpdate();
2150 Invalidate();
2151 }
2152
RequestHelp(const HelpEvent & rHEvt)2153 void SplitWindow::RequestHelp( const HelpEvent& rHEvt )
2154 {
2155 // no keyboard help for splitwin
2156 if ( rHEvt.GetMode() & (HelpEventMode::BALLOON | HelpEventMode::QUICK) && !rHEvt.KeyboardActivated() )
2157 {
2158 Point aMousePosPixel = ScreenToOutputPixel( rHEvt.GetMousePosPixel() );
2159 tools::Rectangle aHelpRect;
2160 const char* pHelpResId = nullptr;
2161
2162 ImplGetFadeInRect( aHelpRect, true );
2163 if ( aHelpRect.IsInside( aMousePosPixel ) )
2164 pHelpResId = SV_HELPTEXT_FADEIN;
2165 else
2166 {
2167 ImplGetFadeOutRect( aHelpRect );
2168 if ( aHelpRect.IsInside( aMousePosPixel ) )
2169 pHelpResId = SV_HELPTEXT_FADEOUT;
2170 }
2171
2172 // get rectangle
2173 if (pHelpResId)
2174 {
2175 Point aPt = OutputToScreenPixel( aHelpRect.TopLeft() );
2176 aHelpRect.SetLeft( aPt.X() );
2177 aHelpRect.SetTop( aPt.Y() );
2178 aPt = OutputToScreenPixel( aHelpRect.BottomRight() );
2179 aHelpRect.SetRight( aPt.X() );
2180 aHelpRect.SetBottom( aPt.Y() );
2181
2182 // get and draw text
2183 OUString aStr = VclResId(pHelpResId);
2184 if ( rHEvt.GetMode() & HelpEventMode::BALLOON )
2185 Help::ShowBalloon( this, aHelpRect.Center(), aHelpRect, aStr );
2186 else
2187 Help::ShowQuickHelp( this, aHelpRect, aStr );
2188 return;
2189 }
2190 }
2191
2192 DockingWindow::RequestHelp( rHEvt );
2193 }
2194
StateChanged(StateChangedType nType)2195 void SplitWindow::StateChanged( StateChangedType nType )
2196 {
2197 switch ( nType )
2198 {
2199 case StateChangedType::InitShow:
2200 if ( IsUpdateMode() )
2201 ImplCalcLayout();
2202 break;
2203 case StateChangedType::UpdateMode:
2204 if ( IsUpdateMode() && IsReallyShown() )
2205 ImplCalcLayout();
2206 break;
2207 case StateChangedType::ControlBackground:
2208 ImplInitSettings();
2209 Invalidate();
2210 break;
2211 default:;
2212 }
2213
2214 DockingWindow::StateChanged( nType );
2215 }
2216
DataChanged(const DataChangedEvent & rDCEvt)2217 void SplitWindow::DataChanged( const DataChangedEvent& rDCEvt )
2218 {
2219 if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
2220 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
2221 {
2222 ImplInitSettings();
2223 Invalidate();
2224 }
2225 else
2226 DockingWindow::DataChanged( rDCEvt );
2227 }
2228
InsertItem(sal_uInt16 nId,vcl::Window * pWindow,long nSize,sal_uInt16 nPos,sal_uInt16 nIntoSetId,SplitWindowItemFlags nBits)2229 void SplitWindow::InsertItem( sal_uInt16 nId, vcl::Window* pWindow, long nSize,
2230 sal_uInt16 nPos, sal_uInt16 nIntoSetId,
2231 SplitWindowItemFlags nBits )
2232 {
2233 #ifdef DBG_UTIL
2234 sal_uInt16 nDbgDummy;
2235 SAL_WARN_IF( ImplFindItem( mpMainSet.get(), nId, nDbgDummy ), "vcl", "SplitWindow::InsertItem() - Id already exists" );
2236 #endif
2237
2238 // Size has to be at least 1.
2239 if ( nSize < 1 )
2240 nSize = 1;
2241
2242 ImplSplitSet* pSet = ImplFindSet( mpMainSet.get(), nIntoSetId );
2243 #ifdef DBG_UTIL
2244 SAL_WARN_IF( !pSet, "vcl", "SplitWindow::InsertItem() - Set not exists" );
2245 #endif
2246 if(!pSet)
2247 {
2248 return;
2249 }
2250
2251 // Don't insert further than the end
2252 if ( nPos > pSet->mvItems.size() )
2253 nPos = pSet->mvItems.size();
2254
2255 // Insert in set
2256 pSet->mvItems.emplace( pSet->mvItems.begin() + nPos );
2257
2258 // init new item
2259 ImplSplitItem & aItem = pSet->mvItems[nPos];
2260 aItem.mnSize = nSize;
2261 aItem.mnPixSize = 0;
2262 aItem.mnId = nId;
2263 aItem.mnBits = nBits;
2264 aItem.mnMinSize=-1;
2265 aItem.mnMaxSize=-1;
2266
2267 if ( pWindow )
2268 {
2269 // New VclPtr reference
2270 aItem.mpWindow = pWindow;
2271 aItem.mpOrgParent = pWindow->GetParent();
2272
2273 // Attach window to SplitWindow.
2274 pWindow->Hide();
2275 pWindow->SetParent( this );
2276 }
2277 else
2278 {
2279 ImplSplitSet * pNewSet = new ImplSplitSet();
2280 pNewSet->mnId = nId;
2281 pNewSet->mnSplitSize = pSet->mnSplitSize;
2282
2283 aItem.mpSet.reset(pNewSet);
2284 }
2285
2286 pSet->mbCalcPix = true;
2287
2288 ImplUpdate();
2289 }
2290
InsertItem(sal_uInt16 nId,long nSize,sal_uInt16 nPos,sal_uInt16 nIntoSetId,SplitWindowItemFlags nBits)2291 void SplitWindow::InsertItem( sal_uInt16 nId, long nSize,
2292 sal_uInt16 nPos, sal_uInt16 nIntoSetId,
2293 SplitWindowItemFlags nBits )
2294 {
2295 InsertItem( nId, nullptr, nSize, nPos, nIntoSetId, nBits );
2296 }
2297
RemoveItem(sal_uInt16 nId)2298 void SplitWindow::RemoveItem( sal_uInt16 nId )
2299 {
2300 #ifdef DBG_UTIL
2301 sal_uInt16 nDbgDummy;
2302 SAL_WARN_IF( !ImplFindItem( mpMainSet.get(), nId, nDbgDummy ), "vcl", "SplitWindow::RemoveItem() - Id not found" );
2303 #endif
2304
2305 // search set
2306 sal_uInt16 nPos;
2307 ImplSplitSet* pSet = ImplFindItem( mpMainSet.get(), nId, nPos );
2308
2309 if (!pSet)
2310 return;
2311
2312 ImplSplitItem* pItem = &pSet->mvItems[nPos];
2313 VclPtr<vcl::Window> pWindow = pItem->mpWindow;
2314 VclPtr<vcl::Window> pOrgParent = pItem->mpOrgParent;
2315
2316 // delete set if required
2317 if ( !pWindow )
2318 pItem->mpSet.reset();
2319
2320 // remove item
2321 pSet->mbCalcPix = true;
2322 pSet->mvItems.erase( pSet->mvItems.begin() + nPos );
2323
2324 ImplUpdate();
2325
2326 // to have the least amounts of paints delete window only here
2327 if ( pWindow )
2328 {
2329 // restore window
2330 pWindow->Hide();
2331 pWindow->SetParent( pOrgParent );
2332 }
2333
2334 // Clear and delete
2335 pWindow.clear();
2336 pOrgParent.clear();
2337 }
2338
Clear()2339 void SplitWindow::Clear()
2340 {
2341 // create Main-Set again
2342 mpMainSet.reset(new ImplSplitSet());
2343 if ( mnWinStyle & WB_NOSPLITDRAW )
2344 mpMainSet->mnSplitSize -= 2;
2345 mpBaseSet = mpMainSet.get();
2346
2347 // and invalidate again
2348 ImplUpdate();
2349 }
2350
SplitItem(sal_uInt16 nId,long nNewSize,bool bPropSmall,bool bPropGreat)2351 void SplitWindow::SplitItem( sal_uInt16 nId, long nNewSize,
2352 bool bPropSmall, bool bPropGreat )
2353 {
2354 sal_uInt16 nPos;
2355 ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
2356
2357 if (!pSet)
2358 return;
2359
2360 size_t nItems = pSet->mvItems.size();
2361 std::vector< ImplSplitItem >& rItems = pSet->mvItems;
2362
2363 // When there is an explicit minimum or maximum size then move nNewSize
2364 // into that range (when it is not yet already in it.)
2365 nNewSize = ValidateSize(nNewSize, rItems[nPos]);
2366
2367 if ( mbCalc )
2368 {
2369 rItems[nPos].mnSize = nNewSize;
2370 return;
2371 }
2372
2373 long nDelta = nNewSize-rItems[nPos].mnPixSize;
2374 if ( !nDelta )
2375 return;
2376
2377 // calculate area, which could be affected by splitting
2378 sal_uInt16 nMin = 0;
2379 sal_uInt16 nMax = nItems;
2380 for (size_t i = 0; i < nItems; ++i)
2381 {
2382 if ( rItems[i].mbFixed )
2383 {
2384 if ( i < nPos )
2385 nMin = i+1;
2386 else
2387 nMax = i;
2388 }
2389 }
2390
2391 // treat TopSet different if the window is sizeable
2392 bool bSmall = true;
2393 bool bGreat = true;
2394 if ( (pSet == mpMainSet.get()) && (mnWinStyle & WB_SIZEABLE) )
2395 {
2396 if ( nPos < pSet->mvItems.size()-1 )
2397 {
2398 if ( !((bPropSmall && bPropGreat) ||
2399 ((nDelta > 0) && bPropSmall) ||
2400 ((nDelta < 0) && bPropGreat)) )
2401 {
2402 if ( nDelta < 0 )
2403 bGreat = false;
2404 else
2405 bSmall = false;
2406 }
2407 }
2408 else
2409 {
2410 if ( nDelta < 0 )
2411 bGreat = false;
2412 else
2413 bSmall = false;
2414 }
2415 }
2416 else if ( nPos >= nMax )
2417 {
2418 bSmall = false;
2419 bGreat = false;
2420 }
2421 else if ( nPos && (nPos >= pSet->mvItems.size()-1) )
2422 {
2423 nPos--;
2424 nDelta *= -1;
2425 bool bTemp = bPropSmall;
2426 bPropSmall = bPropGreat;
2427 bPropGreat = bTemp;
2428 }
2429
2430 sal_uInt16 n;
2431 // now splitt the windows
2432 if ( nDelta < 0 )
2433 {
2434 if ( bGreat )
2435 {
2436 if ( bPropGreat )
2437 {
2438 long nTempDelta = nDelta;
2439 do
2440 {
2441 n = nPos+1;
2442 do
2443 {
2444 if ( nTempDelta )
2445 {
2446 rItems[n].mnPixSize++;
2447 nTempDelta++;
2448 }
2449 n++;
2450 }
2451 while ( n < nMax );
2452 }
2453 while ( nTempDelta );
2454 }
2455 else
2456 rItems[nPos+1].mnPixSize -= nDelta;
2457 }
2458
2459 if ( bSmall )
2460 {
2461 if ( bPropSmall )
2462 {
2463 do
2464 {
2465 n = nPos+1;
2466 do
2467 {
2468 if ( nDelta && rItems[n-1].mnPixSize )
2469 {
2470 rItems[n-1].mnPixSize--;
2471 nDelta++;
2472 }
2473
2474 n--;
2475 }
2476 while ( n > nMin );
2477 }
2478 while ( nDelta );
2479 }
2480 else
2481 {
2482 n = nPos+1;
2483 do
2484 {
2485 if ( rItems[n-1].mnPixSize+nDelta < 0 )
2486 {
2487 nDelta += rItems[n-1].mnPixSize;
2488 rItems[n-1].mnPixSize = 0;
2489 }
2490 else
2491 {
2492 rItems[n-1].mnPixSize += nDelta;
2493 break;
2494 }
2495 n--;
2496 }
2497 while ( n > nMin );
2498 }
2499 }
2500 }
2501 else
2502 {
2503 if ( bGreat )
2504 {
2505 if ( bPropGreat )
2506 {
2507 long nTempDelta = nDelta;
2508 do
2509 {
2510 n = nPos+1;
2511 do
2512 {
2513 if ( nTempDelta )
2514 {
2515 rItems[n-1].mnPixSize++;
2516 nTempDelta--;
2517 }
2518 n--;
2519 }
2520 while ( n > nMin );
2521 }
2522 while ( nTempDelta );
2523 }
2524 else
2525 rItems[nPos].mnPixSize += nDelta;
2526 }
2527
2528 if ( bSmall )
2529 {
2530 if ( bPropSmall )
2531 {
2532 do
2533 {
2534 n = nPos+1;
2535 do
2536 {
2537 if ( nDelta && rItems[n].mnPixSize )
2538 {
2539 rItems[n].mnPixSize--;
2540 nDelta--;
2541 }
2542
2543 n++;
2544 }
2545 while ( n < nMax );
2546 }
2547 while ( nDelta );
2548 }
2549 else
2550 {
2551 n = nPos+1;
2552 do
2553 {
2554 if ( rItems[n].mnPixSize-nDelta < 0 )
2555 {
2556 nDelta -= rItems[n].mnPixSize;
2557 rItems[n].mnPixSize = 0;
2558 }
2559 else
2560 {
2561 rItems[n].mnPixSize -= nDelta;
2562 break;
2563 }
2564 n++;
2565 }
2566 while ( n < nMax );
2567 }
2568 }
2569 }
2570
2571 // update original sizes
2572 ImplCalcLogSize( rItems, nItems );
2573
2574 ImplUpdate();
2575 }
2576
SetItemSize(sal_uInt16 nId,long nNewSize)2577 void SplitWindow::SetItemSize( sal_uInt16 nId, long nNewSize )
2578 {
2579 sal_uInt16 nPos;
2580 ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
2581 ImplSplitItem* pItem;
2582
2583 if ( !pSet )
2584 return;
2585
2586 // check if size is changed
2587 pItem = &pSet->mvItems[nPos];
2588 if ( pItem->mnSize != nNewSize )
2589 {
2590 // set new size and re-calculate
2591 pItem->mnSize = nNewSize;
2592 pSet->mbCalcPix = true;
2593 ImplUpdate();
2594 }
2595 }
2596
GetItemSize(sal_uInt16 nId) const2597 long SplitWindow::GetItemSize( sal_uInt16 nId ) const
2598 {
2599 sal_uInt16 nPos;
2600 ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
2601
2602 if ( pSet )
2603 return pSet->mvItems[nPos].mnSize;
2604 else
2605 return 0;
2606 }
2607
GetItemSize(sal_uInt16 nId,SplitWindowItemFlags nBits) const2608 long SplitWindow::GetItemSize( sal_uInt16 nId, SplitWindowItemFlags nBits ) const
2609 {
2610 sal_uInt16 nPos;
2611 ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
2612
2613 if ( pSet )
2614 {
2615 if ( nBits == pSet->mvItems[nPos].mnBits )
2616 return pSet->mvItems[nPos].mnSize;
2617 else
2618 {
2619 const_cast<SplitWindow*>(this)->ImplCalcLayout();
2620
2621 long nRelSize = 0;
2622 long nPerSize = 0;
2623 size_t nItems;
2624 SplitWindowItemFlags nTempBits;
2625 nItems = pSet->mvItems.size();
2626 std::vector< ImplSplitItem >& rItems = pSet->mvItems;
2627 for ( size_t i = 0; i < nItems; i++ )
2628 {
2629 if ( i == nPos )
2630 nTempBits = nBits;
2631 else
2632 nTempBits = rItems[i].mnBits;
2633 if ( nTempBits & SplitWindowItemFlags::RelativeSize )
2634 nRelSize += rItems[i].mnPixSize;
2635 else if ( nTempBits & SplitWindowItemFlags::PercentSize )
2636 nPerSize += rItems[i].mnPixSize;
2637 }
2638 nPerSize += nRelSize;
2639 if ( nBits & SplitWindowItemFlags::RelativeSize )
2640 {
2641 if ( nRelSize )
2642 return (rItems[nPos].mnPixSize+(nRelSize/2))/nRelSize;
2643 else
2644 return 1;
2645 }
2646 else if ( nBits & SplitWindowItemFlags::PercentSize )
2647 {
2648 if ( nPerSize )
2649 return (rItems[nPos].mnPixSize*100)/nPerSize;
2650 else
2651 return 1;
2652 }
2653 else
2654 return rItems[nPos].mnPixSize;
2655 }
2656 }
2657 else
2658 return 0;
2659 }
2660
SetItemSizeRange(sal_uInt16 nId,const Range & rRange)2661 void SplitWindow::SetItemSizeRange (sal_uInt16 nId, const Range& rRange)
2662 {
2663 sal_uInt16 nPos;
2664 ImplSplitSet* pSet = ImplFindItem(mpBaseSet, nId, nPos);
2665
2666 if (pSet != nullptr)
2667 {
2668 pSet->mvItems[nPos].mnMinSize = rRange.Min();
2669 pSet->mvItems[nPos].mnMaxSize = rRange.Max();
2670 }
2671 }
2672
GetSet(sal_uInt16 nId) const2673 sal_uInt16 SplitWindow::GetSet( sal_uInt16 nId ) const
2674 {
2675 sal_uInt16 nPos;
2676 ImplSplitSet* pSet = ImplFindItem( mpBaseSet, nId, nPos );
2677
2678 if ( pSet )
2679 return pSet->mnId;
2680 else
2681 return 0;
2682 }
2683
IsItemValid(sal_uInt16 nId) const2684 bool SplitWindow::IsItemValid( sal_uInt16 nId ) const
2685 {
2686 sal_uInt16 nPos;
2687 ImplSplitSet* pSet = mpBaseSet ? ImplFindItem(mpBaseSet, nId, nPos) : nullptr;
2688
2689 return pSet != nullptr;
2690 }
2691
GetItemId(vcl::Window * pWindow) const2692 sal_uInt16 SplitWindow::GetItemId( vcl::Window* pWindow ) const
2693 {
2694 return ImplFindItem( mpBaseSet, pWindow );
2695 }
2696
GetItemId(const Point & rPos) const2697 sal_uInt16 SplitWindow::GetItemId( const Point& rPos ) const
2698 {
2699 return ImplFindItem( mpBaseSet, rPos, mbHorz, !mbBottomRight );
2700 }
2701
GetItemPos(sal_uInt16 nId,sal_uInt16 nSetId) const2702 sal_uInt16 SplitWindow::GetItemPos( sal_uInt16 nId, sal_uInt16 nSetId ) const
2703 {
2704 ImplSplitSet* pSet = ImplFindSet( mpBaseSet, nSetId );
2705 sal_uInt16 nPos = SPLITWINDOW_ITEM_NOTFOUND;
2706
2707 if ( pSet )
2708 {
2709 for ( size_t i = 0; i < pSet->mvItems.size(); i++ )
2710 {
2711 if ( pSet->mvItems[i].mnId == nId )
2712 {
2713 nPos = i;
2714 break;
2715 }
2716 }
2717 }
2718
2719 return nPos;
2720 }
2721
GetItemId(sal_uInt16 nPos) const2722 sal_uInt16 SplitWindow::GetItemId( sal_uInt16 nPos ) const
2723 {
2724 ImplSplitSet* pSet = ImplFindSet( mpBaseSet, 0/*nSetId*/ );
2725 if ( pSet && (nPos < pSet->mvItems.size()) )
2726 return pSet->mvItems[nPos].mnId;
2727 else
2728 return 0;
2729 }
2730
GetItemCount(sal_uInt16 nSetId) const2731 sal_uInt16 SplitWindow::GetItemCount( sal_uInt16 nSetId ) const
2732 {
2733 ImplSplitSet* pSet = ImplFindSet( mpBaseSet, nSetId );
2734 if ( pSet )
2735 return pSet->mvItems.size();
2736 else
2737 return 0;
2738 }
2739
ImplNewAlign()2740 void SplitWindow::ImplNewAlign()
2741 {
2742 switch ( meAlign )
2743 {
2744 case WindowAlign::Top:
2745 mbHorz = true;
2746 mbBottomRight = false;
2747 break;
2748 case WindowAlign::Bottom:
2749 mbHorz = true;
2750 mbBottomRight = true;
2751 break;
2752 case WindowAlign::Left:
2753 mbHorz = false;
2754 mbBottomRight = false;
2755 break;
2756 case WindowAlign::Right:
2757 mbHorz = false;
2758 mbBottomRight = true;
2759 break;
2760 }
2761
2762 if ( mnWinStyle & WB_BORDER )
2763 {
2764 ImplCalcBorder( meAlign, mnLeftBorder, mnTopBorder,
2765 mnRightBorder, mnBottomBorder );
2766 }
2767
2768 if ( IsReallyVisible() && IsUpdateMode() )
2769 Invalidate();
2770 ImplUpdate();
2771 }
2772
SetAlign(WindowAlign eNewAlign)2773 void SplitWindow::SetAlign( WindowAlign eNewAlign )
2774 {
2775 if ( meAlign != eNewAlign )
2776 {
2777 meAlign = eNewAlign;
2778 ImplNewAlign();
2779 }
2780 }
2781
ShowFadeInHideButton()2782 void SplitWindow::ShowFadeInHideButton()
2783 {
2784 mbFadeIn = true;
2785 ImplUpdate();
2786 }
2787
ShowFadeOutButton()2788 void SplitWindow::ShowFadeOutButton()
2789 {
2790 mbFadeOut = true;
2791 ImplUpdate();
2792 }
2793
GetFadeInSize() const2794 long SplitWindow::GetFadeInSize() const
2795 {
2796 long n = 0;
2797
2798 if ( mbHorz )
2799 n = mnTopBorder+mnBottomBorder;
2800 else
2801 n = mnLeftBorder+mnRightBorder;
2802
2803 return n+SPLITWIN_SPLITSIZE+SPLITWIN_SPLITSIZEEX-2;
2804 }
2805
2806 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2807