Branch libreoffice-5-0-4
[LibreOffice.git] / sfx2 / source / sidebar / TabBar.cxx
blobbc2fe28761b1dad56845a9a3f89a98f3c681c70d
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 "TabBar.hxx"
21 #include "TabItem.hxx"
22 #include <sfx2/sidebar/ControlFactory.hxx>
23 #include "DeckDescriptor.hxx"
24 #include "Paint.hxx"
25 #include <sfx2/sidebar/Theme.hxx>
26 #include <sfx2/sidebar/Tools.hxx>
27 #include "FocusManager.hxx"
29 #include <vcl/gradient.hxx>
30 #include <vcl/image.hxx>
31 #include <vcl/wrkwin.hxx>
32 #include <comphelper/processfactory.hxx>
33 #include <tools/svborder.hxx>
35 #include <com/sun/star/graphic/XGraphicProvider.hpp>
37 using namespace css;
38 using namespace css::uno;
40 namespace sfx2 { namespace sidebar {
42 TabBar::TabBar(vcl::Window* pParentWindow,
43 const Reference<frame::XFrame>& rxFrame,
44 const boost::function<void(const OUString&)>& rDeckActivationFunctor,
45 const PopupMenuProvider& rPopupMenuProvider)
46 : Window(pParentWindow, WB_DIALOGCONTROL),
47 mxFrame(rxFrame),
48 mpMenuButton(ControlFactory::CreateMenuButton(this)),
49 maItems(),
50 maDeckActivationFunctor(rDeckActivationFunctor),
51 maPopupMenuProvider(rPopupMenuProvider)
53 SetBackground(Theme::GetPaint(Theme::Paint_TabBarBackground).GetWallpaper());
55 mpMenuButton->SetModeImage(Theme::GetImage(Theme::Image_TabBarMenu));
56 mpMenuButton->SetClickHdl(LINK(this, TabBar, OnToolboxClicked));
57 Layout();
59 #ifdef DEBUG
60 SetText(OUString("TabBar"));
61 #endif
64 TabBar::~TabBar()
66 disposeOnce();
69 void TabBar::dispose()
71 for(ItemContainer::iterator
72 iItem(maItems.begin()), iEnd(maItems.end());
73 iItem!=iEnd;
74 ++iItem)
75 iItem->mpButton.disposeAndClear();
76 maItems.clear();
77 mpMenuButton.disposeAndClear();
78 vcl::Window::dispose();
81 void TabBar::Paint(vcl::RenderContext& rRenderContext, const Rectangle& rUpdateArea)
83 Window::Paint(rRenderContext, rUpdateArea);
85 const sal_Int32 nHorizontalPadding(Theme::GetInteger(Theme::Int_TabMenuSeparatorPadding));
86 rRenderContext.SetLineColor(Theme::GetColor(Theme::Color_TabMenuSeparator));
87 rRenderContext.DrawLine(Point(nHorizontalPadding, mnMenuSeparatorY),
88 Point(GetSizePixel().Width() - nHorizontalPadding, mnMenuSeparatorY));
91 sal_Int32 TabBar::GetDefaultWidth()
93 return Theme::GetInteger(Theme::Int_TabItemWidth)
94 + Theme::GetInteger(Theme::Int_TabBarLeftPadding)
95 + Theme::GetInteger(Theme::Int_TabBarRightPadding);
98 void TabBar::SetDecks(const ResourceManager::DeckContextDescriptorContainer& rDecks)
100 // Remove the current buttons.
102 for(ItemContainer::iterator iItem(maItems.begin()); iItem != maItems.end(); ++iItem)
104 iItem->mpButton.disposeAndClear();
106 maItems.clear();
108 maItems.resize(rDecks.size());
109 sal_Int32 nIndex (0);
110 for (ResourceManager::DeckContextDescriptorContainer::const_iterator
111 iDeck(rDecks.begin()); iDeck != rDecks.end(); ++iDeck)
113 const DeckDescriptor* pDescriptor = ResourceManager::Instance().GetDeckDescriptor(iDeck->msId);
114 if (pDescriptor == NULL)
116 OSL_ASSERT(pDescriptor!=NULL);
117 continue;
120 Item& rItem (maItems[nIndex++]);
121 rItem.msDeckId = pDescriptor->msId;
122 rItem.mpButton.disposeAndClear();
123 rItem.mpButton = CreateTabItem(*pDescriptor);
124 rItem.mpButton->SetClickHdl(LINK(&rItem, TabBar::Item, HandleClick));
125 rItem.maDeckActivationFunctor = maDeckActivationFunctor;
126 rItem.mbIsHiddenByDefault = false;
127 rItem.mbIsHidden = ! pDescriptor->mbIsEnabled;
129 rItem.mpButton->Enable(iDeck->mbIsEnabled);
132 UpdateButtonIcons();
133 Layout();
136 void TabBar::UpdateButtonIcons()
138 Image aImage = Theme::GetImage(Theme::Image_TabBarMenu);
139 if ( mpMenuButton->GetDPIScaleFactor() > 1 )
141 BitmapEx b = aImage.GetBitmapEx();
142 b.Scale(mpMenuButton->GetDPIScaleFactor(), mpMenuButton->GetDPIScaleFactor(), BmpScaleFlag::Fast);
143 aImage = Image(b);
145 mpMenuButton->SetModeImage(aImage);
147 for(ItemContainer::const_iterator
148 iItem(maItems.begin()), iEnd(maItems.end());
149 iItem!=iEnd;
150 ++iItem)
152 const DeckDescriptor* pDeckDescriptor = ResourceManager::Instance().GetDeckDescriptor(iItem->msDeckId);
153 if (pDeckDescriptor != NULL)
155 aImage = GetItemImage(*pDeckDescriptor);
156 if ( mpMenuButton->GetDPIScaleFactor() > 1 )
158 BitmapEx b = aImage.GetBitmapEx();
159 b.Scale(mpMenuButton->GetDPIScaleFactor(), mpMenuButton->GetDPIScaleFactor(), BmpScaleFlag::Fast);
160 aImage = Image(b);
163 iItem->mpButton->SetModeImage(aImage);
167 Invalidate();
170 void TabBar::Layout()
172 const SvBorder aPadding (
173 Theme::GetInteger(Theme::Int_TabBarLeftPadding),
174 Theme::GetInteger(Theme::Int_TabBarTopPadding),
175 Theme::GetInteger(Theme::Int_TabBarRightPadding),
176 Theme::GetInteger(Theme::Int_TabBarBottomPadding));
177 sal_Int32 nX (aPadding.Top());
178 sal_Int32 nY (aPadding.Left());
179 const Size aTabItemSize (
180 Theme::GetInteger(Theme::Int_TabItemWidth) * GetDPIScaleFactor(),
181 Theme::GetInteger(Theme::Int_TabItemHeight) * GetDPIScaleFactor());
183 // Place the menu button and the separator.
184 if (mpMenuButton != nullptr)
186 mpMenuButton->SetPosSizePixel(
187 Point(nX,nY),
188 aTabItemSize);
189 mpMenuButton->Show();
190 nY += mpMenuButton->GetSizePixel().Height() + 1 + Theme::GetInteger(Theme::Int_TabMenuPadding);
191 mnMenuSeparatorY = nY - Theme::GetInteger(Theme::Int_TabMenuPadding)/2 - 1;
194 // Place the deck selection buttons.
195 for(ItemContainer::const_iterator
196 iItem(maItems.begin()), iEnd(maItems.end());
197 iItem!=iEnd;
198 ++iItem)
200 Button& rButton (*iItem->mpButton);
201 rButton.Show( ! iItem->mbIsHidden);
203 if (iItem->mbIsHidden)
204 continue;
206 // Place and size the icon.
207 rButton.SetPosSizePixel(
208 Point(nX,nY),
209 aTabItemSize);
210 rButton.Show();
212 nY += rButton.GetSizePixel().Height() + 1 + aPadding.Bottom();
214 Invalidate();
217 void TabBar::HighlightDeck (const OUString& rsDeckId)
219 for (ItemContainer::iterator iItem(maItems.begin()); iItem != maItems.end(); ++iItem)
221 if (iItem->msDeckId.equals(rsDeckId))
222 iItem->mpButton->Check(true);
223 else
224 iItem->mpButton->Check(false);
228 void TabBar::RemoveDeckHighlight ()
230 for (ItemContainer::iterator iItem(maItems.begin()),iEnd(maItems.end());
231 iItem!=iEnd;
232 ++iItem)
234 iItem->mpButton->Check(false);
238 void TabBar::DataChanged (const DataChangedEvent& rDataChangedEvent)
240 SetBackground(Theme::GetPaint(Theme::Paint_TabBarBackground).GetWallpaper());
241 UpdateButtonIcons();
243 Window::DataChanged(rDataChangedEvent);
246 bool TabBar::Notify (NotifyEvent&)
248 return false;
251 VclPtr<RadioButton> TabBar::CreateTabItem(const DeckDescriptor& rDeckDescriptor)
253 VclPtr<RadioButton> pItem = ControlFactory::CreateTabItem(this);
254 pItem->SetAccessibleName(rDeckDescriptor.msTitle);
255 pItem->SetAccessibleDescription(rDeckDescriptor.msHelpText);
256 pItem->SetHelpText(rDeckDescriptor.msHelpText);
257 pItem->SetQuickHelpText(rDeckDescriptor.msHelpText);
258 return pItem;
261 Image TabBar::GetItemImage(const DeckDescriptor& rDeckDescriptor) const
263 return Tools::GetImage(
264 rDeckDescriptor.msIconURL,
265 rDeckDescriptor.msHighContrastIconURL,
266 mxFrame);
269 IMPL_LINK(TabBar::Item, HandleClick, Button*,)
273 maDeckActivationFunctor(msDeckId);
275 catch(const css::uno::Exception&)
276 {} // workaround for #i123198#
278 return 1;
281 const ::rtl::OUString TabBar::GetDeckIdForIndex (const sal_Int32 nIndex) const
283 if (nIndex<0 || static_cast<size_t>(nIndex)>=maItems.size())
284 throw RuntimeException();
285 else
286 return maItems[nIndex].msDeckId;
289 void TabBar::ToggleHideFlag (const sal_Int32 nIndex)
291 if (nIndex<0 || static_cast<size_t>(nIndex) >= maItems.size())
292 throw RuntimeException();
293 else
295 maItems[nIndex].mbIsHidden = ! maItems[nIndex].mbIsHidden;
296 ResourceManager::Instance().SetIsDeckEnabled(
297 maItems[nIndex].msDeckId,
298 maItems[nIndex].mbIsHidden);
299 Layout();
303 void TabBar::RestoreHideFlags()
305 bool bNeedsLayout(false);
306 for (ItemContainer::iterator iItem(maItems.begin()); iItem != maItems.end(); ++iItem)
308 if (iItem->mbIsHidden != iItem->mbIsHiddenByDefault)
310 iItem->mbIsHidden = iItem->mbIsHiddenByDefault;
311 bNeedsLayout = true;
314 if (bNeedsLayout)
315 Layout();
318 void TabBar::UpdateFocusManager(FocusManager& rFocusManager)
320 std::vector<Button*> aButtons;
321 aButtons.reserve(maItems.size()+1);
323 aButtons.push_back(mpMenuButton.get());
324 for (ItemContainer::const_iterator iItem(maItems.begin()); iItem != maItems.end(); ++iItem)
326 aButtons.push_back(iItem->mpButton.get());
328 rFocusManager.SetButtons(aButtons);
331 IMPL_LINK_NOARG(TabBar, OnToolboxClicked)
333 if (!mpMenuButton)
334 return 0;
336 std::vector<DeckMenuData> aMenuData;
338 for (ItemContainer::const_iterator iItem(maItems.begin()); iItem != maItems.end(); ++iItem)
340 const DeckDescriptor* pDeckDescriptor = ResourceManager::Instance().GetDeckDescriptor(iItem->msDeckId);
341 if (pDeckDescriptor != NULL)
343 DeckMenuData aData;
344 aData.msDisplayName = pDeckDescriptor->msTitle;
345 aData.msDeckId = pDeckDescriptor->msId;
346 aData.mbIsCurrentDeck = iItem->mpButton->IsChecked();
347 aData.mbIsActive = !iItem->mbIsHidden;
348 aData.mbIsEnabled = iItem->mpButton->IsEnabled();
350 aMenuData.push_back(aData);
354 maPopupMenuProvider(
355 Rectangle(
356 mpMenuButton->GetPosPixel(),
357 mpMenuButton->GetSizePixel()),
358 aMenuData);
359 mpMenuButton->Check(false);
361 return 0;
364 } } // end of namespace sfx2::sidebar
366 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */