Branch libreoffice-5-0-4
[LibreOffice.git] / sfx2 / source / sidebar / Deck.cxx
blobd5dc5d30b9657bef0d2fe825d8eb05f5e67d32fa
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "Deck.hxx"
21 #include "DeckDescriptor.hxx"
22 #include "DeckLayouter.hxx"
23 #include "DrawHelper.hxx"
24 #include "DeckTitleBar.hxx"
25 #include "PanelTitleBar.hxx"
26 #include "Paint.hxx"
27 #include "Panel.hxx"
28 #include <sfx2/sidebar/Tools.hxx>
29 #include <sfx2/sidebar/Theme.hxx>
31 #include <vcl/dockwin.hxx>
32 #include <vcl/scrbar.hxx>
33 #include <tools/svborder.hxx>
35 using namespace css;
36 using namespace css::uno;
38 namespace sfx2 { namespace sidebar {
40 Deck::Deck(const DeckDescriptor& rDeckDescriptor, vcl::Window* pParentWindow,
41 const std::function<void()>& rCloserAction)
42 : Window(pParentWindow, 0)
43 , msId(rDeckDescriptor.msId)
44 , maIcon()
45 , mnMinimalWidth(0)
46 , maPanels()
47 , mpTitleBar(VclPtr<DeckTitleBar>::Create(rDeckDescriptor.msTitle, this, rCloserAction))
48 , mpScrollClipWindow(VclPtr<vcl::Window>::Create(this))
49 , mpScrollContainer(VclPtr<ScrollContainerWindow>::Create(mpScrollClipWindow.get()))
50 , mpFiller(VclPtr<vcl::Window>::Create(this))
51 , mpVerticalScrollBar(VclPtr<ScrollBar>::Create(this))
53 mpScrollClipWindow->SetBackground(Wallpaper());
54 mpScrollClipWindow->Show();
56 mpScrollContainer->SetStyle(mpScrollContainer->GetStyle() | WB_DIALOGCONTROL);
57 mpScrollContainer->SetBackground(Wallpaper());
58 mpScrollContainer->Show();
60 mpVerticalScrollBar->SetScrollHdl(LINK(this, Deck, HandleVerticalScrollBarChange));
62 #ifdef DEBUG
63 SetText(OUString("Deck"));
64 mpScrollClipWindow->SetText(OUString("ScrollClipWindow"));
65 mpFiller->SetText(OUString("Filler"));
66 mpVerticalScrollBar->SetText(OUString("VerticalScrollBar"));
67 #endif
70 Deck::~Deck()
72 disposeOnce();
75 void Deck::dispose()
77 SharedPanelContainer aPanels;
78 aPanels.swap(maPanels);
80 // We have to explicitly trigger the destruction of panels.
81 // Otherwise that is done by one of our base class destructors
82 // without updating maPanels.
83 for (size_t i = 0; i < aPanels.size(); i++)
84 aPanels[i].disposeAndClear();
86 mpTitleBar.disposeAndClear();
87 mpFiller.disposeAndClear();
88 mpVerticalScrollBar.disposeAndClear();
89 mpScrollContainer.disposeAndClear();
90 mpScrollClipWindow.disposeAndClear();
92 vcl::Window::dispose();
95 DeckTitleBar* Deck::GetTitleBar() const
97 return mpTitleBar.get();
100 Rectangle Deck::GetContentArea() const
102 const Size aWindowSize (GetSizePixel());
103 const int nBorderSize (Theme::GetInteger(Theme::Int_DeckBorderSize));
105 return Rectangle(
106 Theme::GetInteger(Theme::Int_DeckLeftPadding) + nBorderSize,
107 Theme::GetInteger(Theme::Int_DeckTopPadding) + nBorderSize,
108 aWindowSize.Width() - 1 - Theme::GetInteger(Theme::Int_DeckRightPadding) - nBorderSize,
109 aWindowSize.Height() - 1 - Theme::GetInteger(Theme::Int_DeckBottomPadding) - nBorderSize);
112 void Deck::ApplySettings(vcl::RenderContext& rRenderContext)
114 rRenderContext.SetBackground(Wallpaper());
117 void Deck::Paint(vcl::RenderContext& rRenderContext, const Rectangle& /*rUpdateArea*/)
119 const Size aWindowSize (GetSizePixel());
120 const SvBorder aPadding(Theme::GetInteger(Theme::Int_DeckLeftPadding),
121 Theme::GetInteger(Theme::Int_DeckTopPadding),
122 Theme::GetInteger(Theme::Int_DeckRightPadding),
123 Theme::GetInteger(Theme::Int_DeckBottomPadding));
125 // Paint deck background outside the border.
126 Rectangle aBox(0, 0, aWindowSize.Width() - 1, aWindowSize.Height() - 1);
127 DrawHelper::DrawBorder(rRenderContext, aBox, aPadding,
128 Theme::GetPaint(Theme::Paint_DeckBackground),
129 Theme::GetPaint(Theme::Paint_DeckBackground));
131 // Paint the border.
132 const int nBorderSize(Theme::GetInteger(Theme::Int_DeckBorderSize));
133 aBox.Left() += aPadding.Left();
134 aBox.Top() += aPadding.Top();
135 aBox.Right() -= aPadding.Right();
136 aBox.Bottom() -= aPadding.Bottom();
137 const sfx2::sidebar::Paint& rHorizontalBorderPaint(Theme::GetPaint(Theme::Paint_HorizontalBorder));
138 DrawHelper::DrawBorder(rRenderContext, aBox,
139 SvBorder(nBorderSize, nBorderSize, nBorderSize, nBorderSize),
140 rHorizontalBorderPaint,
141 Theme::GetPaint(Theme::Paint_VerticalBorder));
144 void Deck::DataChanged (const DataChangedEvent& rEvent)
146 (void)rEvent;
147 RequestLayout();
150 bool Deck::Notify (NotifyEvent& rEvent)
152 if (rEvent.GetType() == MouseNotifyEvent::COMMAND)
154 CommandEvent* pCommandEvent = static_cast<CommandEvent*>(rEvent.GetData());
155 if (pCommandEvent != NULL)
156 switch (pCommandEvent->GetCommand())
158 case CommandEventId::Wheel:
159 return ProcessWheelEvent(pCommandEvent);
161 default:
162 break;
166 return Window::Notify(rEvent);
169 bool Deck::ProcessWheelEvent(CommandEvent* pCommandEvent)
171 if ( ! mpVerticalScrollBar)
172 return false;
173 if ( ! mpVerticalScrollBar->IsVisible())
174 return false;
176 // Get the wheel data and check that it describes a valid vertical
177 // scroll.
178 const CommandWheelData* pData = pCommandEvent->GetWheelData();
179 if (pData==NULL
180 || pData->GetModifier()
181 || pData->GetMode() != CommandWheelMode::SCROLL
182 || pData->IsHorz())
183 return false;
185 // Execute the actual scroll action.
186 long nDelta = pData->GetDelta();
187 mpVerticalScrollBar->DoScroll(
188 mpVerticalScrollBar->GetThumbPos() - nDelta);
189 return true;
193 * This container may contain existing panels that are
194 * being re-used, and new ones too.
196 void Deck::ResetPanels(const SharedPanelContainer& rPanels)
198 // First dispose old panels we no longer need.
199 for (size_t i = 0; i < maPanels.size(); i++)
201 bool bFound = false;
202 for (size_t j = 0; j < rPanels.size(); j++)
203 bFound = bFound || (maPanels[i].get() == rPanels[j].get());
204 if (!bFound) // this one didn't survive.
205 maPanels[i].disposeAndClear();
207 maPanels = rPanels;
209 RequestLayout();
212 void Deck::RequestLayout()
214 mnMinimalWidth = 0;
216 DeckLayouter::LayoutDeck(GetContentArea(), mnMinimalWidth, maPanels,
217 *GetTitleBar(), *mpScrollClipWindow, *mpScrollContainer,
218 *mpFiller, *mpVerticalScrollBar);
221 vcl::Window* Deck::GetPanelParentWindow()
223 return mpScrollContainer.get();
226 void Deck::ShowPanel(const Panel& rPanel)
228 if (mpVerticalScrollBar && mpVerticalScrollBar->IsVisible())
230 // Get vertical extent of the panel.
231 sal_Int32 nPanelTop (rPanel.GetPosPixel().Y());
232 const sal_Int32 nPanelBottom (nPanelTop + rPanel.GetSizePixel().Height() - 1);
233 // Add the title bar into the extent.
234 if (rPanel.GetTitleBar() != NULL && rPanel.GetTitleBar()->IsVisible())
235 nPanelTop = rPanel.GetTitleBar()->GetPosPixel().Y();
237 // Determine what the new thumb position should be like.
238 // When the whole panel does not fit then make its top visible
239 // and it off at the bottom.
240 sal_Int32 nNewThumbPos (mpVerticalScrollBar->GetThumbPos());
241 if (nPanelBottom >= nNewThumbPos+mpVerticalScrollBar->GetVisibleSize())
242 nNewThumbPos = nPanelBottom - mpVerticalScrollBar->GetVisibleSize();
243 if (nPanelTop < nNewThumbPos)
244 nNewThumbPos = nPanelTop;
246 mpVerticalScrollBar->SetThumbPos(nNewThumbPos);
247 mpScrollContainer->SetPosPixel(
248 Point(
249 mpScrollContainer->GetPosPixel().X(),
250 -nNewThumbPos));
255 const OUString GetWindowClassification(const vcl::Window* pWindow)
257 const OUString& rsName (pWindow->GetText());
258 if (!rsName.isEmpty())
260 return rsName;
262 else
264 return OUString("window");
268 void Deck::PrintWindowSubTree(vcl::Window* pRoot, int nIndentation)
270 static const char* sIndentation = " ";
271 const Point aLocation (pRoot->GetPosPixel());
272 const Size aSize (pRoot->GetSizePixel());
273 SAL_INFO(
274 "sfx.sidebar",
275 sIndentation + strlen(sIndentation) - nIndentation * 4 << pRoot << " "
276 << GetWindowClassification(pRoot) << " "
277 << (pRoot->IsVisible() ? "visible" : "hidden") << " +"
278 << aLocation.X() << "+" << aLocation.Y() << " x" << aSize.Width()
279 << "x" << aSize.Height());
281 const sal_uInt16 nChildCount(pRoot->GetChildCount());
282 for (sal_uInt16 nIndex = 0; nIndex < nChildCount; ++nIndex)
283 PrintWindowSubTree(pRoot->GetChild(nIndex), nIndentation + 1);
286 IMPL_LINK_NOARG(Deck, HandleVerticalScrollBarChange)
288 const sal_Int32 nYOffset (-mpVerticalScrollBar->GetThumbPos());
289 mpScrollContainer->SetPosPixel(Point(mpScrollContainer->GetPosPixel().X(),
290 nYOffset));
291 return sal_IntPtr(true);
294 //----- Deck::ScrollContainerWindow -------------------------------------------
296 Deck::ScrollContainerWindow::ScrollContainerWindow (vcl::Window* pParentWindow)
297 : Window(pParentWindow),
298 maSeparators()
300 #ifdef DEBUG
301 SetText(OUString("ScrollContainerWindow"));
302 #endif
305 void Deck::ScrollContainerWindow::Paint(vcl::RenderContext& rRenderContext, const Rectangle& /*rUpdateArea*/)
307 // Paint the separators.
308 const sal_Int32 nSeparatorHeight(Theme::GetInteger(Theme::Int_DeckSeparatorHeight));
309 const sal_Int32 nLeft(0);
310 const sal_Int32 nRight(GetSizePixel().Width() - 1);
311 const sfx2::sidebar::Paint& rHorizontalBorderPaint(Theme::GetPaint(Theme::Paint_HorizontalBorder));
312 for (std::vector<sal_Int32>::const_iterator iY(maSeparators.begin()); iY != maSeparators.end(); ++iY)
314 DrawHelper::DrawHorizontalLine(rRenderContext, nLeft, nRight, *iY,
315 nSeparatorHeight, rHorizontalBorderPaint);
319 void Deck::ScrollContainerWindow::SetSeparators (const ::std::vector<sal_Int32>& rSeparators)
321 maSeparators = rSeparators;
324 } } // end of namespace sfx2::sidebar
326 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */