xref: /AOO42X/main/sfx2/source/sidebar/Deck.cxx (revision 055746153e5cd78346b485d23b1c8e3408d513f1)
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 "DeckLayouter.hxx"
27 #include "DrawHelper.hxx"
28 #include "DeckTitleBar.hxx"
29 #include "PanelTitleBar.hxx"
30 #include "Paint.hxx"
31 #include "Panel.hxx"
32 #include "ToolBoxBackground.hxx"
33 #include "sfx2/sidebar/Tools.hxx"
34 #include "sfx2/sidebar/Theme.hxx"
35 
36 #include <vcl/dockwin.hxx>
37 #include <vcl/scrbar.hxx>
38 #include <tools/svborder.hxx>
39 
40 #include <boost/bind.hpp>
41 
42 using namespace ::com::sun::star;
43 using namespace ::com::sun::star::uno;
44 
45 namespace sfx2 { namespace sidebar {
46 
47 namespace {
48     static const sal_Int32 MinimalPanelHeight (25);
49 }
50 
Deck(const DeckDescriptor & rDeckDescriptor,Window * pParentWindow,const::boost::function<void (void)> & rCloserAction)51 Deck::Deck (
52     const DeckDescriptor& rDeckDescriptor,
53     Window* pParentWindow,
54     const ::boost::function<void(void)>& rCloserAction)
55     : Window(pParentWindow, 0),
56       msId(rDeckDescriptor.msId),
57       maIcon(),
58       msIconURL(rDeckDescriptor.msIconURL),
59       msHighContrastIconURL(rDeckDescriptor.msHighContrastIconURL),
60       maPanels(),
61       mpTitleBar(new DeckTitleBar(rDeckDescriptor.msTitle, this, rCloserAction)),
62       mpScrollClipWindow(new Window(this)),
63       mpScrollContainer(new ScrollContainerWindow(mpScrollClipWindow.get())),
64       mpFiller(new Window(this)),
65       mpVerticalScrollBar(new ScrollBar(this))
66 {
67     SetBackground(Wallpaper());
68 
69     mpScrollClipWindow->SetBackground(Wallpaper());
70     mpScrollClipWindow->Show();
71 
72     mpScrollContainer->SetStyle(mpScrollContainer->GetStyle() | WB_DIALOGCONTROL);
73     mpScrollContainer->SetBackground(Wallpaper());
74     mpScrollContainer->Show();
75 
76     mpVerticalScrollBar->SetScrollHdl(LINK(this, Deck, HandleVerticalScrollBarChange));
77 
78 #ifdef DEBUG
79     SetText(A2S("Deck"));
80     mpScrollClipWindow->SetText(A2S("ScrollClipWindow"));
81     mpFiller->SetText(A2S("Filler"));
82     mpVerticalScrollBar->SetText(A2S("VerticalScrollBar"));
83 #endif
84 }
85 
~Deck(void)86 Deck::~Deck (void)
87 {
88     Dispose();
89 
90     // We have to explicitly trigger the destruction of panels.
91     // Otherwise that is done by one of our base class destructors
92     // without updating maPanels.
93     maPanels.clear();
94 }
95 
Dispose(void)96 void Deck::Dispose (void)
97 {
98     SharedPanelContainer aPanels;
99     aPanels.swap(maPanels);
100     for (SharedPanelContainer::iterator
101             iPanel(aPanels.begin()),
102             iEnd(aPanels.end());
103          iPanel!=iEnd;
104          ++iPanel)
105     {
106         if (*iPanel)
107         {
108             (*iPanel)->Dispose();
109             OSL_ASSERT(iPanel->unique());
110             iPanel->reset();
111         }
112     }
113 
114     mpTitleBar.reset();
115     mpFiller.reset();
116     mpVerticalScrollBar.reset();
117 }
118 
GetId(void) const119 const ::rtl::OUString& Deck::GetId (void) const
120 {
121     return msId;
122 }
123 
GetTitleBar(void) const124 DeckTitleBar* Deck::GetTitleBar (void) const
125 {
126     return mpTitleBar.get();
127 }
128 
GetContentArea(void) const129 Rectangle Deck::GetContentArea (void) const
130 {
131     const Size aWindowSize (GetSizePixel());
132     const int nBorderSize (Theme::GetInteger(Theme::Int_DeckBorderSize));
133 
134     return Rectangle(
135         Theme::GetInteger(Theme::Int_DeckLeftPadding) + nBorderSize,
136         Theme::GetInteger(Theme::Int_DeckTopPadding) + nBorderSize,
137         aWindowSize.Width() - 1 - Theme::GetInteger(Theme::Int_DeckRightPadding) - nBorderSize,
138         aWindowSize.Height() - 1 - Theme::GetInteger(Theme::Int_DeckBottomPadding) - nBorderSize);
139 }
140 
GetIconURL(const bool bIsHighContrastModeActive) const141 ::rtl::OUString Deck::GetIconURL (const bool bIsHighContrastModeActive) const
142 {
143     if (bIsHighContrastModeActive)
144         return msHighContrastIconURL;
145     else
146         return msIconURL;
147 }
148 
Paint(const Rectangle & rUpdateArea)149 void Deck::Paint (const Rectangle& rUpdateArea)
150 {
151     (void) rUpdateArea;
152 
153     const Size aWindowSize (GetSizePixel());
154     const SvBorder aPadding (
155             Theme::GetInteger(Theme::Int_DeckLeftPadding),
156             Theme::GetInteger(Theme::Int_DeckTopPadding),
157             Theme::GetInteger(Theme::Int_DeckRightPadding),
158             Theme::GetInteger(Theme::Int_DeckBottomPadding));
159 
160     // Paint deck background outside the border.
161     Rectangle aBox(
162         0,
163         0,
164         aWindowSize.Width() - 1,
165         aWindowSize.Height() - 1);
166     DrawHelper::DrawBorder(
167         *this,
168         aBox,
169         aPadding,
170         Theme::GetPaint(Theme::Paint_DeckBackground),
171         Theme::GetPaint(Theme::Paint_DeckBackground));
172 
173     // Paint the border.
174     const int nBorderSize (Theme::GetInteger(Theme::Int_DeckBorderSize));
175     aBox.Left() += aPadding.Left();
176     aBox.Top() += aPadding.Top();
177     aBox.Right() -= aPadding.Right();
178     aBox.Bottom() -= aPadding.Bottom();
179     const sfx2::sidebar::Paint& rHorizontalBorderPaint (Theme::GetPaint(Theme::Paint_HorizontalBorder));
180     DrawHelper::DrawBorder(
181         *this,
182         aBox,
183         SvBorder(nBorderSize, nBorderSize, nBorderSize, nBorderSize),
184         rHorizontalBorderPaint,
185         Theme::GetPaint(Theme::Paint_VerticalBorder));
186 }
187 
DataChanged(const DataChangedEvent & rEvent)188 void Deck::DataChanged (const DataChangedEvent& rEvent)
189 {
190     (void)rEvent;
191     RequestLayout();
192 }
193 
Notify(NotifyEvent & rEvent)194 long Deck::Notify (NotifyEvent& rEvent)
195 {
196     if (rEvent.GetType() == EVENT_COMMAND)
197     {
198         CommandEvent* pCommandEvent = reinterpret_cast<CommandEvent*>(rEvent.GetData());
199         if (pCommandEvent != NULL)
200             switch (pCommandEvent->GetCommand())
201             {
202                 case COMMAND_WHEEL:
203                     return ProcessWheelEvent(pCommandEvent, rEvent)
204                         ? sal_True
205                         : sal_False;
206 
207                 default:
208                     break;
209             }
210     }
211 
212     return Window::Notify(rEvent);
213 }
214 
ProcessWheelEvent(CommandEvent * pCommandEvent,NotifyEvent & rEvent)215 bool Deck::ProcessWheelEvent (
216     CommandEvent* pCommandEvent,
217     NotifyEvent& rEvent)
218 {
219     if ( ! mpVerticalScrollBar)
220         return false;
221     if ( ! mpVerticalScrollBar->IsVisible())
222         return false;
223 
224     // Ignore all wheel commands from outside the vertical scroll bar.
225     // Otherwise after a scroll we might land on a spin field and
226     // subsequent wheel events would change the value of that control.
227     if (rEvent.GetWindow() != mpVerticalScrollBar.get())
228         return true;
229 
230     // Get the wheel data and check that it describes a valid vertical
231     // scroll.
232     const CommandWheelData* pData = pCommandEvent->GetWheelData();
233     if (pData==NULL
234         || pData->GetModifier()
235         || pData->GetMode() != COMMAND_WHEEL_SCROLL
236         || pData->IsHorz())
237         return false;
238 
239     // Execute the actual scroll action.
240     long nDelta = pData->GetDelta();
241     mpVerticalScrollBar->DoScroll(
242         mpVerticalScrollBar->GetThumbPos() - nDelta);
243     return true;
244 }
245 
SetPanels(const SharedPanelContainer & rPanels)246 void Deck::SetPanels (const SharedPanelContainer& rPanels)
247 {
248     maPanels = rPanels;
249 
250     RequestLayout();
251 }
252 
GetPanels(void) const253 const SharedPanelContainer& Deck::GetPanels (void) const
254 {
255     return maPanels;
256 }
257 
RequestLayout(void)258 void Deck::RequestLayout (void)
259 {
260     DeckLayouter::LayoutDeck(
261         GetContentArea(),
262         maPanels,
263         *GetTitleBar(),
264         *mpScrollClipWindow,
265         *mpScrollContainer,
266         *mpFiller,
267         *mpVerticalScrollBar);
268 }
269 
GetPanelParentWindow(void)270 ::Window* Deck::GetPanelParentWindow (void)
271 {
272     return mpScrollContainer.get();
273 }
274 
ShowPanel(const Panel & rPanel)275 void Deck::ShowPanel (const Panel& rPanel)
276 {
277     if (mpVerticalScrollBar && mpVerticalScrollBar->IsVisible())
278     {
279         // Get vertical extent of the panel.
280         sal_Int32 nPanelTop (rPanel.GetPosPixel().Y());
281         const sal_Int32 nPanelBottom (nPanelTop + rPanel.GetSizePixel().Height() - 1);
282         // Add the title bar into the extent.
283         if (rPanel.GetTitleBar() != NULL && rPanel.GetTitleBar()->IsVisible())
284             nPanelTop = rPanel.GetTitleBar()->GetPosPixel().Y();
285 
286         // Determine what the new thumb position should be like.
287         // When the whole panel does not fit then make its top visible
288         // and it off at the bottom.
289         sal_Int32 nNewThumbPos (mpVerticalScrollBar->GetThumbPos());
290         if (nPanelBottom >= nNewThumbPos+mpVerticalScrollBar->GetVisibleSize())
291             nNewThumbPos = nPanelBottom - mpVerticalScrollBar->GetVisibleSize();
292         if (nPanelTop < nNewThumbPos)
293             nNewThumbPos = nPanelTop;
294 
295         mpVerticalScrollBar->SetThumbPos(nNewThumbPos);
296         mpScrollContainer->SetPosPixel(
297             Point(
298                 mpScrollContainer->GetPosPixel().X(),
299                 -nNewThumbPos));
300     }
301 }
302 
GetWindowClassification(const Window * pWindow)303 const char* GetWindowClassification (const Window* pWindow)
304 {
305     const String& rsName (pWindow->GetText());
306     if (rsName.Len() > 0)
307     {
308         return ::rtl::OUStringToOString(rsName, RTL_TEXTENCODING_ASCII_US).getStr();
309     }
310     else
311     {
312         static char msWindow[] = "window";
313         return msWindow;
314     }
315 }
316 
PrintWindowSubTree(Window * pRoot,int nIndentation)317 void Deck::PrintWindowSubTree (Window* pRoot, int nIndentation)
318 {
319     static const char* sIndentation = "                                                                  ";
320     const Point aLocation (pRoot->GetPosPixel());
321     const Size aSize (pRoot->GetSizePixel());
322     const char* sClassification = GetWindowClassification(pRoot);
323     const char* sVisible = pRoot->IsVisible() ? "visible" : "hidden";
324     OSL_TRACE("%s%x %s %s +%d+%d x%dx%d",
325         sIndentation+strlen(sIndentation)-nIndentation*4,
326         pRoot,
327         sClassification,
328         sVisible,
329         aLocation.X(),aLocation.Y(),
330         aSize.Width(),aSize.Height());
331 
332     const sal_uInt16 nChildCount (pRoot->GetChildCount());
333     for (sal_uInt16 nIndex=0; nIndex<nChildCount; ++nIndex)
334         PrintWindowSubTree(pRoot->GetChild(nIndex), nIndentation+1);
335 }
336 
PrintWindowTree(void)337 void Deck::PrintWindowTree (void)
338 {
339     PrintWindowSubTree(this, 0);
340 }
341 
PrintWindowTree(const::std::vector<Panel * > & rPanels)342 void Deck::PrintWindowTree (const ::std::vector<Panel*>& rPanels)
343 {
344     (void)rPanels;
345 
346     PrintWindowTree();
347 }
348 
IMPL_LINK(Deck,HandleVerticalScrollBarChange,void *,EMPTYARG)349 IMPL_LINK(Deck, HandleVerticalScrollBarChange,void*, EMPTYARG)
350 {
351     const sal_Int32 nYOffset (-mpVerticalScrollBar->GetThumbPos());
352     mpScrollContainer->SetPosPixel(
353         Point(
354             mpScrollContainer->GetPosPixel().X(),
355             nYOffset));
356     return sal_True;
357 }
358 
359 //----- Deck::ScrollContainerWindow -------------------------------------------
360 
ScrollContainerWindow(Window * pParentWindow)361 Deck::ScrollContainerWindow::ScrollContainerWindow (Window* pParentWindow)
362     : Window(pParentWindow),
363       maSeparators()
364 {
365 #ifdef DEBUG
366     SetText(A2S("ScrollContainerWindow"));
367 #endif
368 }
369 
~ScrollContainerWindow(void)370 Deck::ScrollContainerWindow::~ScrollContainerWindow (void)
371 {
372 }
373 
Paint(const Rectangle & rUpdateArea)374 void Deck::ScrollContainerWindow::Paint (const Rectangle& rUpdateArea)
375 {
376     (void)rUpdateArea;
377 
378     // Paint the separators.
379     const sal_Int32 nSeparatorHeight (Theme::GetInteger(Theme::Int_DeckSeparatorHeight));
380     const sal_Int32 nLeft (0);
381     const sal_Int32 nRight (GetSizePixel().Width()-1);
382     const sfx2::sidebar::Paint& rHorizontalBorderPaint (Theme::GetPaint(Theme::Paint_HorizontalBorder));
383     for (::std::vector<sal_Int32>::const_iterator iY(maSeparators.begin()), iEnd(maSeparators.end());
384          iY!=iEnd;
385          ++iY)
386     {
387         DrawHelper::DrawHorizontalLine(
388             *this,
389             nLeft,
390             nRight,
391             *iY,
392             nSeparatorHeight,
393             rHorizontalBorderPaint);
394     }
395 }
396 
SetSeparators(const::std::vector<sal_Int32> & rSeparators)397 void Deck::ScrollContainerWindow::SetSeparators (const ::std::vector<sal_Int32>& rSeparators)
398 {
399     maSeparators = rSeparators;
400 }
401 
402 } } // end of namespace sfx2::sidebar
403 
404 /* vim: set noet sw=4 ts=4: */
405