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