1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #include "precompiled_sd.hxx"
25
26 #include "view/SlsLayouter.hxx"
27 #include "model/SlideSorterModel.hxx"
28 #include "model/SlsPageDescriptor.hxx"
29 #include "Window.hxx"
30 #include <rtl/math.hxx>
31 #include <basegfx/numeric/ftools.hxx>
32
33 namespace {
RoundToInt(const double nValue)34 sal_Int32 RoundToInt (const double nValue)
35 {
36 return sal_Int32(::rtl::math::round(nValue));
37 }
38 }
39
40
41 namespace sd { namespace slidesorter { namespace view {
42
43 class Layouter::Implementation
44 {
45 public:
46 SharedSdWindow mpWindow;
47 sal_Int32 mnRequestedLeftBorder;
48 sal_Int32 mnRequestedRightBorder;
49 sal_Int32 mnRequestedTopBorder;
50 sal_Int32 mnRequestedBottomBorder;
51 sal_Int32 mnLeftBorder;
52 sal_Int32 mnRightBorder;
53 sal_Int32 mnTopBorder;
54 sal_Int32 mnBottomBorder;
55 sal_Int32 mnVerticalGap;
56 sal_Int32 mnHorizontalGap;
57 Size maMinimalSize;
58 Size maPreferredSize;
59 Size maMaximalSize;
60 sal_Int32 mnMinimalColumnCount;
61 sal_Int32 mnMaximalColumnCount;
62 sal_Int32 mnPageCount;
63 sal_Int32 mnColumnCount;
64 sal_Int32 mnRowCount;
65 /// The maximum number of columns. Can only be larger than the current
66 /// number of columns when there are not enough pages to fill all
67 /// available columns.
68 sal_Int32 mnMaxColumnCount;
69 /// The maximum number of rows. Can only be larger than the current
70 /// number of rows when there are not enough pages to fill all available
71 /// rows.
72 sal_Int32 mnMaxRowCount;
73 Size maPageObjectSize;
74 ::boost::shared_ptr<PageObjectLayouter> mpPageObjectLayouter;
75 ::boost::shared_ptr<view::Theme> mpTheme;
76
77 /** Specify how the gap between two page objects is associated with the
78 page objects.
79 */
80 enum GapMembership {
81 GM_NONE, // Gap is not associated with any page object.
82 GM_PREVIOUS, // The whole gap is associated with the previous page
83 // object (left or above the gap.)
84 GM_BOTH, // Half of the gap is associated with previous, half
85 // with the next page object.
86 GM_NEXT, // The whole gap is associated with the next page
87 // object (right or below the gap.)
88 GM_PAGE_BORDER
89 };
90
91 static Implementation* Create (
92 const Implementation& rImplementation,
93 const Layouter::Orientation eOrientation);
94
95 virtual Layouter::Orientation GetOrientation (void) const = 0;
96
97 bool Rearrange (
98 const Size& rWindowSize,
99 const Size& rPreviewModelSize,
100 const sal_uInt32 nPageCount);
101
102 /** Calculate the row that the point with the given vertical coordinate
103 is over. The horizontal component is ignored.
104 @param nYPosition
105 Vertical position in model coordinates.
106 @param bIncludeBordersAndGaps
107 When this flag is <TRUE/> then the area of borders and gaps are
108 interpreted as belonging to one of the rows.
109 @param eGapMembership
110 Specifies to what row the gap areas belong. Here GM_NONE
111 corresponds to bIncludeBordersAndGaps being <FALSE/>. When
112 GM_BOTH is given then the upper half is associated to the row
113 above and the lower half to the row below. Values of
114 GM_PREVIOUS and GM_NEXT associate the whole gap area with the
115 row above or below respectively.
116 */
117 sal_Int32 GetRowAtPosition (
118 sal_Int32 nYPosition,
119 bool bIncludeBordersAndGaps,
120 GapMembership eGapMembership = GM_NONE) const;
121
122 /** Calculate the column that the point with the given horizontal
123 coordinate is over. The vertical component is ignored.
124 @param nXPosition
125 Horizontal position in model coordinates.
126 @param bIncludeBordersAndGaps
127 When this flag is <TRUE/> then the area of borders and gaps are
128 interpreted as belonging to one of the columns.
129 @param eGapMembership
130 Specifies to what column the gap areas belong.
131 */
132 sal_Int32 GetColumnAtPosition (
133 sal_Int32 nXPosition,
134 bool bIncludeBordersAndGaps,
135 GapMembership eGapMembership = GM_NONE) const;
136
137 /** This method is typically called from GetRowAtPosition() and
138 GetColumnAtPosition() to handle a position that lies inside the gap
139 between two adjacent rows or columns.
140 @param nDistanceIntoGap
141 Vertical distance from the bottom of the upper row down into the
142 gap or or horizontal distance from the right edge right into the
143 gap.
144 @param eGapMemberhship
145 This value decides what areas in the gap belong to which (or no)
146 row or column.
147 @param nIndex
148 The row index of the upper row or the column index of the left
149 column.
150 @param nGap
151 Width or height of the gap in model coordinates between the
152 page borders.
153 @return
154 Returns either the index of the upper row (as given as nRow), the
155 index of the lower row (nRow+1) or -1 to indicate that the
156 position belongs to no row.
157 */
158 sal_Int32 ResolvePositionInGap (
159 sal_Int32 nDistanceIntoGap,
160 GapMembership eGapMembership,
161 sal_Int32 nIndex,
162 sal_Int32 nGap) const;
163
164 /** Calculate the logical part of the insert position, i.e. the page
165 after which to insert.
166 */
167 virtual void CalculateLogicalInsertPosition (
168 const Point& rModelPosition,
169 InsertPosition& rPosition) const = 0;
170
171 /** Calculate the geometrical part of the insert position, i.e. the
172 location of where to display the insertion indicator and the
173 distances about which the leading and trailing pages have to be
174 moved to make room for the indicator.
175 */
176 void CalculateGeometricPosition (
177 InsertPosition& rPosition,
178 const Size& rIndicatorSize,
179 const bool bIsVertical,
180 model::SlideSorterModel& rModel) const;
181
182 /** Return the bounding box of the preview or, when selected, of the page
183 object. Thus, it returns something like a visual bounding box.
184 */
185 Rectangle GetInnerBoundingBox (
186 model::SlideSorterModel& rModel,
187 const sal_Int32 nIndex) const;
188
189 Range GetValidHorizontalSizeRange (void) const;
190 Range GetValidVerticalSizeRange (void) const;
191
192 Range GetRangeOfVisiblePageObjects (const Rectangle& aVisibleArea) const;
193 sal_Int32 GetIndex (
194 const sal_Int32 nRow,
195 const sal_Int32 nColumn,
196 const bool bClampToValidRange) const;
197
198 Rectangle GetPageObjectBox (
199 const sal_Int32 nIndex,
200 const bool bIncludeBorderAndGap = false) const;
201
202 Rectangle GetPageObjectBox (
203 const sal_Int32 nRow,
204 const sal_Int32 nColumn) const;
205
206 Rectangle AddBorderAndGap (
207 const Rectangle& rBoundingBox,
208 const sal_Int32 nRow,
209 const sal_Int32 nColumn) const;
210
211 Rectangle GetTotalBoundingBox (void) const;
212
213 virtual ~Implementation (void);
214
215 protected:
216 Implementation (
217 const SharedSdWindow& rpWindow,
218 const ::boost::shared_ptr<view::Theme>& rpTheme);
219 Implementation (const Implementation& rImplementation);
220
221 virtual void CalculateRowAndColumnCount (const Size& rWindowSize) = 0;
222 virtual void CalculateMaxRowAndColumnCount (const Size& rWindowSize) = 0;
223 virtual Size CalculateTargetSize (
224 const Size& rWindowSize,
225 const Size& rPreviewModelSize) const = 0;
226 Size GetTargetSize (
227 const Size& rWindowSize,
228 const Size& rPreviewModelSize,
229 const bool bCalculateWidth,
230 const bool bCalculateHeight) const;
231 void CalculateVerticalLogicalInsertPosition (
232 const Point& rModelPosition,
233 InsertPosition& rPosition) const;
234 };
235
236
237 /** The vertical layouter has one column and as many rows as there are
238 pages.
239 */
240 class VerticalImplementation : public Layouter::Implementation
241 {
242 public:
243 VerticalImplementation (
244 const SharedSdWindow& rpWindow,
245 const ::boost::shared_ptr<view::Theme>& rpTheme);
246 VerticalImplementation (const Implementation& rImplementation);
247
248 virtual Layouter::Orientation GetOrientation (void) const;
249
250 void CalculateLogicalInsertPosition (
251 const Point& rModelPosition,
252 InsertPosition& rPosition) const;
253
254 protected:
255 virtual void CalculateRowAndColumnCount (const Size& rWindowSize);
256 virtual void CalculateMaxRowAndColumnCount (const Size& rWindowSize);
257 virtual Size CalculateTargetSize (
258 const Size& rWindowSize,
259 const Size& rPreviewModelSize) const;
260 };
261
262
263 /** The horizontal layouter has one row and as many columns as there are
264 pages.
265 */
266 class HorizontalImplementation : public Layouter::Implementation
267 {
268 public:
269 HorizontalImplementation (
270 const SharedSdWindow& rpWindow,
271 const ::boost::shared_ptr<view::Theme>& rpTheme);
272 HorizontalImplementation (const Implementation& rImplementation);
273
274 virtual Layouter::Orientation GetOrientation (void) const;
275
276 void CalculateLogicalInsertPosition (
277 const Point& rModelPosition,
278 InsertPosition& rPosition) const;
279
280 protected:
281 virtual void CalculateRowAndColumnCount (const Size& rWindowSize);
282 virtual void CalculateMaxRowAndColumnCount (const Size& rWindowSize);
283 virtual Size CalculateTargetSize (
284 const Size& rWindowSize,
285 const Size& rPreviewModelSize) const;
286 };
287
288
289 /** The number of columns of the grid layouter is defined via a control in
290 the slide sorter tool bar. The number of rows is calculated from the
291 number of columns and the number of pages.
292 */
293 class GridImplementation : public Layouter::Implementation
294 {
295 public:
296 GridImplementation (
297 const SharedSdWindow& rpWindow,
298 const ::boost::shared_ptr<view::Theme>& rpTheme);
299 GridImplementation (const Implementation& rImplementation);
300
301 virtual Layouter::Orientation GetOrientation (void) const;
302
303 void CalculateLogicalInsertPosition (
304 const Point& rModelPosition,
305 InsertPosition& rPosition) const;
306
307 protected:
308 virtual void CalculateRowAndColumnCount (const Size& rWindowSize);
309 virtual void CalculateMaxRowAndColumnCount (const Size& rWindowSize);
310 virtual Size CalculateTargetSize (
311 const Size& rWindowSize,
312 const Size& rPreviewModelSize) const;
313 };
314
315
316
317
318 //===== Layouter ==============================================================
319
Layouter(const SharedSdWindow & rpWindow,const::boost::shared_ptr<Theme> & rpTheme)320 Layouter::Layouter (
321 const SharedSdWindow& rpWindow,
322 const ::boost::shared_ptr<Theme>& rpTheme)
323 : mpImplementation(new GridImplementation(rpWindow, rpTheme)),
324 mpWindow(rpWindow)
325 {
326 }
327
328
329
330
~Layouter(void)331 Layouter::~Layouter (void)
332 {
333 }
334
335
336
337
GetPageObjectLayouter(void) const338 ::boost::shared_ptr<PageObjectLayouter> Layouter::GetPageObjectLayouter (void) const
339 {
340 return mpImplementation->mpPageObjectLayouter;
341 }
342
343
344
345
SetBorders(sal_Int32 nLeftBorder,sal_Int32 nRightBorder,sal_Int32 nTopBorder,sal_Int32 nBottomBorder)346 void Layouter::SetBorders (
347 sal_Int32 nLeftBorder,
348 sal_Int32 nRightBorder,
349 sal_Int32 nTopBorder,
350 sal_Int32 nBottomBorder)
351 {
352 if (nLeftBorder >= 0)
353 mpImplementation->mnRequestedLeftBorder = nLeftBorder;
354 if (nRightBorder >= 0)
355 mpImplementation->mnRequestedRightBorder = nRightBorder;
356 if (nTopBorder >= 0)
357 mpImplementation->mnRequestedTopBorder = nTopBorder;
358 if (nBottomBorder >= 0)
359 mpImplementation->mnRequestedBottomBorder = nBottomBorder;
360 }
361
362
363
364
SetColumnCount(sal_Int32 nMinimalColumnCount,sal_Int32 nMaximalColumnCount)365 void Layouter::SetColumnCount (
366 sal_Int32 nMinimalColumnCount,
367 sal_Int32 nMaximalColumnCount)
368 {
369 if (nMinimalColumnCount <= nMaximalColumnCount)
370 {
371 mpImplementation->mnMinimalColumnCount = nMinimalColumnCount;
372 mpImplementation->mnMaximalColumnCount = nMaximalColumnCount;
373 }
374 }
375
376
377
378
Rearrange(const Orientation eOrientation,const Size & rWindowSize,const Size & rPageSize,const sal_uInt32 nPageCount)379 bool Layouter::Rearrange (
380 const Orientation eOrientation,
381 const Size& rWindowSize,
382 const Size& rPageSize,
383 const sal_uInt32 nPageCount)
384 {
385 OSL_ASSERT(mpWindow);
386
387 if (eOrientation != mpImplementation->GetOrientation())
388 mpImplementation.reset(Implementation::Create(*mpImplementation, eOrientation));
389
390 return mpImplementation->Rearrange(rWindowSize, rPageSize, nPageCount);
391 }
392
393
394
395
_SetZoom(double nZoomFactor)396 void Layouter::_SetZoom (double nZoomFactor)
397 {
398 _SetZoom(Fraction(nZoomFactor));
399 }
400
401
402
403
_SetZoom(Fraction nZoomFactor)404 void Layouter::_SetZoom (Fraction nZoomFactor)
405 {
406 OSL_ASSERT(mpWindow);
407
408 MapMode aMapMode (mpWindow->GetMapMode());
409 aMapMode.SetScaleX (nZoomFactor);
410 aMapMode.SetScaleY (nZoomFactor);
411 mpWindow->SetMapMode (aMapMode);
412 }
413
414
415
416
GetColumnCount(void) const417 sal_Int32 Layouter::GetColumnCount (void) const
418 {
419 return mpImplementation->mnColumnCount;
420 }
421
422
423
424
GetRowCount(void) const425 sal_Int32 Layouter::GetRowCount (void) const
426 {
427 return mpImplementation->mnRowCount;
428 }
429
430
431
432
GetRow(const sal_Int32 nIndex) const433 sal_Int32 Layouter::GetRow (const sal_Int32 nIndex) const
434 {
435 return nIndex / mpImplementation->mnColumnCount;
436 }
437
438
439
440
GetColumn(const sal_Int32 nIndex) const441 sal_Int32 Layouter::GetColumn (const sal_Int32 nIndex) const
442 {
443 return nIndex % mpImplementation->mnColumnCount;
444 }
445
446
447
448
GetIndex(const sal_Int32 nRow,const sal_Int32 nColumn) const449 sal_Int32 Layouter::GetIndex (const sal_Int32 nRow, const sal_Int32 nColumn) const
450 {
451 return mpImplementation->GetIndex(nRow,nColumn,true);
452 }
453
454
455
456
GetPageObjectSize(void) const457 Size Layouter::GetPageObjectSize (void) const
458 {
459 return mpImplementation->maPageObjectSize;
460 }
461
462
463
464
GetPageObjectBox(const sal_Int32 nIndex,const bool bIncludeBorderAndGap) const465 Rectangle Layouter::GetPageObjectBox (
466 const sal_Int32 nIndex,
467 const bool bIncludeBorderAndGap) const
468 {
469 return mpImplementation->GetPageObjectBox(nIndex, bIncludeBorderAndGap);
470 }
471
472
473
474
GetTotalBoundingBox(void) const475 Rectangle Layouter::GetTotalBoundingBox (void) const
476 {
477 return mpImplementation->GetTotalBoundingBox();
478 }
479
480
481
482
GetInsertPosition(const Point & rModelPosition,const Size & rIndicatorSize,model::SlideSorterModel & rModel) const483 InsertPosition Layouter::GetInsertPosition (
484 const Point& rModelPosition,
485 const Size& rIndicatorSize,
486 model::SlideSorterModel& rModel) const
487 {
488 InsertPosition aPosition;
489 mpImplementation->CalculateLogicalInsertPosition(
490 rModelPosition,
491 aPosition);
492 mpImplementation->CalculateGeometricPosition(
493 aPosition,
494 rIndicatorSize,
495 GetColumnCount()==1,
496 rModel);
497 return aPosition;
498 }
499
500
501
502
GetValidHorizontalSizeRange(void) const503 Range Layouter::GetValidHorizontalSizeRange (void) const
504 {
505 return mpImplementation->GetValidHorizontalSizeRange();
506 }
507
508
509
510
GetValidVerticalSizeRange(void) const511 Range Layouter::GetValidVerticalSizeRange (void) const
512 {
513 return mpImplementation->GetValidVerticalSizeRange();
514 }
515
516
517
518
GetRangeOfVisiblePageObjects(const Rectangle & aVisibleArea) const519 Range Layouter::GetRangeOfVisiblePageObjects (const Rectangle& aVisibleArea) const
520 {
521 return mpImplementation->GetRangeOfVisiblePageObjects(aVisibleArea);
522 }
523
524
525
526
GetIndexAtPoint(const Point & rPosition,const bool bIncludePageBorders,const bool bClampToValidRange) const527 sal_Int32 Layouter::GetIndexAtPoint (
528 const Point& rPosition,
529 const bool bIncludePageBorders,
530 const bool bClampToValidRange) const
531 {
532 const sal_Int32 nRow (
533 mpImplementation->GetRowAtPosition (
534 rPosition.Y(),
535 bIncludePageBorders,
536 bIncludePageBorders ? Implementation::GM_PAGE_BORDER : Implementation::GM_NONE));
537 const sal_Int32 nColumn (
538 mpImplementation->GetColumnAtPosition (
539 rPosition.X(),
540 bIncludePageBorders,
541 bIncludePageBorders ? Implementation::GM_PAGE_BORDER : Implementation::GM_NONE));
542
543 return mpImplementation->GetIndex(nRow,nColumn,bClampToValidRange);
544 }
545
546
547
548
549 //===== Layouter::Implementation ==============================================
550
Create(const Implementation & rImplementation,const Layouter::Orientation eOrientation)551 Layouter::Implementation* Layouter::Implementation::Create (
552 const Implementation& rImplementation,
553 const Layouter::Orientation eOrientation)
554 {
555 switch (eOrientation)
556 {
557 case HORIZONTAL: return new HorizontalImplementation(rImplementation);
558 case VERTICAL: return new VerticalImplementation(rImplementation);
559 case GRID:
560 default: return new GridImplementation(rImplementation);
561 }
562 }
563
564
565
566
Implementation(const SharedSdWindow & rpWindow,const::boost::shared_ptr<view::Theme> & rpTheme)567 Layouter::Implementation::Implementation (
568 const SharedSdWindow& rpWindow,
569 const ::boost::shared_ptr<view::Theme>& rpTheme)
570 : mpWindow(rpWindow),
571 mnRequestedLeftBorder(5),
572 mnRequestedRightBorder(5),
573 mnRequestedTopBorder(5),
574 mnRequestedBottomBorder(5),
575 mnLeftBorder(5),
576 mnRightBorder(5),
577 mnTopBorder(5),
578 mnBottomBorder(5),
579 mnVerticalGap (10 - 2*rpTheme->GetIntegerValue(Theme::Integer_FocusIndicatorWidth)),
580 mnHorizontalGap(10 - 2*rpTheme->GetIntegerValue(Theme::Integer_FocusIndicatorWidth)),
581 maMinimalSize(132,98),
582 maPreferredSize(200,150),
583 maMaximalSize(300,200),
584 mnMinimalColumnCount(1),
585 mnMaximalColumnCount(15),
586 mnPageCount(0),
587 mnColumnCount(1),
588 mnRowCount(0),
589 mnMaxColumnCount(0),
590 mnMaxRowCount(0),
591 maPageObjectSize(1,1),
592 mpPageObjectLayouter(),
593 mpTheme(rpTheme)
594 {
595 }
596
597
598
599
Implementation(const Implementation & rImplementation)600 Layouter::Implementation::Implementation (const Implementation& rImplementation)
601 : mpWindow(rImplementation.mpWindow),
602 mnRequestedLeftBorder(rImplementation.mnRequestedLeftBorder),
603 mnRequestedRightBorder(rImplementation.mnRequestedRightBorder),
604 mnRequestedTopBorder(rImplementation.mnRequestedTopBorder),
605 mnRequestedBottomBorder(rImplementation.mnRequestedBottomBorder),
606 mnLeftBorder(rImplementation.mnLeftBorder),
607 mnRightBorder(rImplementation.mnRightBorder),
608 mnTopBorder(rImplementation.mnTopBorder),
609 mnBottomBorder(rImplementation.mnBottomBorder),
610 mnVerticalGap(rImplementation.mnVerticalGap),
611 mnHorizontalGap(rImplementation.mnHorizontalGap),
612 maMinimalSize(rImplementation.maMinimalSize),
613 maPreferredSize(rImplementation.maPreferredSize),
614 maMaximalSize(rImplementation.maMaximalSize),
615 mnMinimalColumnCount(rImplementation.mnMinimalColumnCount),
616 mnMaximalColumnCount(rImplementation.mnMaximalColumnCount),
617 mnPageCount(rImplementation.mnPageCount),
618 mnColumnCount(rImplementation.mnColumnCount),
619 mnRowCount(rImplementation.mnRowCount),
620 mnMaxColumnCount(rImplementation.mnMaxColumnCount),
621 mnMaxRowCount(rImplementation.mnMaxRowCount),
622 maPageObjectSize(rImplementation.maPageObjectSize),
623 mpPageObjectLayouter(),
624 mpTheme(rImplementation.mpTheme)
625 {
626 }
627
628
629
630
~Implementation(void)631 Layouter::Implementation::~Implementation (void)
632 {
633 }
634
635
636
637
Rearrange(const Size & rWindowSize,const Size & rPreviewModelSize,const sal_uInt32 nPageCount)638 bool Layouter::Implementation::Rearrange (
639 const Size& rWindowSize,
640 const Size& rPreviewModelSize,
641 const sal_uInt32 nPageCount)
642 {
643 mnPageCount = nPageCount;
644
645 // Return early when the window or the model have not yet been initialized.
646 if (rWindowSize.Width()<=0 || rWindowSize.Height()<=0)
647 return false;
648 if (rPreviewModelSize.Width()<=0 || rPreviewModelSize.Height()<=0)
649 return false;
650
651 CalculateRowAndColumnCount(rWindowSize);
652
653 // Update the border values.
654 mnLeftBorder = mnRequestedLeftBorder;
655 mnTopBorder = mnRequestedTopBorder;
656 mnRightBorder = mnRequestedRightBorder;
657 mnBottomBorder = mnRequestedBottomBorder;
658 if (mnColumnCount > 1)
659 {
660 int nMinimumBorderWidth = mnHorizontalGap/2;
661 if (mnLeftBorder < nMinimumBorderWidth)
662 mnLeftBorder = nMinimumBorderWidth;
663 if (mnRightBorder < nMinimumBorderWidth)
664 mnRightBorder = nMinimumBorderWidth;
665 }
666 else
667 {
668 int nMinimumBorderHeight = mnVerticalGap/2;
669 if (mnTopBorder < nMinimumBorderHeight)
670 mnTopBorder = nMinimumBorderHeight;
671 if (mnBottomBorder < nMinimumBorderHeight)
672 mnBottomBorder = nMinimumBorderHeight;
673 }
674
675 mpPageObjectLayouter.reset(
676 new PageObjectLayouter(
677 mpTheme,
678 CalculateTargetSize(rWindowSize, rPreviewModelSize),
679 rPreviewModelSize,
680 mpWindow,
681 mnPageCount));
682 maPageObjectSize = mpPageObjectLayouter->GetSize(
683 PageObjectLayouter::FocusIndicator,
684 PageObjectLayouter::WindowCoordinateSystem);
685
686 CalculateMaxRowAndColumnCount(rWindowSize);
687
688 return true;
689 }
690
691
692
693
GetRowAtPosition(sal_Int32 nYPosition,bool bIncludeBordersAndGaps,GapMembership eGapMembership) const694 sal_Int32 Layouter::Implementation::GetRowAtPosition (
695 sal_Int32 nYPosition,
696 bool bIncludeBordersAndGaps,
697 GapMembership eGapMembership) const
698 {
699 sal_Int32 nRow = -1;
700
701 const sal_Int32 nY = nYPosition - mnTopBorder;
702 if (nY >= 0)
703 {
704 // Vertical distance from one row to the next.
705 const sal_Int32 nRowOffset (maPageObjectSize.Height() + mnVerticalGap);
706
707 // Calculate row consisting of page objects and gap below.
708 nRow = nY / nRowOffset;
709
710 const sal_Int32 nDistanceIntoGap ((nY - nRow*nRowOffset) - maPageObjectSize.Height());
711 // When inside the gap below then nYPosition is not over a page
712 // object.
713 if (nDistanceIntoGap > 0)
714 nRow = ResolvePositionInGap (
715 nDistanceIntoGap,
716 eGapMembership,
717 nRow,
718 mnVerticalGap);
719 }
720 else if (bIncludeBordersAndGaps)
721 {
722 // We are in the top border area. Set nRow to the first row when
723 // the top border shall be considered to belong to the first row.
724 nRow = 0;
725 }
726
727 return nRow;
728 }
729
730
731
732
GetColumnAtPosition(sal_Int32 nXPosition,bool bIncludeBordersAndGaps,GapMembership eGapMembership) const733 sal_Int32 Layouter::Implementation::GetColumnAtPosition (
734 sal_Int32 nXPosition,
735 bool bIncludeBordersAndGaps,
736 GapMembership eGapMembership) const
737 {
738 sal_Int32 nColumn = -1;
739
740 sal_Int32 nX = nXPosition - mnLeftBorder;
741 if (nX >= 0)
742 {
743 // Horizontal distance from one column to the next.
744 const sal_Int32 nColumnOffset (maPageObjectSize.Width() + mnHorizontalGap);
745
746 // Calculate row consisting of page objects and gap below.
747 nColumn = nX / nColumnOffset;
748 if (nColumn < 0)
749 nColumn = 0;
750 else if (nColumn >= mnColumnCount)
751 nColumn = mnColumnCount-1;
752
753 const sal_Int32 nDistanceIntoGap ((nX - nColumn*nColumnOffset) - maPageObjectSize.Width());
754 // When inside the gap at the right then nXPosition is not over a
755 // page object.
756 if (nDistanceIntoGap > 0)
757 nColumn = ResolvePositionInGap (
758 nDistanceIntoGap,
759 eGapMembership,
760 nColumn,
761 mnHorizontalGap);
762 }
763 else if (bIncludeBordersAndGaps)
764 {
765 // We are in the left border area. Set nColumn to the first column
766 // when the left border shall be considered to belong to the first
767 // column.
768 nColumn = 0;
769 }
770 return nColumn;
771 }
772
773
774
775
ResolvePositionInGap(sal_Int32 nDistanceIntoGap,GapMembership eGapMembership,sal_Int32 nIndex,sal_Int32 nGap) const776 sal_Int32 Layouter::Implementation::ResolvePositionInGap (
777 sal_Int32 nDistanceIntoGap,
778 GapMembership eGapMembership,
779 sal_Int32 nIndex,
780 sal_Int32 nGap) const
781 {
782 switch (eGapMembership)
783 {
784 case GM_NONE:
785 // The gap is no man's land.
786 nIndex = -1;
787 break;
788
789 case GM_BOTH:
790 {
791 // The lower half of the gap belongs to the next row or column.
792 sal_Int32 nFirstHalfGapWidth = nGap / 2;
793 if (nDistanceIntoGap > nFirstHalfGapWidth)
794 nIndex ++;
795 break;
796 }
797
798 case GM_PREVIOUS:
799 // Row or column already at correct value.
800 break;
801
802 case GM_NEXT:
803 // The complete gap belongs to the next row or column.
804 nIndex ++;
805 break;
806
807 case GM_PAGE_BORDER:
808 if (nDistanceIntoGap > 0)
809 {
810 if (nDistanceIntoGap > nGap)
811 {
812 // Inside the border of the next row or column.
813 nIndex ++;
814 }
815 else
816 {
817 // Inside the gap between the page borders.
818 nIndex = -1;
819 }
820 }
821 break;
822
823 default:
824 nIndex = -1;
825 }
826
827 return nIndex;
828 }
829
830
831
832
CalculateGeometricPosition(InsertPosition & rPosition,const Size & rIndicatorSize,const bool bIsVertical,model::SlideSorterModel & rModel) const833 void Layouter::Implementation::CalculateGeometricPosition (
834 InsertPosition& rPosition,
835 const Size& rIndicatorSize,
836 const bool bIsVertical,
837 model::SlideSorterModel& rModel) const
838 {
839 // 1. Determine right/bottom of the leading page and the left/top of the
840 // trailing page object and how to distribute the missing space.
841 sal_Int32 nLeadingLocation (0);
842 sal_Int32 nTrailingLocation (0);
843 bool bIsLeadingFixed (false);
844 bool bIsTrailingFixed (false);
845 sal_Int32 nSecondaryLocation (0);
846 const sal_Int32 nIndex (rPosition.GetIndex());
847
848 if (rPosition.IsAtRunStart())
849 {
850 // Place indicator at the top of the column.
851 const Rectangle aOuterBox (GetPageObjectBox(nIndex));
852 const Rectangle aInnerBox (GetInnerBoundingBox(rModel, nIndex));
853 if (bIsVertical)
854 {
855 nLeadingLocation = aOuterBox.Top();
856 nTrailingLocation = aInnerBox.Top();
857 nSecondaryLocation = aInnerBox.Center().X();
858 }
859 else
860 {
861 nLeadingLocation = aOuterBox.Left();
862 nTrailingLocation = aInnerBox.Left();
863 nSecondaryLocation = aInnerBox.Center().Y();
864 }
865 bIsLeadingFixed = true;
866 }
867 else if (rPosition.IsAtRunEnd())
868 {
869 // Place indicator at the bottom/right of the column/row.
870
871 const Rectangle aOuterBox (GetPageObjectBox(nIndex-1));
872 const Rectangle aInnerBox (GetInnerBoundingBox(rModel, nIndex-1));
873 if (bIsVertical)
874 {
875 nLeadingLocation = aInnerBox.Bottom();
876 nTrailingLocation = aOuterBox.Bottom();
877 nSecondaryLocation = aInnerBox.Center().X();
878 }
879 else
880 {
881 nLeadingLocation = aInnerBox.Right();
882 nTrailingLocation = aOuterBox.Right();
883 nSecondaryLocation = aInnerBox.Center().Y();
884 }
885 bIsTrailingFixed = true;
886 if ( ! rPosition.IsExtraSpaceNeeded())
887 bIsLeadingFixed = true;
888 }
889 else
890 {
891 // Place indicator between two rows/columns.
892 const Rectangle aBox1 (GetInnerBoundingBox(rModel, nIndex-1));
893 const Rectangle aBox2 (GetInnerBoundingBox(rModel, nIndex));
894 if (bIsVertical)
895 {
896 nLeadingLocation = aBox1.Bottom();
897 nTrailingLocation = aBox2.Top();
898 nSecondaryLocation = (aBox1.Center().X() + aBox2.Center().X()) / 2;
899 }
900 else
901 {
902 nLeadingLocation = aBox1.Right();
903 nTrailingLocation = aBox2.Left();
904 nSecondaryLocation = (aBox1.Center().Y() + aBox2.Center().Y()) / 2;
905 }
906 }
907
908 // 2. Calculate the location of the insert indicator and the offsets of
909 // leading and trailing pages.
910 const sal_Int32 nAvailableSpace (nTrailingLocation - nLeadingLocation);
911 const sal_Int32 nRequiredSpace (bIsVertical ? rIndicatorSize.Height():rIndicatorSize.Width());
912 const sal_Int32 nMissingSpace (::std::max(sal_Int32(0), nRequiredSpace - nAvailableSpace));
913 sal_Int32 nPrimaryLocation (0);
914 sal_Int32 nLeadingOffset (0);
915 sal_Int32 nTrailingOffset (0);
916 if (bIsLeadingFixed)
917 {
918 nPrimaryLocation = nLeadingLocation + nRequiredSpace/2;
919 if ( ! bIsTrailingFixed)
920 nTrailingOffset = nMissingSpace;
921 }
922 else if (bIsTrailingFixed)
923 {
924 nPrimaryLocation = nTrailingLocation - nRequiredSpace/2;
925 nLeadingOffset = -nMissingSpace;
926 }
927 else
928 {
929 nPrimaryLocation = (nLeadingLocation + nTrailingLocation) /2;
930 nLeadingOffset = -nMissingSpace/2;
931 nTrailingOffset = nMissingSpace + nLeadingOffset;
932 }
933
934 if (bIsVertical)
935 {
936 rPosition.SetGeometricalPosition(
937 Point(nSecondaryLocation, nPrimaryLocation),
938 Point(0, nLeadingOffset),
939 Point(0, nTrailingOffset));
940 }
941 else
942 {
943 rPosition.SetGeometricalPosition(
944 Point(nPrimaryLocation, nSecondaryLocation),
945 Point(nLeadingOffset, 0),
946 Point(nTrailingOffset, 0));
947 }
948 }
949
950
951
952
GetInnerBoundingBox(model::SlideSorterModel & rModel,const sal_Int32 nIndex) const953 Rectangle Layouter::Implementation::GetInnerBoundingBox (
954 model::SlideSorterModel& rModel,
955 const sal_Int32 nIndex) const
956 {
957 model::SharedPageDescriptor pDescriptor (rModel.GetPageDescriptor(nIndex));
958 if ( ! pDescriptor)
959 return Rectangle();
960
961 const Point aLocation (pDescriptor->GetLocation(true));
962 if (pDescriptor->HasState(model::PageDescriptor::ST_Selected))
963 return mpPageObjectLayouter->GetBoundingBox(
964 aLocation,
965 PageObjectLayouter::PageObject,
966 PageObjectLayouter::ModelCoordinateSystem);
967 else
968 return mpPageObjectLayouter->GetBoundingBox(
969 aLocation,
970 PageObjectLayouter::Preview,
971 PageObjectLayouter::ModelCoordinateSystem);
972 }
973
974
975
976
GetValidHorizontalSizeRange(void) const977 Range Layouter::Implementation::GetValidHorizontalSizeRange (void) const
978 {
979 return Range(
980 mnLeftBorder + maMinimalSize.Width() + mnRightBorder,
981 mnLeftBorder + maMaximalSize.Width() + mnRightBorder);
982 }
983
984
985
986
GetValidVerticalSizeRange(void) const987 Range Layouter::Implementation::GetValidVerticalSizeRange (void) const
988 {
989 return Range(
990 mnTopBorder + maMinimalSize.Height() + mnBottomBorder,
991 mnTopBorder + maMaximalSize.Height() + mnBottomBorder);
992 }
993
994
995
996
GetRangeOfVisiblePageObjects(const Rectangle & aVisibleArea) const997 Range Layouter::Implementation::GetRangeOfVisiblePageObjects (const Rectangle& aVisibleArea) const
998 {
999 const sal_Int32 nRow0 (GetRowAtPosition(aVisibleArea.Top(), true, GM_NEXT));
1000 const sal_Int32 nCol0 (GetColumnAtPosition(aVisibleArea.Left(),true, GM_NEXT));
1001 const sal_Int32 nRow1 (GetRowAtPosition(aVisibleArea.Bottom(), true, GM_PREVIOUS));
1002 const sal_Int32 nCol1 (GetColumnAtPosition(aVisibleArea.Right(), true, GM_PREVIOUS));
1003
1004 // When start and end lie in different rows then the range may include
1005 // slides outside (left or right of) the given area.
1006 return Range(GetIndex(nRow0,nCol0,true), GetIndex(nRow1,nCol1,true));
1007 }
1008
1009
1010
1011
GetTargetSize(const Size & rWindowSize,const Size & rPreviewModelSize,const bool bCalculateWidth,const bool bCalculateHeight) const1012 Size Layouter::Implementation::GetTargetSize (
1013 const Size& rWindowSize,
1014 const Size& rPreviewModelSize,
1015 const bool bCalculateWidth,
1016 const bool bCalculateHeight) const
1017 {
1018 (void)rPreviewModelSize;
1019
1020 if (mnColumnCount<=0 || mnRowCount<=0)
1021 return maPreferredSize;
1022 if ( ! (bCalculateWidth || bCalculateHeight))
1023 {
1024 OSL_ASSERT(bCalculateWidth || bCalculateHeight);
1025 return maPreferredSize;
1026 }
1027
1028 // Calculate the width of each page object.
1029 Size aTargetSize (0,0);
1030 if (bCalculateWidth)
1031 aTargetSize.setWidth(
1032 (rWindowSize.Width() - mnLeftBorder - mnRightBorder
1033 - (mnColumnCount-1) * mnHorizontalGap)
1034 / mnColumnCount);
1035 else if (bCalculateHeight)
1036 aTargetSize.setHeight(
1037 (rWindowSize.Height() - mnTopBorder - mnBottomBorder
1038 - (mnRowCount-1) * mnVerticalGap)
1039 / mnRowCount);
1040
1041 if (bCalculateWidth)
1042 {
1043 if (aTargetSize.Width() < maMinimalSize.Width())
1044 aTargetSize.setWidth(maMinimalSize.Width());
1045 else if (aTargetSize.Width() > maMaximalSize.Width())
1046 aTargetSize.setWidth(maMaximalSize.Width());
1047 }
1048 else if (bCalculateHeight)
1049 {
1050 if (aTargetSize.Height() < maMinimalSize.Height())
1051 aTargetSize.setHeight(maMinimalSize.Height());
1052 else if (aTargetSize.Height() > maMaximalSize.Height())
1053 aTargetSize.setHeight(maMaximalSize.Height());
1054 }
1055
1056 return aTargetSize;
1057 }
1058
1059
1060
1061
GetIndex(const sal_Int32 nRow,const sal_Int32 nColumn,const bool bClampToValidRange) const1062 sal_Int32 Layouter::Implementation::GetIndex (
1063 const sal_Int32 nRow,
1064 const sal_Int32 nColumn,
1065 const bool bClampToValidRange) const
1066 {
1067 if (nRow >= 0 && nColumn >= 0)
1068 {
1069 const sal_Int32 nIndex (nRow * mnColumnCount + nColumn);
1070 if (nIndex >= mnPageCount)
1071 if (bClampToValidRange)
1072 return mnPageCount-1;
1073 else
1074 return -1;
1075 else
1076 return nIndex;
1077 }
1078 else if (bClampToValidRange)
1079 return 0;
1080 else
1081 return -1;
1082 }
1083
1084
1085
1086
GetPageObjectBox(const sal_Int32 nIndex,const bool bIncludeBorderAndGap) const1087 Rectangle Layouter::Implementation::GetPageObjectBox (
1088 const sal_Int32 nIndex,
1089 const bool bIncludeBorderAndGap) const
1090 {
1091 const sal_Int32 nRow (nIndex / mnColumnCount);
1092 const sal_Int32 nColumn (nIndex % mnColumnCount);
1093
1094 const Rectangle aBoundingBox (GetPageObjectBox(nRow,nColumn));
1095 if (bIncludeBorderAndGap)
1096 return AddBorderAndGap(aBoundingBox, nRow, nColumn);
1097 else
1098 return aBoundingBox;
1099 }
1100
1101
1102
1103
GetPageObjectBox(const sal_Int32 nRow,const sal_Int32 nColumn) const1104 Rectangle Layouter::Implementation::GetPageObjectBox (
1105 const sal_Int32 nRow,
1106 const sal_Int32 nColumn) const
1107 {
1108 return Rectangle(
1109 Point (mnLeftBorder
1110 + nColumn * maPageObjectSize.Width()
1111 + (nColumn>0 ? nColumn : 0) * mnHorizontalGap,
1112 mnTopBorder
1113 + nRow * maPageObjectSize.Height()
1114 + (nRow>0 ? nRow : 0) * mnVerticalGap),
1115 maPageObjectSize);
1116 }
1117
1118
1119
1120
1121
AddBorderAndGap(const Rectangle & rBoundingBox,const sal_Int32 nRow,const sal_Int32 nColumn) const1122 Rectangle Layouter::Implementation::AddBorderAndGap (
1123 const Rectangle& rBoundingBox,
1124 const sal_Int32 nRow,
1125 const sal_Int32 nColumn) const
1126 {
1127 Rectangle aBoundingBox (rBoundingBox);
1128
1129 if (nColumn == 0)
1130 aBoundingBox.Left() = 0;
1131 else
1132 aBoundingBox.Left() -= mnHorizontalGap/2;
1133 if (nColumn == mnColumnCount-1)
1134 aBoundingBox.Right() += mnRightBorder;
1135 else
1136 aBoundingBox.Right() += mnHorizontalGap/2;
1137 if (nRow == 0)
1138 aBoundingBox.Top() = 0;
1139 else
1140 aBoundingBox.Top() -= mnVerticalGap/2;
1141 if (nRow == mnRowCount-1)
1142 aBoundingBox.Bottom() += mnBottomBorder;
1143 else
1144 aBoundingBox.Bottom() += mnVerticalGap/2;
1145 return aBoundingBox;
1146 }
1147
1148
1149
1150
GetTotalBoundingBox(void) const1151 Rectangle Layouter::Implementation::GetTotalBoundingBox (void) const
1152 {
1153 sal_Int32 nHorizontalSize = 0;
1154 sal_Int32 nVerticalSize = 0;
1155 if (mnColumnCount > 0)
1156 {
1157 sal_Int32 nRowCount = (mnPageCount+mnColumnCount-1) / mnColumnCount;
1158 nHorizontalSize =
1159 mnLeftBorder
1160 + mnRightBorder
1161 + mnColumnCount * maPageObjectSize.Width();
1162 if (mnColumnCount > 1)
1163 nHorizontalSize += (mnColumnCount-1) * mnHorizontalGap;
1164 nVerticalSize =
1165 mnTopBorder
1166 + mnBottomBorder
1167 + nRowCount * maPageObjectSize.Height();
1168 if (nRowCount > 1)
1169 nVerticalSize += (nRowCount-1) * mnVerticalGap;
1170 }
1171
1172 return Rectangle (
1173 Point(0,0),
1174 Size (nHorizontalSize, nVerticalSize)
1175 );
1176 }
1177
1178
1179
1180
CalculateVerticalLogicalInsertPosition(const Point & rModelPosition,InsertPosition & rPosition) const1181 void Layouter::Implementation::CalculateVerticalLogicalInsertPosition (
1182 const Point& rModelPosition,
1183 InsertPosition& rPosition) const
1184 {
1185 const sal_Int32 nY = rModelPosition.Y() - mnTopBorder + maPageObjectSize.Height()/2;
1186 const sal_Int32 nRowHeight (maPageObjectSize.Height() + mnVerticalGap);
1187 const sal_Int32 nRow (::std::min(mnPageCount, nY / nRowHeight));
1188 rPosition.SetLogicalPosition (
1189 nRow,
1190 0,
1191 nRow,
1192 (nRow == 0),
1193 (nRow == mnRowCount),
1194 (nRow >= mnMaxRowCount));
1195 }
1196
1197
1198
1199
1200 //===== HorizontalImplementation ================================================
1201
HorizontalImplementation(const SharedSdWindow & rpWindow,const::boost::shared_ptr<view::Theme> & rpTheme)1202 HorizontalImplementation::HorizontalImplementation (
1203 const SharedSdWindow& rpWindow,
1204 const ::boost::shared_ptr<view::Theme>& rpTheme)
1205 : Implementation(rpWindow, rpTheme)
1206 {
1207 }
1208
1209
1210
1211
HorizontalImplementation(const Implementation & rImplementation)1212 HorizontalImplementation::HorizontalImplementation (const Implementation& rImplementation)
1213 : Implementation(rImplementation)
1214 {
1215 }
1216
1217
1218
1219
GetOrientation(void) const1220 Layouter::Orientation HorizontalImplementation::GetOrientation (void) const
1221 {
1222 return Layouter::HORIZONTAL;
1223 }
1224
1225
1226
1227
CalculateRowAndColumnCount(const Size & rWindowSize)1228 void HorizontalImplementation::CalculateRowAndColumnCount (const Size& rWindowSize)
1229 {
1230 (void)rWindowSize;
1231
1232 // Row and column count are fixed (for a given page count.)
1233 mnColumnCount = mnPageCount;
1234 mnRowCount = 1;
1235 }
1236
1237
1238
1239
CalculateMaxRowAndColumnCount(const Size & rWindowSize)1240 void HorizontalImplementation::CalculateMaxRowAndColumnCount (const Size& rWindowSize)
1241 {
1242 mnMaxColumnCount = (rWindowSize.Width() - mnLeftBorder - mnRightBorder)
1243 / (maPageObjectSize.Width() + mnHorizontalGap);
1244 mnMaxRowCount = 1;
1245 }
1246
1247
1248
1249
CalculateTargetSize(const Size & rWindowSize,const Size & rPreviewModelSize) const1250 Size HorizontalImplementation::CalculateTargetSize (
1251 const Size& rWindowSize,
1252 const Size& rPreviewModelSize) const
1253 {
1254 return Implementation::GetTargetSize(rWindowSize, rPreviewModelSize, false, true);
1255 }
1256
1257
1258
1259
CalculateLogicalInsertPosition(const Point & rModelPosition,InsertPosition & rPosition) const1260 void HorizontalImplementation::CalculateLogicalInsertPosition (
1261 const Point& rModelPosition,
1262 InsertPosition& rPosition) const
1263 {
1264 const sal_Int32 nX = rModelPosition.X() - mnLeftBorder + maPageObjectSize.Width()/2;
1265 const sal_Int32 nColumnWidth (maPageObjectSize.Width() + mnHorizontalGap);
1266 const sal_Int32 nColumn (::std::min(mnPageCount, nX / nColumnWidth));
1267 rPosition.SetLogicalPosition (
1268 0,
1269 nColumn,
1270 nColumn,
1271 (nColumn == 0),
1272 (nColumn == mnColumnCount),
1273 (nColumn >= mnMaxColumnCount));
1274 }
1275
1276
1277
1278
1279 //===== VerticalImplementation ================================================
1280
VerticalImplementation(const SharedSdWindow & rpWindow,const::boost::shared_ptr<view::Theme> & rpTheme)1281 VerticalImplementation::VerticalImplementation (
1282 const SharedSdWindow& rpWindow,
1283 const ::boost::shared_ptr<view::Theme>& rpTheme)
1284 : Implementation(rpWindow, rpTheme)
1285 {
1286 }
1287
1288
1289
1290
VerticalImplementation(const Implementation & rImplementation)1291 VerticalImplementation::VerticalImplementation (const Implementation& rImplementation)
1292 : Implementation(rImplementation)
1293 {
1294 }
1295
1296
1297
1298
GetOrientation(void) const1299 Layouter::Orientation VerticalImplementation::GetOrientation (void) const
1300 {
1301 return Layouter::VERTICAL;
1302 }
1303
1304
1305
1306
CalculateRowAndColumnCount(const Size & rWindowSize)1307 void VerticalImplementation::CalculateRowAndColumnCount (const Size& rWindowSize)
1308 {
1309 (void)rWindowSize;
1310
1311 // Row and column count are fixed (for a given page count.)
1312 mnRowCount = mnPageCount;
1313 mnColumnCount = 1;
1314
1315 }
1316
1317
1318
1319
CalculateMaxRowAndColumnCount(const Size & rWindowSize)1320 void VerticalImplementation::CalculateMaxRowAndColumnCount (const Size& rWindowSize)
1321 {
1322 mnMaxRowCount = (rWindowSize.Height() - mnTopBorder - mnBottomBorder)
1323 / (maPageObjectSize.Height() + mnVerticalGap);
1324 mnMaxColumnCount = 1;
1325 }
1326
1327
1328
1329
CalculateTargetSize(const Size & rWindowSize,const Size & rPreviewModelSize) const1330 Size VerticalImplementation::CalculateTargetSize (
1331 const Size& rWindowSize,
1332 const Size& rPreviewModelSize) const
1333 {
1334 return Implementation::GetTargetSize(rWindowSize, rPreviewModelSize, true, false);
1335 }
1336
1337
1338
1339
CalculateLogicalInsertPosition(const Point & rModelPosition,InsertPosition & rPosition) const1340 void VerticalImplementation::CalculateLogicalInsertPosition (
1341 const Point& rModelPosition,
1342 InsertPosition& rPosition) const
1343 {
1344 return CalculateVerticalLogicalInsertPosition(rModelPosition, rPosition);
1345 }
1346
1347
1348
1349
1350 //===== GridImplementation ================================================
1351
GridImplementation(const SharedSdWindow & rpWindow,const::boost::shared_ptr<view::Theme> & rpTheme)1352 GridImplementation::GridImplementation (
1353 const SharedSdWindow& rpWindow,
1354 const ::boost::shared_ptr<view::Theme>& rpTheme)
1355 : Implementation(rpWindow, rpTheme)
1356 {
1357 }
1358
1359
1360
1361
GridImplementation(const Implementation & rImplementation)1362 GridImplementation::GridImplementation (const Implementation& rImplementation)
1363 : Implementation(rImplementation)
1364 {
1365 }
1366
1367
1368
1369
GetOrientation(void) const1370 Layouter::Orientation GridImplementation::GetOrientation (void) const
1371 {
1372 return Layouter::GRID;
1373 }
1374
1375
1376
1377
CalculateRowAndColumnCount(const Size & rWindowSize)1378 void GridImplementation::CalculateRowAndColumnCount (const Size& rWindowSize)
1379 {
1380 // Calculate the column count.
1381 mnColumnCount
1382 = (rWindowSize.Width() - mnRequestedLeftBorder - mnRequestedRightBorder)
1383 / (maPreferredSize.Width() + mnHorizontalGap);
1384 if (mnColumnCount < mnMinimalColumnCount)
1385 mnColumnCount = mnMinimalColumnCount;
1386 if (mnColumnCount > mnMaximalColumnCount)
1387 mnColumnCount = mnMaximalColumnCount;
1388 mnRowCount = (mnPageCount + mnColumnCount-1)/mnColumnCount;
1389 }
1390
1391
1392
1393
CalculateMaxRowAndColumnCount(const Size & rWindowSize)1394 void GridImplementation::CalculateMaxRowAndColumnCount (const Size& rWindowSize)
1395 {
1396 mnMaxColumnCount = (rWindowSize.Width() - mnLeftBorder - mnRightBorder)
1397 / (maPageObjectSize.Width() + mnHorizontalGap);
1398 mnMaxRowCount = (rWindowSize.Height() - mnTopBorder - mnBottomBorder)
1399 / (maPageObjectSize.Height() + mnVerticalGap);
1400 }
1401
1402
1403
1404
1405
CalculateTargetSize(const Size & rWindowSize,const Size & rPreviewModelSize) const1406 Size GridImplementation::CalculateTargetSize (
1407 const Size& rWindowSize,
1408 const Size& rPreviewModelSize) const
1409 {
1410 return Implementation::GetTargetSize(rWindowSize, rPreviewModelSize, true, true);
1411 }
1412
1413
1414
1415
CalculateLogicalInsertPosition(const Point & rModelPosition,InsertPosition & rPosition) const1416 void GridImplementation::CalculateLogicalInsertPosition (
1417 const Point& rModelPosition,
1418 InsertPosition& rPosition) const
1419 {
1420 if (mnColumnCount == 1)
1421 {
1422 CalculateVerticalLogicalInsertPosition(rModelPosition, rPosition);
1423 }
1424 else
1425 {
1426 // Handle the general case of more than one column.
1427 sal_Int32 nRow (::std::min(
1428 mnRowCount-1,
1429 GetRowAtPosition (rModelPosition.Y(), true, GM_BOTH)));
1430 const sal_Int32 nX = rModelPosition.X() - mnLeftBorder + maPageObjectSize.Width()/2;
1431 const sal_Int32 nColumnWidth (maPageObjectSize.Width() + mnHorizontalGap);
1432 sal_Int32 nColumn (::std::min(mnColumnCount, nX / nColumnWidth));
1433 sal_Int32 nIndex (nRow * mnColumnCount + nColumn);
1434 bool bIsAtRunEnd (nColumn == mnColumnCount);
1435
1436 if (nIndex >= mnPageCount)
1437 {
1438 nIndex = mnPageCount;
1439 nRow = mnRowCount-1;
1440 nColumn = ::std::min(::std::min(mnPageCount, mnColumnCount), nColumn);
1441 bIsAtRunEnd = true;
1442 }
1443
1444 rPosition.SetLogicalPosition (
1445 nRow,
1446 nColumn,
1447 nIndex,
1448 (nColumn == 0),
1449 bIsAtRunEnd,
1450 (nColumn >= mnMaxColumnCount));
1451 }
1452 }
1453
1454
1455
1456
1457 //===== InsertPosition ========================================================
1458
InsertPosition(void)1459 InsertPosition::InsertPosition (void)
1460 : mnRow(-1),
1461 mnColumn(-1),
1462 mnIndex(-1),
1463 mbIsAtRunStart(false),
1464 mbIsAtRunEnd(false),
1465 mbIsExtraSpaceNeeded(false),
1466 maLocation(0,0),
1467 maLeadingOffset(0,0),
1468 maTrailingOffset(0,0)
1469 {
1470 }
1471
1472
1473
1474
operator =(const InsertPosition & rInsertPosition)1475 InsertPosition& InsertPosition::operator= (const InsertPosition& rInsertPosition)
1476 {
1477 if (this != &rInsertPosition)
1478 {
1479 mnRow = rInsertPosition.mnRow;
1480 mnColumn = rInsertPosition.mnColumn;
1481 mnIndex = rInsertPosition.mnIndex;
1482 mbIsAtRunStart = rInsertPosition.mbIsAtRunStart;
1483 mbIsAtRunEnd = rInsertPosition.mbIsAtRunEnd;
1484 mbIsExtraSpaceNeeded = rInsertPosition.mbIsExtraSpaceNeeded;
1485 maLocation = rInsertPosition.maLocation;
1486 maLeadingOffset = rInsertPosition.maLeadingOffset;
1487 maTrailingOffset = rInsertPosition.maTrailingOffset;
1488 }
1489 return *this;
1490 }
1491
1492
1493
1494
operator ==(const InsertPosition & rInsertPosition) const1495 bool InsertPosition::operator== (const InsertPosition& rInsertPosition) const
1496 {
1497 // Do not compare the geometrical information (maLocation).
1498 return mnRow==rInsertPosition.mnRow
1499 && mnColumn==rInsertPosition.mnColumn
1500 && mnIndex==rInsertPosition.mnIndex
1501 && mbIsAtRunStart==rInsertPosition.mbIsAtRunStart
1502 && mbIsAtRunEnd==rInsertPosition.mbIsAtRunEnd
1503 && mbIsExtraSpaceNeeded==rInsertPosition.mbIsExtraSpaceNeeded;
1504 }
1505
1506
1507
1508
operator !=(const InsertPosition & rInsertPosition) const1509 bool InsertPosition::operator!= (const InsertPosition& rInsertPosition) const
1510 {
1511 return !operator==(rInsertPosition);
1512 }
1513
1514
1515
1516
SetLogicalPosition(const sal_Int32 nRow,const sal_Int32 nColumn,const sal_Int32 nIndex,const bool bIsAtRunStart,const bool bIsAtRunEnd,const bool bIsExtraSpaceNeeded)1517 void InsertPosition::SetLogicalPosition (
1518 const sal_Int32 nRow,
1519 const sal_Int32 nColumn,
1520 const sal_Int32 nIndex,
1521 const bool bIsAtRunStart,
1522 const bool bIsAtRunEnd,
1523 const bool bIsExtraSpaceNeeded)
1524 {
1525 mnRow = nRow;
1526 mnColumn = nColumn;
1527 mnIndex = nIndex;
1528 mbIsAtRunStart = bIsAtRunStart;
1529 mbIsAtRunEnd = bIsAtRunEnd;
1530 mbIsExtraSpaceNeeded = bIsExtraSpaceNeeded;
1531 }
1532
1533
1534
1535
SetGeometricalPosition(const Point aLocation,const Point aLeadingOffset,const Point aTrailingOffset)1536 void InsertPosition::SetGeometricalPosition(
1537 const Point aLocation,
1538 const Point aLeadingOffset,
1539 const Point aTrailingOffset)
1540 {
1541 maLocation = aLocation;
1542 maLeadingOffset = aLeadingOffset;
1543 maTrailingOffset = aTrailingOffset;
1544 }
1545
1546
1547
1548 } } } // end of namespace ::sd::slidesorter::namespace
1549