1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <view/SlsPageObjectLayouter.hxx>
21 #include <view/SlsTheme.hxx>
22 #include <view/SlsLayouter.hxx>
23 #include <model/SlideSorterModel.hxx>
24 #include <model/SlsPageDescriptor.hxx>
25 #include <Window.hxx>
26 #include <osl/diagnose.h>
27 
28 namespace sd { namespace slidesorter { namespace view {
29 
30 class Layouter::Implementation
31 {
32 public:
33     VclPtr<sd::Window> mpWindow;
34     static const sal_Int32 mnRequestedLeftBorder = 5;
35     static const sal_Int32 mnRequestedRightBorder = 5;
36     static const sal_Int32 mnRequestedTopBorder = 5;
37     static const sal_Int32 mnRequestedBottomBorder = 5;
38     sal_Int32 mnLeftBorder;
39     sal_Int32 mnRightBorder;
40     sal_Int32 mnTopBorder;
41     sal_Int32 mnBottomBorder;
42     static const sal_Int32 gnVerticalGap = 10 - 2*Theme_FocusIndicatorWidth;
43     static const sal_Int32 gnHorizontalGap = 10 - 2*Theme_FocusIndicatorWidth;
44     Size const maMinimalSize;
45     Size const maPreferredSize;
46     Size const maMaximalSize;
47     sal_Int32 mnMinimalColumnCount;
48     sal_Int32 mnMaximalColumnCount;
49     sal_Int32 mnPageCount;
50     sal_Int32 mnColumnCount;
51     sal_Int32 mnRowCount;
52     /// The maximum number of columns.  Can only be larger than the current
53     /// number of columns when there are not enough pages to fill all
54     /// available columns.
55     sal_Int32 mnMaxColumnCount;
56     /// The maximum number of rows.  Can only be larger than the current
57     /// number of rows when there are not enough pages to fill all available
58     /// rows.
59     sal_Int32 mnMaxRowCount;
60     Size maPageObjectSize;
61     std::shared_ptr<PageObjectLayouter> mpPageObjectLayouter;
62     std::shared_ptr<view::Theme> mpTheme;
63 
64     /** Specify how the gap between two page objects is associated with the
65       page objects.
66     */
67     enum GapMembership {
68         GM_NONE,       // Gap is not associated with any page object.
69         GM_PREVIOUS,   // The whole gap is associated with the previous page
70                        // object (left or above the gap.)
71         GM_BOTH,       // Half of the gap is associated with previous, half
72                        // with the next page object.
73         GM_NEXT,       // The whole gap is associated with the next page
74                        // object (right or below the gap.)
75         GM_PAGE_BORDER
76     };
77 
78     static Implementation* Create (
79         const Implementation& rImplementation,
80         const Layouter::Orientation eOrientation);
81 
82     virtual Layouter::Orientation GetOrientation() const = 0;
83 
84     bool Rearrange (
85         const Size& rWindowSize,
86         const Size& rPreviewModelSize,
87         const sal_uInt32 nPageCount);
88 
89     /** Calculate the row that the point with the given vertical coordinate
90         is over.  The horizontal component is ignored.
91         @param nYPosition
92             Vertical position in model coordinates.
93         @param bIncludeBordersAndGaps
94             When this flag is <TRUE/> then the area of borders and gaps are
95             interpreted as belonging to one of the rows.
96         @param eGapMembership
97             Specifies to what row the gap areas belong.  Here GM_NONE
98             corresponds to bIncludeBordersAndGaps being <FALSE/>.  When
99             GM_BOTH is given then the upper half is associated to the row
100             above and the lower half to the row below.  Values of
101             GM_PREVIOUS and GM_NEXT associate the whole gap area with the
102             row above or below respectively.
103     */
104     sal_Int32 GetRowAtPosition (
105         sal_Int32 nYPosition,
106         bool bIncludeBordersAndGaps,
107         GapMembership eGapMembership) const;
108 
109     /** Calculate the column that the point with the given horizontal
110         coordinate is over.  The vertical component is ignored.
111         @param nXPosition
112             Horizontal position in model coordinates.
113         @param bIncludeBordersAndGaps
114             When this flag is <TRUE/> then the area of borders and gaps are
115             interpreted as belonging to one of the columns.
116         @param eGapMembership
117             Specifies to what column the gap areas belong.
118     */
119     sal_Int32 GetColumnAtPosition (
120         sal_Int32 nXPosition,
121         bool bIncludeBordersAndGaps,
122         GapMembership eGapMembership) const;
123 
124     /** This method is typically called from GetRowAtPosition() and
125         GetColumnAtPosition() to handle a position that lies inside the gap
126         between two adjacent rows or columns.
127         @param nDistanceIntoGap
128             Vertical distance from the bottom of the upper row down into the
129             gap or horizontal distance from the right edge right into the
130             gap.
131         @param eGapMemberhship
132             This value decides what areas in the gap belong to which (or no)
133             row or column.
134         @param nIndex
135             The row index of the upper row or the column index of the left
136             column.
137         @param nGap
138              Width or height of the gap in model coordinates between the
139              page borders.
140         @return
141            Returns either the index of the upper row (as given as nRow), the
142            index of the lower row (nRow+1) or -1 to indicate that the
143            position belongs to no row.
144         */
145     static sal_Int32 ResolvePositionInGap (
146         sal_Int32 nDistanceIntoGap,
147         GapMembership eGapMembership,
148         sal_Int32 nIndex,
149         sal_Int32 nGap);
150 
151     /** Calculate the logical part of the insert position, i.e. the page
152         after which to insert.
153     */
154     virtual void CalculateLogicalInsertPosition (
155         const Point& rModelPosition,
156         InsertPosition& rPosition) const = 0;
157 
158     /** Calculate the geometrical part of the insert position, i.e. the
159         location of where to display the insertion indicator and the
160         distances about which the leading and trailing pages have to be
161         moved to make room for the indicator.
162     */
163     void CalculateGeometricPosition (
164         InsertPosition& rPosition,
165         const Size& rIndicatorSize,
166         const bool bIsVertical,
167         model::SlideSorterModel const & rModel) const;
168 
169     /** Return the bounding box of the preview or, when selected, of the page
170         object.  Thus, it returns something like a visual bounding box.
171     */
172     ::tools::Rectangle GetInnerBoundingBox (
173         model::SlideSorterModel const & rModel,
174         const sal_Int32 nIndex) const;
175 
176     Range GetValidHorizontalSizeRange() const;
177     Range GetValidVerticalSizeRange() const;
178 
179     Range GetRangeOfVisiblePageObjects (const ::tools::Rectangle& aVisibleArea) const;
180     sal_Int32 GetIndex (
181         const sal_Int32 nRow,
182         const sal_Int32 nColumn,
183         const bool bClampToValidRange) const;
184 
185         ::tools::Rectangle GetPageObjectBox (
186         const sal_Int32 nIndex,
187         const bool bIncludeBorderAndGap = false) const;
188 
189     ::tools::Rectangle GetPageObjectBox (
190         const sal_Int32 nRow,
191         const sal_Int32 nColumn) const;
192 
193     ::tools::Rectangle AddBorderAndGap (
194         const ::tools::Rectangle& rBoundingBox,
195         const sal_Int32 nRow,
196         const sal_Int32 nColumn) const;
197 
198     ::tools::Rectangle GetTotalBoundingBox() const;
199 
200     virtual ~Implementation();
201 
202 protected:
203     Implementation (
204         sd::Window *pWindow,
205         const std::shared_ptr<view::Theme>& rpTheme);
206     explicit Implementation (const Implementation& rImplementation);
207 
208     virtual void CalculateRowAndColumnCount (const Size& rWindowSize) = 0;
209     virtual void CalculateMaxRowAndColumnCount (const Size& rWindowSize) = 0;
210     virtual Size CalculateTargetSize (
211         const Size& rWindowSize) const = 0;
212     Size GetTargetSize (
213         const Size& rWindowSize,
214         const bool bCalculateWidth,
215         const bool bCalculateHeight) const;
216     void CalculateVerticalLogicalInsertPosition (
217         const Point& rModelPosition,
218         InsertPosition& rPosition) const;
219 };
220 
221 /** The vertical layouter has one column and as many rows as there are
222     pages.
223 */
224 class VerticalImplementation : public Layouter::Implementation
225 {
226 public:
227     explicit VerticalImplementation (const Implementation& rImplementation);
228 
229     virtual Layouter::Orientation GetOrientation() const override;
230 
231     void CalculateLogicalInsertPosition (
232         const Point& rModelPosition,
233         InsertPosition& rPosition) const override;
234 
235 protected:
236     virtual void CalculateRowAndColumnCount (const Size& rWindowSize) override;
237     virtual void CalculateMaxRowAndColumnCount (const Size& rWindowSize) override;
238     virtual Size CalculateTargetSize (
239         const Size& rWindowSize) const override;
240 };
241 
242 /** The horizontal layouter has one row and as many columns as there are
243     pages.
244 */
245 class HorizontalImplementation : public Layouter::Implementation
246 {
247 public:
248     explicit HorizontalImplementation(const Implementation& rImplementation);
249 
250     virtual Layouter::Orientation GetOrientation() const override;
251 
252     void CalculateLogicalInsertPosition (
253         const Point& rModelPosition,
254         InsertPosition& rPosition) const override;
255 
256 protected:
257     virtual void CalculateRowAndColumnCount (const Size& rWindowSize) override;
258     virtual void CalculateMaxRowAndColumnCount (const Size& rWindowSize) override;
259     virtual Size CalculateTargetSize (
260         const Size& rWindowSize) const override;
261 };
262 
263 /** The number of columns of the grid layouter is defined via a control in
264     the slide sorter tool bar.  The number of rows is calculated from the
265     number of columns and the number of pages.
266 */
267 class GridImplementation : public Layouter::Implementation
268 {
269 public:
270     GridImplementation (
271         sd::Window *pWindow,
272         const std::shared_ptr<view::Theme>& rpTheme);
273     explicit GridImplementation(const Implementation& rImplementation);
274 
275     virtual Layouter::Orientation GetOrientation() const override;
276 
277     void CalculateLogicalInsertPosition (
278         const Point& rModelPosition,
279         InsertPosition& rPosition) const override;
280 
281 protected:
282     virtual void CalculateRowAndColumnCount (const Size& rWindowSize) override;
283     virtual void CalculateMaxRowAndColumnCount (const Size& rWindowSize) override;
284     virtual Size CalculateTargetSize (
285         const Size& rWindowSize) const override;
286 };
287 
288 //===== Layouter ==============================================================
289 
Layouter(sd::Window * pWindow,const std::shared_ptr<Theme> & rpTheme)290 Layouter::Layouter (
291     sd::Window *pWindow,
292     const std::shared_ptr<Theme>& rpTheme)
293     : mpImplementation(new GridImplementation(pWindow, rpTheme)),
294       mpWindow(pWindow)
295 {
296 }
297 
~Layouter()298 Layouter::~Layouter()
299 {
300 }
301 
GetPageObjectLayouter() const302 std::shared_ptr<PageObjectLayouter> const & Layouter::GetPageObjectLayouter() const
303 {
304     return mpImplementation->mpPageObjectLayouter;
305 }
306 
SetColumnCount(sal_Int32 nMinimalColumnCount,sal_Int32 nMaximalColumnCount)307 void Layouter::SetColumnCount (
308     sal_Int32 nMinimalColumnCount,
309         sal_Int32 nMaximalColumnCount)
310 {
311     if (nMinimalColumnCount <= nMaximalColumnCount)
312     {
313         mpImplementation->mnMinimalColumnCount = nMinimalColumnCount;
314         mpImplementation->mnMaximalColumnCount = nMaximalColumnCount;
315     }
316 }
317 
Rearrange(const Orientation eOrientation,const Size & rWindowSize,const Size & rPageSize,const sal_uInt32 nPageCount)318 bool Layouter::Rearrange (
319     const Orientation eOrientation,
320     const Size& rWindowSize,
321     const Size& rPageSize,
322     const sal_uInt32 nPageCount)
323 {
324     OSL_ASSERT(mpWindow);
325 
326     if (eOrientation != mpImplementation->GetOrientation())
327         mpImplementation.reset(Implementation::Create(*mpImplementation, eOrientation));
328 
329     return mpImplementation->Rearrange(rWindowSize, rPageSize, nPageCount);
330 }
331 
GetColumnCount() const332 sal_Int32 Layouter::GetColumnCount() const
333 {
334     return mpImplementation->mnColumnCount;
335 }
336 
GetIndex(const sal_Int32 nRow,const sal_Int32 nColumn) const337 sal_Int32 Layouter::GetIndex (const sal_Int32 nRow, const sal_Int32 nColumn) const
338 {
339     return mpImplementation->GetIndex(nRow,nColumn,true);
340 }
341 
GetPageObjectSize() const342 Size const & Layouter::GetPageObjectSize() const
343 {
344     return mpImplementation->maPageObjectSize;
345 }
346 
GetPageObjectBox(const sal_Int32 nIndex,const bool bIncludeBorderAndGap) const347 ::tools::Rectangle Layouter::GetPageObjectBox (
348     const sal_Int32 nIndex,
349     const bool bIncludeBorderAndGap) const
350 {
351     return mpImplementation->GetPageObjectBox(nIndex, bIncludeBorderAndGap);
352 }
353 
GetTotalBoundingBox() const354 ::tools::Rectangle Layouter::GetTotalBoundingBox() const
355 {
356     return mpImplementation->GetTotalBoundingBox();
357 }
358 
GetInsertPosition(const Point & rModelPosition,const Size & rIndicatorSize,model::SlideSorterModel const & rModel) const359 InsertPosition Layouter::GetInsertPosition (
360     const Point& rModelPosition,
361     const Size& rIndicatorSize,
362     model::SlideSorterModel const & rModel) const
363 {
364     InsertPosition aPosition;
365     mpImplementation->CalculateLogicalInsertPosition(
366         rModelPosition,
367         aPosition);
368     mpImplementation->CalculateGeometricPosition(
369         aPosition,
370         rIndicatorSize,
371         GetColumnCount()==1,
372         rModel);
373     return aPosition;
374 }
375 
GetValidHorizontalSizeRange() const376 Range Layouter::GetValidHorizontalSizeRange() const
377 {
378     return mpImplementation->GetValidHorizontalSizeRange();
379 }
380 
GetValidVerticalSizeRange() const381 Range Layouter::GetValidVerticalSizeRange() const
382 {
383     return mpImplementation->GetValidVerticalSizeRange();
384 }
385 
GetRangeOfVisiblePageObjects(const::tools::Rectangle & aVisibleArea) const386 Range Layouter::GetRangeOfVisiblePageObjects (const ::tools::Rectangle& aVisibleArea) const
387 {
388     return mpImplementation->GetRangeOfVisiblePageObjects(aVisibleArea);
389 }
390 
GetIndexAtPoint(const Point & rPosition,const bool bIncludePageBorders,const bool bClampToValidRange) const391 sal_Int32 Layouter::GetIndexAtPoint (
392     const Point& rPosition,
393     const bool bIncludePageBorders,
394     const bool bClampToValidRange) const
395 {
396     const sal_Int32 nRow (
397         mpImplementation->GetRowAtPosition (
398             rPosition.Y(),
399             bIncludePageBorders,
400             bIncludePageBorders ? Implementation::GM_PAGE_BORDER : Implementation::GM_NONE));
401     const sal_Int32 nColumn (
402         mpImplementation->GetColumnAtPosition (
403             rPosition.X(),
404             bIncludePageBorders,
405             bIncludePageBorders ? Implementation::GM_PAGE_BORDER : Implementation::GM_NONE));
406 
407     return mpImplementation->GetIndex(nRow,nColumn,bClampToValidRange);
408 }
409 
410 //===== Layouter::Implementation ==============================================
411 
Create(const Implementation & rImplementation,const Layouter::Orientation eOrientation)412 Layouter::Implementation* Layouter::Implementation::Create (
413     const Implementation& rImplementation,
414     const Layouter::Orientation eOrientation)
415 {
416     switch (eOrientation)
417     {
418         case HORIZONTAL: return new HorizontalImplementation(rImplementation);
419         case VERTICAL: return new VerticalImplementation(rImplementation);
420         case GRID:
421         default: return new GridImplementation(rImplementation);
422     }
423 }
424 
Implementation(sd::Window * pWindow,const std::shared_ptr<view::Theme> & rpTheme)425 Layouter::Implementation::Implementation (
426     sd::Window *pWindow,
427     const std::shared_ptr<view::Theme>& rpTheme)
428     : mpWindow(pWindow),
429       mnLeftBorder(5),
430       mnRightBorder(5),
431       mnTopBorder(5),
432       mnBottomBorder(5),
433       maMinimalSize(132,98),
434       maPreferredSize(200,150),
435       maMaximalSize(600,400),
436       mnMinimalColumnCount(1),
437       mnMaximalColumnCount(15),
438       mnPageCount(0),
439       mnColumnCount(1),
440       mnRowCount(0),
441       mnMaxColumnCount(0),
442       mnMaxRowCount(0),
443       maPageObjectSize(1,1),
444       mpPageObjectLayouter(),
445       mpTheme(rpTheme)
446 {
447 }
448 
Implementation(const Implementation & rImplementation)449 Layouter::Implementation::Implementation (const Implementation& rImplementation)
450     : mpWindow(rImplementation.mpWindow),
451       mnLeftBorder(rImplementation.mnLeftBorder),
452       mnRightBorder(rImplementation.mnRightBorder),
453       mnTopBorder(rImplementation.mnTopBorder),
454       mnBottomBorder(rImplementation.mnBottomBorder),
455       maMinimalSize(rImplementation.maMinimalSize),
456       maPreferredSize(rImplementation.maPreferredSize),
457       maMaximalSize(rImplementation.maMaximalSize),
458       mnMinimalColumnCount(rImplementation.mnMinimalColumnCount),
459       mnMaximalColumnCount(rImplementation.mnMaximalColumnCount),
460       mnPageCount(rImplementation.mnPageCount),
461       mnColumnCount(rImplementation.mnColumnCount),
462       mnRowCount(rImplementation.mnRowCount),
463       mnMaxColumnCount(rImplementation.mnMaxColumnCount),
464       mnMaxRowCount(rImplementation.mnMaxRowCount),
465       maPageObjectSize(rImplementation.maPageObjectSize),
466       mpPageObjectLayouter(),
467       mpTheme(rImplementation.mpTheme)
468 {
469 }
470 
~Implementation()471 Layouter::Implementation::~Implementation()
472 {
473 }
474 
Rearrange(const Size & rWindowSize,const Size & rPreviewModelSize,const sal_uInt32 nPageCount)475 bool Layouter::Implementation::Rearrange (
476     const Size& rWindowSize,
477     const Size& rPreviewModelSize,
478     const sal_uInt32 nPageCount)
479 {
480     mnPageCount = nPageCount;
481 
482     // Return early when the window or the model have not yet been initialized.
483     if (rWindowSize.Width()<=0 || rWindowSize.Height()<=0)
484         return false;
485     if (rPreviewModelSize.Width()<=0 || rPreviewModelSize.Height()<=0)
486         return false;
487 
488     CalculateRowAndColumnCount(rWindowSize);
489 
490     // Update the border values.
491     mnLeftBorder = mnRequestedLeftBorder;
492     mnTopBorder = mnRequestedTopBorder;
493     mnRightBorder = mnRequestedRightBorder;
494     mnBottomBorder = mnRequestedBottomBorder;
495     if (mnColumnCount > 1)
496     {
497         int nMinimumBorderWidth = gnHorizontalGap/2;
498         if (mnLeftBorder < nMinimumBorderWidth)
499             mnLeftBorder = nMinimumBorderWidth;
500         if (mnRightBorder < nMinimumBorderWidth)
501             mnRightBorder = nMinimumBorderWidth;
502     }
503     else
504     {
505         int nMinimumBorderHeight = gnVerticalGap/2;
506         if (mnTopBorder < nMinimumBorderHeight)
507             mnTopBorder = nMinimumBorderHeight;
508         if (mnBottomBorder < nMinimumBorderHeight)
509             mnBottomBorder = nMinimumBorderHeight;
510     }
511 
512     mpPageObjectLayouter.reset(
513         new PageObjectLayouter(
514             CalculateTargetSize(rWindowSize),
515             rPreviewModelSize,
516             mpWindow,
517             mnPageCount));
518 
519     maPageObjectSize = mpPageObjectLayouter->GetGridMaxSize();
520 
521     CalculateMaxRowAndColumnCount(rWindowSize);
522 
523     return true;
524 }
525 
GetRowAtPosition(sal_Int32 nYPosition,bool bIncludeBordersAndGaps,GapMembership eGapMembership) const526 sal_Int32 Layouter::Implementation::GetRowAtPosition (
527     sal_Int32 nYPosition,
528     bool bIncludeBordersAndGaps,
529     GapMembership eGapMembership) const
530 {
531     sal_Int32 nRow = -1;
532 
533     const sal_Int32 nY = nYPosition - mnTopBorder;
534     if (nY >= 0)
535     {
536         // Vertical distance from one row to the next.
537         const sal_Int32 nRowOffset (maPageObjectSize.Height() + gnVerticalGap);
538 
539         // Calculate row consisting of page objects and gap below.
540         nRow = nY / nRowOffset;
541 
542         const sal_Int32 nDistanceIntoGap ((nY - nRow*nRowOffset) - maPageObjectSize.Height());
543         // When inside the gap below then nYPosition is not over a page
544         // object.
545         if (nDistanceIntoGap > 0)
546         {
547             sal_Int32 nResolvedRow = ResolvePositionInGap(
548                 nDistanceIntoGap,
549                 eGapMembership,
550                 nRow,
551                 gnVerticalGap);
552             if (!bIncludeBordersAndGaps || nResolvedRow != -1)
553                 nRow = nResolvedRow;
554         }
555     }
556     else if (bIncludeBordersAndGaps)
557     {
558         // We are in the top border area.  Set nRow to the first row when
559         // the top border shall be considered to belong to the first row.
560         nRow = 0;
561     }
562 
563     return nRow;
564 }
565 
GetColumnAtPosition(sal_Int32 nXPosition,bool bIncludeBordersAndGaps,GapMembership eGapMembership) const566 sal_Int32 Layouter::Implementation::GetColumnAtPosition (
567     sal_Int32 nXPosition,
568     bool bIncludeBordersAndGaps,
569     GapMembership eGapMembership) const
570 {
571     sal_Int32 nColumn = -1;
572 
573     sal_Int32 nX = nXPosition - mnLeftBorder;
574     if (nX >= 0)
575     {
576         // Horizontal distance from one column to the next.
577         const sal_Int32 nColumnOffset (maPageObjectSize.Width() + gnHorizontalGap);
578 
579         // Calculate row consisting of page objects and gap below.
580         nColumn = nX / nColumnOffset;
581         if (nColumn < 0)
582             nColumn = 0;
583         else if (nColumn >= mnColumnCount)
584             nColumn = mnColumnCount-1;
585 
586         const sal_Int32 nDistanceIntoGap ((nX - nColumn*nColumnOffset) - maPageObjectSize.Width());
587         // When inside the gap at the right then nXPosition is not over a
588         // page object.
589         if (nDistanceIntoGap > 0)
590         {
591             sal_Int32 nResolvedColumn = ResolvePositionInGap(
592                 nDistanceIntoGap,
593                 eGapMembership,
594                 nColumn,
595                 gnHorizontalGap);
596             if (!bIncludeBordersAndGaps || nResolvedColumn != -1)
597                 nColumn = nResolvedColumn;
598         }
599     }
600     else if (bIncludeBordersAndGaps)
601     {
602         // We are in the left border area.  Set nColumn to the first column
603         // when the left border shall be considered to belong to the first
604         // column.
605         nColumn = 0;
606     }
607     return nColumn;
608 }
609 
ResolvePositionInGap(sal_Int32 nDistanceIntoGap,GapMembership eGapMembership,sal_Int32 nIndex,sal_Int32 nGap)610 sal_Int32 Layouter::Implementation::ResolvePositionInGap (
611     sal_Int32 nDistanceIntoGap,
612     GapMembership eGapMembership,
613     sal_Int32 nIndex,
614     sal_Int32 nGap)
615 {
616     switch (eGapMembership)
617     {
618         case GM_NONE:
619             // The gap is no man's land.
620             nIndex = -1;
621             break;
622 
623         case GM_BOTH:
624         {
625             // The lower half of the gap belongs to the next row or column.
626             sal_Int32 nFirstHalfGapWidth = nGap / 2;
627             if (nDistanceIntoGap > nFirstHalfGapWidth)
628                 nIndex ++;
629             break;
630         }
631 
632         case GM_PREVIOUS:
633             // Row or column already at correct value.
634             break;
635 
636         case GM_NEXT:
637             // The complete gap belongs to the next row or column.
638             nIndex ++;
639             break;
640 
641         case GM_PAGE_BORDER:
642             if (nDistanceIntoGap > 0)
643             {
644                 if (nDistanceIntoGap > nGap)
645                 {
646                     // Inside the border of the next row or column.
647                     nIndex ++;
648                 }
649                 else
650                 {
651                     // Inside the gap between the page borders.
652                     nIndex = -1;
653                 }
654             }
655             break;
656 
657         default:
658             nIndex = -1;
659     }
660 
661     return nIndex;
662 }
663 
CalculateGeometricPosition(InsertPosition & rPosition,const Size & rIndicatorSize,const bool bIsVertical,model::SlideSorterModel const & rModel) const664 void Layouter::Implementation::CalculateGeometricPosition (
665     InsertPosition& rPosition,
666     const Size& rIndicatorSize,
667     const bool bIsVertical,
668     model::SlideSorterModel const & rModel) const
669 {
670     // 1. Determine right/bottom of the leading page and the left/top of the
671     // trailing page object and how to distribute the missing space.
672     sal_Int32 nLeadingLocation (0);
673     sal_Int32 nTrailingLocation (0);
674     bool bIsLeadingFixed (false);
675     bool bIsTrailingFixed (false);
676     sal_Int32 nSecondaryLocation (0);
677     const sal_Int32 nIndex (rPosition.GetIndex());
678 
679     if (rPosition.IsAtRunStart())
680     {
681         // Place indicator at the top of the column.
682         const ::tools::Rectangle aOuterBox (GetPageObjectBox(nIndex));
683         const ::tools::Rectangle aInnerBox (GetInnerBoundingBox(rModel, nIndex));
684         if (bIsVertical)
685         {
686             nLeadingLocation = aOuterBox.Top();
687             nTrailingLocation = aInnerBox.Top();
688             nSecondaryLocation = aInnerBox.Center().X();
689         }
690         else
691         {
692             nLeadingLocation = aOuterBox.Left();
693             nTrailingLocation = aInnerBox.Left();
694             nSecondaryLocation = aInnerBox.Center().Y();
695         }
696         bIsLeadingFixed = true;
697     }
698     else if (rPosition.IsAtRunEnd())
699     {
700         // Place indicator at the bottom/right of the column/row.
701 
702         const ::tools::Rectangle aOuterBox (GetPageObjectBox(nIndex-1));
703         const ::tools::Rectangle aInnerBox (GetInnerBoundingBox(rModel, nIndex-1));
704         if (bIsVertical)
705         {
706             nLeadingLocation = aInnerBox.Bottom();
707             nTrailingLocation = aOuterBox.Bottom();
708             nSecondaryLocation = aInnerBox.Center().X();
709         }
710         else
711         {
712             nLeadingLocation = aInnerBox.Right();
713             nTrailingLocation = aOuterBox.Right();
714             nSecondaryLocation = aInnerBox.Center().Y();
715         }
716         bIsTrailingFixed = true;
717         if ( ! rPosition.IsExtraSpaceNeeded())
718             bIsLeadingFixed = true;
719     }
720     else
721     {
722         // Place indicator between two rows/columns.
723         const ::tools::Rectangle aBox1 (GetInnerBoundingBox(rModel, nIndex-1));
724         const ::tools::Rectangle aBox2 (GetInnerBoundingBox(rModel, nIndex));
725         if (bIsVertical)
726         {
727             nLeadingLocation = aBox1.Bottom();
728             nTrailingLocation = aBox2.Top();
729             nSecondaryLocation = (aBox1.Center().X() + aBox2.Center().X()) / 2;
730         }
731         else
732         {
733             nLeadingLocation = aBox1.Right();
734             nTrailingLocation = aBox2.Left();
735             nSecondaryLocation = (aBox1.Center().Y() + aBox2.Center().Y()) / 2;
736         }
737     }
738 
739     // 2. Calculate the location of the insert indicator and the offsets of
740     // leading and trailing pages.
741     const sal_Int32 nAvailableSpace (nTrailingLocation - nLeadingLocation);
742     const sal_Int32 nRequiredSpace (bIsVertical ? rIndicatorSize.Height():rIndicatorSize.Width());
743     const sal_Int32 nMissingSpace (::std::max(sal_Int32(0), nRequiredSpace - nAvailableSpace));
744     sal_Int32 nPrimaryLocation (0);
745     sal_Int32 nLeadingOffset (0);
746     sal_Int32 nTrailingOffset (0);
747     if (bIsLeadingFixed)
748     {
749         nPrimaryLocation = nLeadingLocation + nRequiredSpace/2;
750         if ( ! bIsTrailingFixed)
751             nTrailingOffset = nMissingSpace;
752     }
753     else if (bIsTrailingFixed)
754     {
755         nPrimaryLocation = nTrailingLocation - nRequiredSpace/2;
756         nLeadingOffset = -nMissingSpace;
757     }
758     else
759     {
760         nPrimaryLocation = (nLeadingLocation + nTrailingLocation) /2;
761         nLeadingOffset = -nMissingSpace/2;
762         nTrailingOffset = nMissingSpace + nLeadingOffset;
763     }
764 
765     if (bIsVertical)
766     {
767         rPosition.SetGeometricalPosition(
768             Point(nSecondaryLocation, nPrimaryLocation),
769             Point(0, nLeadingOffset),
770             Point(0, nTrailingOffset));
771     }
772     else
773     {
774         rPosition.SetGeometricalPosition(
775             Point(nPrimaryLocation, nSecondaryLocation),
776             Point(nLeadingOffset, 0),
777             Point(nTrailingOffset, 0));
778     }
779 }
780 
GetInnerBoundingBox(model::SlideSorterModel const & rModel,const sal_Int32 nIndex) const781 ::tools::Rectangle Layouter::Implementation::GetInnerBoundingBox (
782     model::SlideSorterModel const & rModel,
783     const sal_Int32 nIndex) const
784 {
785     model::SharedPageDescriptor pDescriptor (rModel.GetPageDescriptor(nIndex));
786     if ( ! pDescriptor)
787         return ::tools::Rectangle();
788 
789     PageObjectLayouter::Part ePart = PageObjectLayouter::Part::Preview;
790 
791     if (pDescriptor->HasState(model::PageDescriptor::ST_Selected))
792         ePart = PageObjectLayouter::Part::PageObject;
793 
794     return mpPageObjectLayouter->GetBoundingBox(
795             pDescriptor, ePart,
796             PageObjectLayouter::ModelCoordinateSystem, true);
797 }
798 
GetValidHorizontalSizeRange() const799 Range Layouter::Implementation::GetValidHorizontalSizeRange() const
800 {
801     return Range(
802         mnLeftBorder + maMinimalSize.Width() + mnRightBorder,
803         mnLeftBorder + maMaximalSize.Width() + mnRightBorder);
804 }
805 
GetValidVerticalSizeRange() const806 Range Layouter::Implementation::GetValidVerticalSizeRange() const
807 {
808     return Range(
809         mnTopBorder + maMinimalSize.Height() + mnBottomBorder,
810         mnTopBorder + maMaximalSize.Height() + mnBottomBorder);
811 }
812 
GetRangeOfVisiblePageObjects(const::tools::Rectangle & aVisibleArea) const813 Range Layouter::Implementation::GetRangeOfVisiblePageObjects (const ::tools::Rectangle& aVisibleArea) const
814 {
815     // technically that's not empty, but it's the default, so...
816     if (aVisibleArea.IsEmpty())
817         return Range(-1, -1);
818 
819     const sal_Int32 nRow0 (GetRowAtPosition(aVisibleArea.Top(), true, GM_NEXT));
820     const sal_Int32 nCol0 (GetColumnAtPosition(aVisibleArea.Left(),true, GM_NEXT));
821     const sal_Int32 nRow1 (GetRowAtPosition(aVisibleArea.Bottom(), true, GM_PREVIOUS));
822     const sal_Int32 nCol1 (GetColumnAtPosition(aVisibleArea.Right(), true, GM_PREVIOUS));
823 
824     // When start and end lie in different rows then the range may include
825     // slides outside (left or right of) the given area.
826     return Range(GetIndex(nRow0,nCol0,true), GetIndex(nRow1,nCol1,true));
827 }
828 
GetTargetSize(const Size & rWindowSize,const bool bCalculateWidth,const bool bCalculateHeight) const829 Size Layouter::Implementation::GetTargetSize (
830     const Size& rWindowSize,
831     const bool bCalculateWidth,
832     const bool bCalculateHeight) const
833 {
834     if (mnColumnCount<=0 || mnRowCount<=0)
835         return maPreferredSize;
836     if ( ! (bCalculateWidth || bCalculateHeight))
837     {
838         OSL_ASSERT(bCalculateWidth || bCalculateHeight);
839         return maPreferredSize;
840     }
841 
842     // Calculate the width of each page object.
843     Size aTargetSize (0,0);
844     if (bCalculateWidth)
845         aTargetSize.setWidth(
846             (rWindowSize.Width() - mnLeftBorder - mnRightBorder
847                 - (mnColumnCount-1) * gnHorizontalGap)
848                     / mnColumnCount);
849     else if (bCalculateHeight)
850         aTargetSize.setHeight(
851             (rWindowSize.Height() - mnTopBorder - mnBottomBorder
852                 - (mnRowCount-1) * gnVerticalGap)
853                     / mnRowCount);
854 
855     if (bCalculateWidth)
856     {
857         if (aTargetSize.Width() < maMinimalSize.Width())
858             aTargetSize.setWidth(maMinimalSize.Width());
859         else if (aTargetSize.Width() > maMaximalSize.Width())
860             aTargetSize.setWidth(maMaximalSize.Width());
861     }
862     else if (bCalculateHeight)
863     {
864         if (aTargetSize.Height() < maMinimalSize.Height())
865             aTargetSize.setHeight(maMinimalSize.Height());
866         else if (aTargetSize.Height() > maMaximalSize.Height())
867             aTargetSize.setHeight(maMaximalSize.Height());
868     }
869 
870     return aTargetSize;
871 }
872 
GetIndex(const sal_Int32 nRow,const sal_Int32 nColumn,const bool bClampToValidRange) const873 sal_Int32 Layouter::Implementation::GetIndex (
874     const sal_Int32 nRow,
875     const sal_Int32 nColumn,
876     const bool bClampToValidRange) const
877 {
878     if (nRow >= 0 && nColumn >= 0)
879     {
880         const sal_Int32 nIndex (nRow * mnColumnCount + nColumn);
881         if (nIndex >= mnPageCount)
882             if (bClampToValidRange)
883                 return mnPageCount-1;
884             else
885                 return -1;
886         else
887             return nIndex;
888     }
889     else if (bClampToValidRange)
890         return 0;
891     else
892         return -1;
893 }
894 
GetPageObjectBox(const sal_Int32 nIndex,const bool bIncludeBorderAndGap) const895 ::tools::Rectangle Layouter::Implementation::GetPageObjectBox (
896     const sal_Int32 nIndex,
897     const bool bIncludeBorderAndGap) const
898 {
899     const sal_Int32 nRow (nIndex / mnColumnCount);
900     const sal_Int32 nColumn (nIndex % mnColumnCount);
901 
902     const ::tools::Rectangle aBoundingBox (GetPageObjectBox(nRow,nColumn));
903     if (bIncludeBorderAndGap)
904         return AddBorderAndGap(aBoundingBox, nRow, nColumn);
905     else
906         return aBoundingBox;
907 }
908 
GetPageObjectBox(const sal_Int32 nRow,const sal_Int32 nColumn) const909 ::tools::Rectangle Layouter::Implementation::GetPageObjectBox (
910     const sal_Int32 nRow,
911     const sal_Int32 nColumn) const
912 {
913     return ::tools::Rectangle(
914         Point (mnLeftBorder
915             + nColumn * maPageObjectSize.Width()
916             + std::max<sal_Int32>(nColumn,0) * gnHorizontalGap,
917             mnTopBorder
918             + nRow * maPageObjectSize.Height()
919             + std::max<sal_Int32>(nRow,0) * gnVerticalGap),
920         maPageObjectSize);
921 }
922 
AddBorderAndGap(const::tools::Rectangle & rBoundingBox,const sal_Int32 nRow,const sal_Int32 nColumn) const923 ::tools::Rectangle Layouter::Implementation::AddBorderAndGap (
924     const ::tools::Rectangle& rBoundingBox,
925     const sal_Int32 nRow,
926     const sal_Int32 nColumn) const
927 {
928     ::tools::Rectangle aBoundingBox (rBoundingBox);
929 
930     if (nColumn == 0)
931         aBoundingBox.SetLeft( 0 );
932     else
933         aBoundingBox.AdjustLeft( -(gnHorizontalGap/2) );
934     if (nColumn == mnColumnCount-1)
935         aBoundingBox.AdjustRight(mnRightBorder );
936     else
937         aBoundingBox.AdjustRight(gnHorizontalGap/2 );
938     if (nRow == 0)
939         aBoundingBox.SetTop( 0 );
940     else
941         aBoundingBox.AdjustTop( -(gnVerticalGap/2) );
942     if (nRow == mnRowCount-1)
943         aBoundingBox.AdjustBottom(mnBottomBorder );
944     else
945         aBoundingBox.AdjustBottom(gnVerticalGap/2 );
946     return aBoundingBox;
947 }
948 
GetTotalBoundingBox() const949 ::tools::Rectangle Layouter::Implementation::GetTotalBoundingBox() const
950 {
951     sal_Int32 nHorizontalSize = 0;
952     sal_Int32 nVerticalSize = 0;
953     if (mnColumnCount > 0)
954     {
955         sal_Int32 nRowCount = (mnPageCount+mnColumnCount-1) / mnColumnCount;
956         nHorizontalSize =
957             mnLeftBorder
958             + mnRightBorder
959             + mnColumnCount * maPageObjectSize.Width();
960         if (mnColumnCount > 1)
961             nHorizontalSize +=  (mnColumnCount-1) * gnHorizontalGap;
962         nVerticalSize =
963             mnTopBorder
964             + mnBottomBorder
965             + nRowCount * maPageObjectSize.Height();
966         if (nRowCount > 1)
967             nVerticalSize += (nRowCount-1) * gnVerticalGap;
968     }
969 
970     return ::tools::Rectangle (
971         Point(0,0),
972         Size (nHorizontalSize, nVerticalSize)
973         );
974 }
975 
CalculateVerticalLogicalInsertPosition(const Point & rModelPosition,InsertPosition & rPosition) const976 void Layouter::Implementation::CalculateVerticalLogicalInsertPosition (
977     const Point& rModelPosition,
978     InsertPosition& rPosition) const
979 {
980     const sal_Int32 nY = rModelPosition.Y() - mnTopBorder + maPageObjectSize.Height()/2;
981     const sal_Int32 nRowHeight (maPageObjectSize.Height() + gnVerticalGap);
982     const sal_Int32 nRow (::std::min(mnPageCount, nY / nRowHeight));
983     rPosition.SetLogicalPosition (
984         nRow,
985         0,
986         nRow,
987         (nRow == 0),
988         (nRow == mnRowCount),
989         (nRow >= mnMaxRowCount));
990 }
991 
992 //===== HorizontalImplementation ================================================
993 
HorizontalImplementation(const Implementation & rImplementation)994 HorizontalImplementation::HorizontalImplementation (const Implementation& rImplementation)
995     : Implementation(rImplementation)
996 {
997 }
998 
GetOrientation() const999 Layouter::Orientation HorizontalImplementation::GetOrientation() const
1000 {
1001     return Layouter::HORIZONTAL;
1002 }
1003 
CalculateRowAndColumnCount(const Size &)1004 void HorizontalImplementation::CalculateRowAndColumnCount (const Size&)
1005 {
1006     // Row and column count are fixed (for a given page count.)
1007     mnColumnCount = mnPageCount;
1008     mnRowCount = 1;
1009 }
1010 
CalculateMaxRowAndColumnCount(const Size & rWindowSize)1011 void HorizontalImplementation::CalculateMaxRowAndColumnCount (const Size& rWindowSize)
1012 {
1013     mnMaxColumnCount = (rWindowSize.Width() - mnLeftBorder - mnRightBorder)
1014         / (maPageObjectSize.Width()  + gnHorizontalGap);
1015     mnMaxRowCount = 1;
1016 }
1017 
CalculateTargetSize(const Size & rWindowSize) const1018 Size HorizontalImplementation::CalculateTargetSize (
1019     const Size& rWindowSize) const
1020 {
1021     return Implementation::GetTargetSize(rWindowSize, false, true);
1022 }
1023 
CalculateLogicalInsertPosition(const Point & rModelPosition,InsertPosition & rPosition) const1024 void HorizontalImplementation::CalculateLogicalInsertPosition (
1025     const Point& rModelPosition,
1026     InsertPosition& rPosition) const
1027 {
1028     const sal_Int32 nX = rModelPosition.X() - mnLeftBorder + maPageObjectSize.Width()/2;
1029     const sal_Int32 nColumnWidth (maPageObjectSize.Width() + gnHorizontalGap);
1030     const sal_Int32 nColumn (::std::min(mnPageCount, nX / nColumnWidth));
1031     rPosition.SetLogicalPosition (
1032         0,
1033         nColumn,
1034         nColumn,
1035         (nColumn == 0),
1036         (nColumn == mnColumnCount),
1037         (nColumn >= mnMaxColumnCount));
1038 }
1039 
1040 //===== VerticalImplementation ================================================
1041 
VerticalImplementation(const Implementation & rImplementation)1042 VerticalImplementation::VerticalImplementation (const Implementation& rImplementation)
1043     : Implementation(rImplementation)
1044 {
1045 }
1046 
GetOrientation() const1047 Layouter::Orientation VerticalImplementation::GetOrientation() const
1048 {
1049     return Layouter::VERTICAL;
1050 }
1051 
CalculateRowAndColumnCount(const Size &)1052 void VerticalImplementation::CalculateRowAndColumnCount (const Size&)
1053 {
1054     // Row and column count are fixed (for a given page count.)
1055     mnRowCount = mnPageCount;
1056     mnColumnCount = 1;
1057 
1058 }
1059 
CalculateMaxRowAndColumnCount(const Size & rWindowSize)1060 void VerticalImplementation::CalculateMaxRowAndColumnCount (const Size& rWindowSize)
1061 {
1062     mnMaxRowCount = (rWindowSize.Height() - mnTopBorder - mnBottomBorder)
1063         / (maPageObjectSize.Height()  + gnVerticalGap);
1064     mnMaxColumnCount = 1;
1065 }
1066 
CalculateTargetSize(const Size & rWindowSize) const1067 Size VerticalImplementation::CalculateTargetSize (
1068     const Size& rWindowSize) const
1069 {
1070     return Implementation::GetTargetSize(rWindowSize, true, false);
1071 }
1072 
CalculateLogicalInsertPosition(const Point & rModelPosition,InsertPosition & rPosition) const1073 void VerticalImplementation::CalculateLogicalInsertPosition (
1074     const Point& rModelPosition,
1075     InsertPosition& rPosition) const
1076 {
1077     return CalculateVerticalLogicalInsertPosition(rModelPosition, rPosition);
1078 }
1079 
1080 //===== GridImplementation ================================================
1081 
GridImplementation(sd::Window * pWindow,const std::shared_ptr<view::Theme> & rpTheme)1082 GridImplementation::GridImplementation (
1083     sd::Window *pWindow,
1084     const std::shared_ptr<view::Theme>& rpTheme)
1085     : Implementation(pWindow, rpTheme)
1086 {
1087 }
1088 
GridImplementation(const Implementation & rImplementation)1089 GridImplementation::GridImplementation (const Implementation& rImplementation)
1090     : Implementation(rImplementation)
1091 {
1092 }
1093 
GetOrientation() const1094 Layouter::Orientation GridImplementation::GetOrientation() const
1095 {
1096     return Layouter::GRID;
1097 }
1098 
CalculateRowAndColumnCount(const Size & rWindowSize)1099 void GridImplementation::CalculateRowAndColumnCount (const Size& rWindowSize)
1100 {
1101     // Calculate the column count.
1102     mnColumnCount
1103         = (rWindowSize.Width() - mnRequestedLeftBorder - mnRequestedRightBorder)
1104         / (maPreferredSize.Width()  + gnHorizontalGap);
1105     if (mnColumnCount < mnMinimalColumnCount)
1106         mnColumnCount = mnMinimalColumnCount;
1107     if (mnColumnCount > mnMaximalColumnCount)
1108         mnColumnCount = mnMaximalColumnCount;
1109     mnRowCount = (mnPageCount + mnColumnCount-1)/mnColumnCount;
1110 }
1111 
CalculateMaxRowAndColumnCount(const Size & rWindowSize)1112 void GridImplementation::CalculateMaxRowAndColumnCount (const Size& rWindowSize)
1113 {
1114     mnMaxColumnCount = (rWindowSize.Width() - mnLeftBorder - mnRightBorder)
1115         / (maPageObjectSize.Width()  + gnHorizontalGap);
1116     mnMaxRowCount = (rWindowSize.Height() - mnTopBorder - mnBottomBorder)
1117         / (maPageObjectSize.Height()  + gnVerticalGap);
1118 }
1119 
CalculateTargetSize(const Size & rWindowSize) const1120 Size GridImplementation::CalculateTargetSize (
1121     const Size& rWindowSize) const
1122 {
1123     return Implementation::GetTargetSize(rWindowSize, true, true);
1124 }
1125 
CalculateLogicalInsertPosition(const Point & rModelPosition,InsertPosition & rPosition) const1126 void GridImplementation::CalculateLogicalInsertPosition (
1127     const Point& rModelPosition,
1128     InsertPosition& rPosition) const
1129 {
1130     if (mnColumnCount == 1)
1131     {
1132         CalculateVerticalLogicalInsertPosition(rModelPosition, rPosition);
1133     }
1134     else
1135     {
1136         // Handle the general case of more than one column.
1137         sal_Int32 nRow (::std::min(
1138             mnRowCount-1,
1139             GetRowAtPosition (rModelPosition.Y(), true, GM_BOTH)));
1140         const sal_Int32 nX = rModelPosition.X() - mnLeftBorder + maPageObjectSize.Width()/2;
1141         const sal_Int32 nColumnWidth (maPageObjectSize.Width() + gnHorizontalGap);
1142         sal_Int32 nColumn (::std::min(mnColumnCount, nX / nColumnWidth));
1143         sal_Int32 nIndex (nRow * mnColumnCount + nColumn);
1144         bool bIsAtRunEnd (nColumn == mnColumnCount);
1145 
1146         if (nIndex >= mnPageCount)
1147         {
1148             nIndex = mnPageCount;
1149             nRow = mnRowCount-1;
1150             nColumn = ::std::min(::std::min(mnPageCount, mnColumnCount), nColumn);
1151             bIsAtRunEnd = true;
1152         }
1153 
1154         rPosition.SetLogicalPosition (
1155             nRow,
1156             nColumn,
1157             nIndex,
1158             (nColumn == 0),
1159             bIsAtRunEnd,
1160             (nColumn >= mnMaxColumnCount));
1161     }
1162 }
1163 
1164 //===== InsertPosition ========================================================
1165 
InsertPosition()1166 InsertPosition::InsertPosition()
1167     : mnRow(-1),
1168       mnColumn(-1),
1169       mnIndex(-1),
1170       mbIsAtRunStart(false),
1171       mbIsAtRunEnd(false),
1172       mbIsExtraSpaceNeeded(false),
1173       maLocation(0,0),
1174       maLeadingOffset(0,0),
1175       maTrailingOffset(0,0)
1176 {
1177 }
1178 
operator ==(const InsertPosition & rInsertPosition) const1179 bool InsertPosition::operator== (const InsertPosition& rInsertPosition) const
1180 {
1181     // Do not compare the geometrical information (maLocation).
1182     return mnRow==rInsertPosition.mnRow
1183         && mnColumn==rInsertPosition.mnColumn
1184         && mnIndex==rInsertPosition.mnIndex
1185         && mbIsAtRunStart==rInsertPosition.mbIsAtRunStart
1186         && mbIsAtRunEnd==rInsertPosition.mbIsAtRunEnd
1187         && mbIsExtraSpaceNeeded==rInsertPosition.mbIsExtraSpaceNeeded;
1188 }
1189 
operator !=(const InsertPosition & rInsertPosition) const1190 bool InsertPosition::operator!= (const InsertPosition& rInsertPosition) const
1191 {
1192     return !operator==(rInsertPosition);
1193 }
1194 
SetLogicalPosition(const sal_Int32 nRow,const sal_Int32 nColumn,const sal_Int32 nIndex,const bool bIsAtRunStart,const bool bIsAtRunEnd,const bool bIsExtraSpaceNeeded)1195 void InsertPosition::SetLogicalPosition (
1196     const sal_Int32 nRow,
1197     const sal_Int32 nColumn,
1198     const sal_Int32 nIndex,
1199     const bool bIsAtRunStart,
1200     const bool bIsAtRunEnd,
1201     const bool bIsExtraSpaceNeeded)
1202 {
1203     mnRow = nRow;
1204     mnColumn = nColumn;
1205     mnIndex = nIndex;
1206     mbIsAtRunStart = bIsAtRunStart;
1207     mbIsAtRunEnd = bIsAtRunEnd;
1208     mbIsExtraSpaceNeeded = bIsExtraSpaceNeeded;
1209 }
1210 
SetGeometricalPosition(const Point & rLocation,const Point & rLeadingOffset,const Point & rTrailingOffset)1211 void InsertPosition::SetGeometricalPosition(
1212     const Point& rLocation,
1213     const Point& rLeadingOffset,
1214     const Point& rTrailingOffset)
1215 {
1216     maLocation = rLocation;
1217     maLeadingOffset = rLeadingOffset;
1218     maTrailingOffset = rTrailingOffset;
1219 }
1220 
1221 } } } // end of namespace ::sd::slidesorter::namespace
1222 
1223 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1224