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