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