1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "precompiled_sd.hxx"
25 
26 #include "view/SlsPageObjectLayouter.hxx"
27 
28 #include "model/SlsPageDescriptor.hxx"
29 #include "view/SlsFontProvider.hxx"
30 #include "view/SlsTheme.hxx"
31 #include "tools/IconCache.hxx"
32 #include "Window.hxx"
33 #include "res_bmp.hrc"
34 
35 namespace sd { namespace slidesorter { namespace view {
36 
37 namespace {
38 const static sal_Int32 gnLeftPageNumberOffset = 2;
39 const static sal_Int32 gnRightPageNumberOffset = 5;
40 const static sal_Int32 gnOuterBorderWidth = 5;
41 const static sal_Int32 gnInfoAreaMinWidth = 26;
42 }
43 
PageObjectLayouter(const::boost::shared_ptr<Theme> & rpTheme,const Size & rPageObjectWindowSize,const Size & rPageSize,const SharedSdWindow & rpWindow,const sal_Int32 nPageCount)44 PageObjectLayouter::PageObjectLayouter (
45     const ::boost::shared_ptr<Theme>& rpTheme,
46     const Size& rPageObjectWindowSize,
47     const Size& rPageSize,
48     const SharedSdWindow& rpWindow,
49     const sal_Int32 nPageCount)
50     : mpWindow(rpWindow),
51       maPageObjectSize(rPageObjectWindowSize.Width(), rPageObjectWindowSize.Height()),
52       mnModelToWindowScale(1),
53       maPageObjectBoundingBox(),
54       maPageNumberAreaBoundingBox(),
55       maPreviewBoundingBox(),
56       maTransitionEffectBoundingBox(),
57       maTransitionEffectIcon(IconCache::Instance().GetIcon(BMP_FADE_EFFECT_INDICATOR)),
58       mpPageNumberFont(Theme::GetFont(Theme::Font_PageNumber, *rpWindow))
59 {
60     const Size aPageNumberAreaSize (GetPageNumberAreaSize(nPageCount));
61 
62     const int nMaximumBorderWidth (gnOuterBorderWidth);
63     const int nFocusIndicatorWidth (rpTheme->GetIntegerValue(Theme::Integer_FocusIndicatorWidth));
64 
65     maPreviewBoundingBox = CalculatePreviewBoundingBox(
66         maPageObjectSize,
67         Size(rPageSize.Width(), rPageSize.Height()),
68         aPageNumberAreaSize.Width(),
69         nFocusIndicatorWidth);
70     maFocusIndicatorBoundingBox = Rectangle(Point(0,0), maPageObjectSize);
71     maPageObjectBoundingBox = Rectangle(
72         Point(
73             nFocusIndicatorWidth,
74             nFocusIndicatorWidth),
75         Size(
76             maPageObjectSize.Width()-2*nFocusIndicatorWidth,
77             maPageObjectSize.Height()-2*nFocusIndicatorWidth));
78 
79     maPageNumberAreaBoundingBox = Rectangle(
80         Point(
81             std::max(gnLeftPageNumberOffset,
82                 sal_Int32(maPreviewBoundingBox.Left()
83                 - gnRightPageNumberOffset
84                 - aPageNumberAreaSize.Width())),
85             nMaximumBorderWidth),
86         aPageNumberAreaSize);
87 
88     const Size aIconSize (maTransitionEffectIcon.GetSizePixel());
89     maTransitionEffectBoundingBox = Rectangle(
90         Point(
91             (maPreviewBoundingBox.Left() - aIconSize.Width()) / 2,
92             maPreviewBoundingBox.Bottom() - aIconSize.Height()),
93         aIconSize);
94 }
95 
96 
97 
98 
~PageObjectLayouter(void)99 PageObjectLayouter::~PageObjectLayouter(void)
100 {
101 }
102 
103 
104 
105 
CalculatePreviewBoundingBox(Size & rPageObjectSize,const Size & rPageSize,const sal_Int32 nPageNumberAreaWidth,const sal_Int32 nFocusIndicatorWidth)106 Rectangle PageObjectLayouter::CalculatePreviewBoundingBox (
107     Size& rPageObjectSize,
108     const Size& rPageSize,
109     const sal_Int32 nPageNumberAreaWidth,
110     const sal_Int32 nFocusIndicatorWidth)
111 {
112     const sal_Int32 nIconWidth (maTransitionEffectIcon.GetSizePixel().Width());
113     const sal_Int32 nLeftAreaWidth (
114         ::std::max(
115             gnInfoAreaMinWidth,
116             gnRightPageNumberOffset
117                 + ::std::max(
118                     nPageNumberAreaWidth,
119                     nIconWidth)));
120     sal_Int32 nPreviewWidth;
121     sal_Int32 nPreviewHeight;
122     const double nPageAspectRatio (double(rPageSize.Width()) / double(rPageSize.Height()));
123     if (rPageObjectSize.Height() == 0)
124     {
125         // Calculate height so that the preview fills the available
126         // horizontal space completely while observing the aspect ratio of
127         // the preview.
128         nPreviewWidth = rPageObjectSize.Width()
129             - nLeftAreaWidth - gnOuterBorderWidth - 2*nFocusIndicatorWidth - 1;
130         nPreviewHeight = ::basegfx::fround(nPreviewWidth / nPageAspectRatio);
131         rPageObjectSize.setHeight(nPreviewHeight + 2*gnOuterBorderWidth + 2*nFocusIndicatorWidth + 1);
132     }
133     else if (rPageObjectSize.Width() == 0)
134     {
135         // Calculate the width of the page object so that the preview fills
136         // the available vertical space completely while observing the
137         // aspect ratio of the preview.
138         nPreviewHeight = rPageObjectSize.Height() - 2*gnOuterBorderWidth - 2*nFocusIndicatorWidth - 1;
139         nPreviewWidth = ::basegfx::fround(nPreviewHeight * nPageAspectRatio);
140         rPageObjectSize.setWidth(nPreviewWidth
141             + nLeftAreaWidth + gnOuterBorderWidth + 2*nFocusIndicatorWidth + 1);
142 
143     }
144     else
145     {
146         // The size of the page object is given.  Calculate the size of the
147         // preview.
148         nPreviewWidth = rPageObjectSize.Width()
149             - nLeftAreaWidth - gnOuterBorderWidth - 2*nFocusIndicatorWidth - 1;
150         nPreviewHeight = rPageObjectSize.Height()
151             - gnOuterBorderWidth - 2*nFocusIndicatorWidth - 1;
152         if (double(nPreviewWidth)/double(nPreviewHeight) > nPageAspectRatio)
153             nPreviewWidth = ::basegfx::fround(nPreviewHeight * nPageAspectRatio);
154         else
155             nPreviewHeight = ::basegfx::fround(nPreviewWidth / nPageAspectRatio);
156     }
157     // When the preview does not fill the available space completely then
158     // place it flush right and vertically centered.
159     const int nLeft (rPageObjectSize.Width()
160         - gnOuterBorderWidth - nPreviewWidth - nFocusIndicatorWidth - 1);
161     const int nTop ((rPageObjectSize.Height() - nPreviewHeight)/2);
162     return Rectangle(
163         nLeft,
164         nTop,
165         nLeft + nPreviewWidth,
166         nTop + nPreviewHeight);
167 }
168 
169 
170 
171 
GetBoundingBox(const model::SharedPageDescriptor & rpPageDescriptor,const Part ePart,const CoordinateSystem eCoordinateSystem)172 Rectangle PageObjectLayouter::GetBoundingBox (
173     const model::SharedPageDescriptor& rpPageDescriptor,
174     const Part ePart,
175     const CoordinateSystem eCoordinateSystem)
176 {
177     OSL_ASSERT(rpPageDescriptor);
178     Point aLocation (rpPageDescriptor ? rpPageDescriptor->GetLocation() : Point(0,0));
179     return GetBoundingBox(aLocation, ePart, eCoordinateSystem);
180 }
181 
182 
183 
184 
GetBoundingBox(const Point & rPageObjectLocation,const Part ePart,const CoordinateSystem eCoordinateSystem)185 Rectangle PageObjectLayouter::GetBoundingBox (
186     const Point& rPageObjectLocation,
187     const Part ePart,
188     const CoordinateSystem eCoordinateSystem)
189 {
190     Rectangle aBoundingBox;
191     switch (ePart)
192     {
193         case FocusIndicator:
194             aBoundingBox = maFocusIndicatorBoundingBox;
195             break;
196 
197         case PageObject:
198         case MouseOverIndicator:
199             aBoundingBox = maPageObjectBoundingBox;
200             break;
201 
202         case Preview:
203             aBoundingBox = maPreviewBoundingBox;
204             break;
205 
206         case PageNumber:
207             aBoundingBox = maPageNumberAreaBoundingBox;
208             break;
209 
210         case Name:
211             aBoundingBox = maPageNumberAreaBoundingBox;
212             break;
213 
214         case TransitionEffectIndicator:
215             aBoundingBox = maTransitionEffectBoundingBox;
216             break;
217     }
218 
219     // Adapt coordinates to the requested coordinate system.
220     Point aLocation (rPageObjectLocation);
221     if (eCoordinateSystem == WindowCoordinateSystem)
222         aLocation += mpWindow->GetMapMode().GetOrigin();
223 
224     return Rectangle(
225         aBoundingBox.TopLeft() + aLocation,
226         aBoundingBox.BottomRight() + aLocation);
227 }
228 
229 
230 
231 
GetSize(const Part ePart,const CoordinateSystem eCoordinateSystem)232 Size PageObjectLayouter::GetSize (
233     const Part ePart,
234     const CoordinateSystem eCoordinateSystem)
235 {
236     return GetBoundingBox(Point(0,0), ePart, eCoordinateSystem).GetSize();
237 }
238 
239 
240 
241 
GetPageNumberAreaSize(const int nPageCount)242 Size PageObjectLayouter::GetPageNumberAreaSize (const int nPageCount)
243 {
244     OSL_ASSERT(mpWindow);
245 
246     // Set the correct font.
247     Font aOriginalFont (mpWindow->GetFont());
248     if (mpPageNumberFont)
249         mpWindow->SetFont(*mpPageNumberFont);
250 
251     String sPageNumberTemplate;
252     if (nPageCount < 10)
253         sPageNumberTemplate = String::CreateFromAscii("9");
254     else if (nPageCount < 100)
255         sPageNumberTemplate = String::CreateFromAscii("99");
256     else if (nPageCount < 200)
257         // Just for the case that 1 is narrower than 9.
258         sPageNumberTemplate = String::CreateFromAscii("199");
259     else if (nPageCount < 1000)
260         sPageNumberTemplate = String::CreateFromAscii("999");
261     else
262         sPageNumberTemplate = String::CreateFromAscii("9999");
263     // More then 9999 pages are not handled.
264 
265     const Size aSize (
266         mpWindow->GetTextWidth(sPageNumberTemplate),
267         mpWindow->GetTextHeight());
268 
269     mpWindow->SetFont(aOriginalFont);
270 
271     return aSize;
272 }
273 
274 
275 
276 
GetTransitionEffectIcon(void) const277 Image PageObjectLayouter::GetTransitionEffectIcon (void) const
278 {
279     return maTransitionEffectIcon;
280 }
281 
282 
283 } } } // end of namespace ::sd::slidesorter::view
284