xref: /trunk/main/sfx2/source/sidebar/Deck.cxx (revision ff12d537)
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 #include "precompiled_sfx2.hxx"
23 
24 #include "Deck.hxx"
25 #include "DeckDescriptor.hxx"
26 #include "DrawHelper.hxx"
27 #include "DeckTitleBar.hxx"
28 #include "Panel.hxx"
29 #include "Theme.hxx"
30 
31 #include <tools/SvBorder.hxx>
32 
33 
34 namespace sfx2 { namespace sidebar {
35 
36 
37 namespace {
38     static const sal_Int32 MinimalPanelHeight (25);
39 }
40 
41 
42 
43 Deck::Deck (
44     const DeckDescriptor& rDeckDescriptor,
45     Window* pParentWindow)
46     : Window(pParentWindow),
47       msId(rDeckDescriptor.msId),
48       mpTitleBar(new DeckTitleBar(rDeckDescriptor.msTitle, this)),
49       maIcon(),
50       msIconURL(rDeckDescriptor.msIconURL),
51       msHighContrastIconURL(rDeckDescriptor.msHighContrastIconURL),
52       mpFiller(NULL)
53 {
54     SetBackground(Wallpaper());
55 }
56 
57 
58 
59 
60 Deck::~Deck (void)
61 {
62     Dispose();
63 }
64 
65 
66 
67 
68 void Deck::Dispose (void)
69 {
70     ::std::vector<Panel*> aPanels;
71     aPanels.swap(maPanels);
72     for (::std::vector<Panel*>::const_iterator
73              iPanel(aPanels.begin()),
74              iEnd(aPanels.end());
75          iPanel!=iEnd;
76          ++iPanel)
77     {
78         (*iPanel)->Dispose();
79     }
80 }
81 
82 
83 
84 
85 const ::rtl::OUString& Deck::GetId (void) const
86 {
87     return msId;
88 }
89 
90 
91 
92 
93 TitleBar* Deck::GetTitleBar (void) const
94 {
95     return mpTitleBar;
96 }
97 
98 
99 
100 
101 Rectangle Deck::GetContentArea (void) const
102 {
103     const Size aWindowSize (GetSizePixel());
104     const SvBorder aPadding (Theme::GetDeckPadding());
105     const int nBorderSize (Theme::GetBorderSize());
106 
107     return Rectangle(
108         aPadding.Left() + nBorderSize,
109         aPadding.Top() + nBorderSize,
110         aWindowSize.Width() - 1 - aPadding.Right() - nBorderSize,
111         aWindowSize.Height() - 1 - aPadding.Bottom() - nBorderSize);
112 }
113 
114 
115 
116 
117 ::rtl::OUString Deck::GetIconURL (const bool bIsHighContrastModeActive) const
118 {
119     if (bIsHighContrastModeActive)
120         return msHighContrastIconURL;
121     else
122         return msIconURL;
123 }
124 
125 
126 
127 
128 void Deck::Paint (const Rectangle& rUpdateArea)
129 {
130     const Size aWindowSize (GetSizePixel());
131     const SvBorder aPadding (Theme::GetDeckPadding());
132 
133     // Paint deck background outside the border.
134     DrawHelper::DrawBorder(
135         *this,
136         Rectangle(
137             0,
138             0,
139             aWindowSize.Width() - 1,
140             aWindowSize.Height() - 1),
141         aPadding,
142         Theme::GetDeckBackground(),
143         Theme::GetDeckBackground());
144 
145     // Paint the border.
146     const int nBorderSize (Theme::GetBorderSize());
147     DrawHelper::DrawBorder(
148         *this,
149         Rectangle(
150             aPadding.Left(),
151             aPadding.Top(),
152             aWindowSize.Width() - 1 - aPadding.Right(),
153             aWindowSize.Height() - 1 - aPadding.Bottom()),
154         SvBorder(nBorderSize, nBorderSize, nBorderSize, nBorderSize),
155         Theme::GetHorizontalBorderPaint(),
156         Theme::GetVerticalBorderPaint());
157 }
158 
159 
160 
161 
162 void Deck::SetPanels (const ::std::vector<Panel*>& rPanels)
163 {
164     maPanels.resize(rPanels.size());
165     ::std::copy(rPanels.begin(), rPanels.end(), maPanels.begin());
166 
167     RequestLayout();
168 }
169 
170 
171 
172 
173 void Deck::RequestLayout (void)
174 {
175     switch(maPanels.size())
176     {
177         case 0:
178             // This basically is an error but there is not much that
179             // we can do about it.
180             OSL_ASSERT(maPanels.size()>0);
181             break;
182 
183         case 1:
184             if (maPanels[0]->IsTitleBarOptional())
185             {
186                 // There is only one panel in the deck and its title
187                 // bar is optional => do not draw the title bar.
188                 LayoutSinglePanel();
189             }
190             else
191                 LayoutMultiplePanels();
192             break;
193 
194         default:
195             LayoutMultiplePanels();
196             break;
197     }
198 
199     Invalidate();
200 }
201 
202 
203 
204 
205 void Deck::LayoutSinglePanel (void)
206 {
207     Rectangle aBox (GetContentArea());
208     aBox = PlaceDeckTitle(GetTitleBar(), aBox);
209     Panel& rPanel (*maPanels.front());
210 
211     if (rPanel.IsExpanded())
212     {
213         rPanel.Show();
214         rPanel.GetTitleBar()->Hide();
215         rPanel.SetPosSizePixel(aBox.Left(), aBox.Top(), aBox.GetWidth(), aBox.GetHeight());
216         HideFiller();
217     }
218     else
219     {
220         rPanel.Hide();
221         ShowFiller(aBox);
222     }
223 }
224 
225 
226 
227 
228 void Deck::LayoutMultiplePanels (void)
229 {
230     Rectangle aBox (GetContentArea());
231     if (aBox.GetWidth()<=0 || aBox.GetHeight()<=0)
232         return;
233     aBox = PlaceDeckTitle(GetTitleBar(), aBox);
234     const sal_Int32 nWidth (aBox.GetWidth());
235     const sal_Int32 nPanelTitleBarHeight (Theme::GetPanelTitleBarHeight());
236 
237     // Determine the height that is available for panel content
238     // and count the different layouts.
239     const sal_Int32 nX = aBox.Left();
240     sal_Int32 nHeight = aBox.GetHeight();
241     sal_Int32 nFullCount (0);
242     sal_Int32 nVerticalStackCount (0);
243     for (::std::vector<Panel*>::const_iterator
244              iPanel(maPanels.begin()),
245              iEnd(maPanels.end());
246          iPanel!=iEnd;
247          ++iPanel)
248     {
249         const Panel& rPanel (**iPanel);
250 
251         nHeight -= nPanelTitleBarHeight;
252 
253         if (rPanel.IsExpanded())
254         {
255             if (rPanel.GetVerticalStackElement().is())
256             {
257                 ++nVerticalStackCount;
258                 nHeight -= rPanel.GetVerticalStackElement()->getHeightForWidth(nWidth);
259             }
260             else
261             {
262                 ++nFullCount;
263             }
264         }
265     }
266 
267     sal_Int32 nHeightPerPanel (nFullCount<=0 ? 0 : nHeight / nFullCount);
268     // The division might lead to rounding errors.  Enlarge the first
269     // panel to compensate for that.
270     sal_Int32 nHeightOfFirstPanel = nFullCount+nVerticalStackCount<=0
271         ? 0
272         : nHeightPerPanel + (nHeight - nHeightPerPanel*(nFullCount+nVerticalStackCount));
273     if (nHeightPerPanel < MinimalPanelHeight)
274     {
275         // Display a vertical scroll bar.
276         // Force height to the minimal panel height.
277         nHeightPerPanel = MinimalPanelHeight;
278         nHeightOfFirstPanel = nHeightPerPanel;
279     }
280 
281     // Assign heights and places.
282     sal_Int32 nY (aBox.Top());
283     for (::std::vector<Panel*>::const_iterator
284              iPanel(maPanels.begin()),
285              iEnd(maPanels.end());
286          iPanel!=iEnd;
287          ++iPanel)
288     {
289         Panel& rPanel (**iPanel);
290 
291         // Place the title bar.
292         TitleBar* pTitleBar = rPanel.GetTitleBar();
293         pTitleBar->SetPosSizePixel(nX, nY, nWidth, nPanelTitleBarHeight);
294         pTitleBar->Show();
295         nY += nPanelTitleBarHeight;
296 
297         if (rPanel.IsExpanded())
298         {
299             rPanel.Show();
300 
301             // Place the panel.
302             sal_Int32 nPanelHeight (0);
303             if (rPanel.GetVerticalStackElement().is())
304                 nPanelHeight = rPanel.GetVerticalStackElement()->getHeightForWidth(nWidth);
305             else
306                 if (iPanel==maPanels.begin())
307                     nPanelHeight = nHeightOfFirstPanel;
308                 else
309                     nPanelHeight = nHeightPerPanel;
310 
311             rPanel.SetPosSizePixel(nX, nY, nWidth, nPanelHeight);
312             nY += nPanelHeight;
313         }
314         else
315             rPanel.Hide();
316     }
317 
318     if (nY < aBox.Bottom())
319         ShowFiller(Rectangle(aBox.Left(), nY, aBox.Right(), aBox.Bottom()));
320     else
321         HideFiller();
322 }
323 
324 
325 
326 
327 Rectangle Deck::PlaceDeckTitle (
328     TitleBar* pDeckTitleBar,
329     const Rectangle& rAvailableSpace)
330 {
331     if (pDeckTitleBar == NULL)
332     {
333         OSL_ASSERT(pDeckTitleBar!=NULL);
334         return rAvailableSpace;
335     }
336 
337     const sal_Int32 nDeckTitleBarHeight (Theme::GetDeckTitleBarHeight());
338     pDeckTitleBar->SetPosSizePixel(
339         rAvailableSpace.Left(),
340         rAvailableSpace.Top(),
341         rAvailableSpace.GetWidth(),
342         nDeckTitleBarHeight);
343     pDeckTitleBar->Show();
344     return Rectangle(
345         rAvailableSpace.Left(),
346         rAvailableSpace.Top() + nDeckTitleBarHeight,
347         rAvailableSpace.Right(),
348         rAvailableSpace.Bottom());
349 }
350 
351 
352 
353 
354 void Deck::ShowFiller (const Rectangle& rBox)
355 {
356     if (mpFiller == NULL)
357     {
358         mpFiller = new Window(this);
359         mpFiller->SetBackground(Theme::GetDeckBackground().GetWallpaper());
360     }
361     mpFiller->SetPosSizePixel(rBox.TopLeft(), rBox.GetSize());
362     mpFiller->Show();
363 }
364 
365 
366 
367 
368 void Deck::HideFiller (void)
369 {
370     if (mpFiller != NULL)
371         mpFiller->Hide();
372 }
373 
374 
375 
376 } } // end of namespace sfx2::sidebar
377