1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
21 #include "TabItem.hxx"
22 #include <sfx2/sidebar/ControlFactory.hxx>
23 #include "DeckDescriptor.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>
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
),
48 mpMenuButton(ControlFactory::CreateMenuButton(this)),
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
));
60 SetText(OUString("TabBar"));
69 void TabBar::dispose()
71 for(ItemContainer::iterator
72 iItem(maItems
.begin()), iEnd(maItems
.end());
75 iItem
->mpButton
.disposeAndClear();
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();
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
);
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
);
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
);
145 mpMenuButton
->SetModeImage(aImage
);
147 for(ItemContainer::const_iterator
148 iItem(maItems
.begin()), iEnd(maItems
.end());
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
);
163 iItem
->mpButton
->SetModeImage(aImage
);
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(
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());
200 Button
& rButton (*iItem
->mpButton
);
201 rButton
.Show( ! iItem
->mbIsHidden
);
203 if (iItem
->mbIsHidden
)
206 // Place and size the icon.
207 rButton
.SetPosSizePixel(
212 nY
+= rButton
.GetSizePixel().Height() + 1 + aPadding
.Bottom();
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);
224 iItem
->mpButton
->Check(false);
228 void TabBar::RemoveDeckHighlight ()
230 for (ItemContainer::iterator
iItem(maItems
.begin()),iEnd(maItems
.end());
234 iItem
->mpButton
->Check(false);
238 void TabBar::DataChanged (const DataChangedEvent
& rDataChangedEvent
)
240 SetBackground(Theme::GetPaint(Theme::Paint_TabBarBackground
).GetWallpaper());
243 Window::DataChanged(rDataChangedEvent
);
246 bool TabBar::Notify (NotifyEvent
&)
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
);
261 Image
TabBar::GetItemImage(const DeckDescriptor
& rDeckDescriptor
) const
263 return Tools::GetImage(
264 rDeckDescriptor
.msIconURL
,
265 rDeckDescriptor
.msHighContrastIconURL
,
269 IMPL_LINK(TabBar::Item
, HandleClick
, Button
*,)
273 maDeckActivationFunctor(msDeckId
);
275 catch(const css::uno::Exception
&)
276 {} // workaround for #i123198#
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();
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();
295 maItems
[nIndex
].mbIsHidden
= ! maItems
[nIndex
].mbIsHidden
;
296 ResourceManager::Instance().SetIsDeckEnabled(
297 maItems
[nIndex
].msDeckId
,
298 maItems
[nIndex
].mbIsHidden
);
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
;
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
)
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
)
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
);
356 mpMenuButton
->GetPosPixel(),
357 mpMenuButton
->GetSizePixel()),
359 mpMenuButton
->Check(false);
364 } } // end of namespace sfx2::sidebar
366 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */