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 "TabBar.hxx"
25 #include "TabItem.hxx"
26 #include "sidebar/ControlFactory.hxx"
27 #include "DeckDescriptor.hxx"
28 #include "Paint.hxx"
29 #include "sfx2/sidebar/Theme.hxx"
30 #include "sfx2/sidebar/Tools.hxx"
31 #include "FocusManager.hxx"
32
33 #include <vcl/gradient.hxx>
34 #include <vcl/image.hxx>
35 #include <vcl/wrkwin.hxx>
36 #include <comphelper/processfactory.hxx>
37 #include <comphelper/componentcontext.hxx>
38 #include <tools/svborder.hxx>
39
40 #include <com/sun/star/graphic/XGraphicProvider.hpp>
41
42
43 using namespace ::com::sun::star;
44 using namespace ::com::sun::star::uno;
45
46
47
48
49 namespace sfx2 { namespace sidebar {
50
TabBar(Window * pParentWindow,const Reference<frame::XFrame> & rxFrame,const::boost::function<void (const::rtl::OUString &)> & rDeckActivationFunctor,const PopupMenuProvider & rPopupMenuProvider)51 TabBar::TabBar (
52 Window* pParentWindow,
53 const Reference<frame::XFrame>& rxFrame,
54 const ::boost::function<void(const ::rtl::OUString&)>& rDeckActivationFunctor,
55 const PopupMenuProvider& rPopupMenuProvider)
56 : Window(pParentWindow, WB_DIALOGCONTROL),
57 mxFrame(rxFrame),
58 mpMenuButton(ControlFactory::CreateMenuButton(this)),
59 maItems(),
60 maDeckActivationFunctor(rDeckActivationFunctor),
61 maPopupMenuProvider(rPopupMenuProvider)
62 {
63 SetBackground(Theme::GetPaint(Theme::Paint_TabBarBackground).GetWallpaper());
64
65 mpMenuButton->SetModeImage(
66 Theme::GetImage(Theme::Image_TabBarMenu),
67 Theme::IsHighContrastMode()
68 ? BMP_COLOR_HIGHCONTRAST
69 : BMP_COLOR_NORMAL);
70 mpMenuButton->SetClickHdl(LINK(this, TabBar, OnToolboxClicked));
71 Layout();
72
73 #ifdef DEBUG
74 SetText(A2S("TabBar"));
75 #endif
76 }
77
78
79
80
~TabBar(void)81 TabBar::~TabBar (void)
82 {
83 }
84
85
86
87
Paint(const Rectangle & rUpdateArea)88 void TabBar::Paint (const Rectangle& rUpdateArea)
89 {
90 Window::Paint(rUpdateArea);
91
92 const sal_Int32 nHorizontalPadding (Theme::GetInteger(Theme::Int_TabMenuSeparatorPadding));
93 SetLineColor(Theme::GetColor(Theme::Color_TabMenuSeparator));
94 DrawLine(
95 Point(nHorizontalPadding, mnMenuSeparatorY),
96 Point(GetSizePixel().Width()-nHorizontalPadding, mnMenuSeparatorY));
97 }
98
99
100
101
GetDefaultWidth(void)102 sal_Int32 TabBar::GetDefaultWidth (void)
103 {
104 return Theme::GetInteger(Theme::Int_TabItemWidth)
105 + Theme::GetInteger(Theme::Int_TabBarLeftPadding)
106 + Theme::GetInteger(Theme::Int_TabBarRightPadding);
107 }
108
109
110
111
SetDecks(const ResourceManager::DeckContextDescriptorContainer & rDecks)112 void TabBar::SetDecks (
113 const ResourceManager::DeckContextDescriptorContainer& rDecks)
114 {
115 // Remove the current buttons.
116 {
117 for(ItemContainer::iterator
118 iItem(maItems.begin()), iEnd(maItems.end());
119 iItem!=iEnd;
120 ++iItem)
121 {
122 iItem->mpButton.reset();
123 }
124 maItems.clear();
125 }
126
127 maItems.resize(rDecks.size());
128 sal_Int32 nIndex (0);
129 for (ResourceManager::DeckContextDescriptorContainer::const_iterator
130 iDeck(rDecks.begin()),
131 iEnd(rDecks.end());
132 iDeck!=iEnd;
133 ++iDeck)
134 {
135 const DeckDescriptor* pDescriptor = ResourceManager::Instance().GetDeckDescriptor(iDeck->msId);
136 if (pDescriptor == NULL)
137 {
138 OSL_ASSERT(pDescriptor!=NULL);
139 continue;
140 }
141
142 Item& rItem (maItems[nIndex++]);
143 rItem.msDeckId = pDescriptor->msId;
144 rItem.mpButton.reset(CreateTabItem(*pDescriptor));
145 rItem.mpButton->SetClickHdl(LINK(&rItem, TabBar::Item, HandleClick));
146 rItem.maDeckActivationFunctor = maDeckActivationFunctor;
147 rItem.mbIsHiddenByDefault = false;
148 rItem.mbIsHidden = ! pDescriptor->mbIsEnabled;
149
150 rItem.mpButton->Enable(iDeck->mbIsEnabled);
151 }
152
153 UpdateButtonIcons();
154 Layout();
155 }
156
157
158
159
UpdateButtonIcons(void)160 void TabBar::UpdateButtonIcons (void)
161 {
162 const BmpColorMode eColorMode (
163 Theme::IsHighContrastMode()
164 ? BMP_COLOR_HIGHCONTRAST
165 : BMP_COLOR_NORMAL);
166
167 mpMenuButton->SetModeImage(Theme::GetImage(Theme::Image_TabBarMenu), eColorMode);
168
169 for(ItemContainer::const_iterator
170 iItem(maItems.begin()), iEnd(maItems.end());
171 iItem!=iEnd;
172 ++iItem)
173 {
174 const DeckDescriptor* pDeckDescriptor = ResourceManager::Instance().GetDeckDescriptor(iItem->msDeckId);
175 if (pDeckDescriptor != NULL)
176 iItem->mpButton->SetModeImage(
177 GetItemImage(*pDeckDescriptor),
178 eColorMode);
179 }
180
181 Invalidate();
182 }
183
184
185
186
Layout(void)187 void TabBar::Layout (void)
188 {
189 const SvBorder aPadding (
190 Theme::GetInteger(Theme::Int_TabBarLeftPadding),
191 Theme::GetInteger(Theme::Int_TabBarTopPadding),
192 Theme::GetInteger(Theme::Int_TabBarRightPadding),
193 Theme::GetInteger(Theme::Int_TabBarBottomPadding));
194 sal_Int32 nX (aPadding.Top());
195 sal_Int32 nY (aPadding.Left());
196 const Size aTabItemSize (
197 Theme::GetInteger(Theme::Int_TabItemWidth),
198 Theme::GetInteger(Theme::Int_TabItemHeight));
199
200 // Place the menu button and the separator.
201 if( bool(mpMenuButton))
202 {
203 mpMenuButton->SetPosSizePixel(
204 Point(nX,nY),
205 aTabItemSize);
206 mpMenuButton->Show();
207 nY += mpMenuButton->GetSizePixel().Height() + 1 + Theme::GetInteger(Theme::Int_TabMenuPadding);
208 mnMenuSeparatorY = nY - Theme::GetInteger(Theme::Int_TabMenuPadding)/2 - 1;
209 }
210
211 // Place the deck selection buttons.
212 for(ItemContainer::const_iterator
213 iItem(maItems.begin()), iEnd(maItems.end());
214 iItem!=iEnd;
215 ++iItem)
216 {
217 Button& rButton (*iItem->mpButton);
218 rButton.Show( ! iItem->mbIsHidden);
219
220 if (iItem->mbIsHidden)
221 continue;
222
223 // Place and size the icon.
224 rButton.SetPosSizePixel(
225 Point(nX,nY),
226 aTabItemSize);
227 rButton.Show();
228
229 nY += rButton.GetSizePixel().Height() + 1 + aPadding.Bottom();
230 }
231 Invalidate();
232 }
233
234
235
236
HighlightDeck(const::rtl::OUString & rsDeckId)237 void TabBar::HighlightDeck (const ::rtl::OUString& rsDeckId)
238 {
239 for (ItemContainer::iterator iItem(maItems.begin()),iEnd(maItems.end());
240 iItem!=iEnd;
241 ++iItem)
242 {
243 if (iItem->msDeckId.equals(rsDeckId))
244 iItem->mpButton->Check(sal_True);
245 else
246 iItem->mpButton->Check(sal_False);
247 }
248 }
249
250
251
252
GetItemForId(const::rtl::OUString & rsDeckId)253 TabBar::Item* TabBar::GetItemForId (const ::rtl::OUString& rsDeckId)
254 {
255 for (ItemContainer::iterator iItem(maItems.begin()),iEnd(maItems.end());
256 iItem!=iEnd;
257 ++iItem)
258 {
259 if (iItem->msDeckId.equals(rsDeckId))
260 return &*iItem;
261 }
262 return NULL;
263 }
264
265
266
267
DataChanged(const DataChangedEvent & rDataChangedEvent)268 void TabBar::DataChanged (const DataChangedEvent& rDataChangedEvent)
269 {
270 SetBackground(Theme::GetPaint(Theme::Paint_TabBarBackground).GetWallpaper());
271 UpdateButtonIcons();
272
273 Window::DataChanged(rDataChangedEvent);
274 }
275
276
277
278
Notify(NotifyEvent &)279 long TabBar::Notify (NotifyEvent&)
280 {
281 return sal_False;
282 }
283
284
285
286
CreateTabItem(const DeckDescriptor & rDeckDescriptor)287 RadioButton* TabBar::CreateTabItem (const DeckDescriptor& rDeckDescriptor)
288 {
289 RadioButton* pItem = ControlFactory::CreateTabItem(this);
290 pItem->SetHelpText(rDeckDescriptor.msHelpText);
291 pItem->SetQuickHelpText(rDeckDescriptor.msHelpText);
292
293 return pItem;
294 }
295
296
297
GetItemImage(const DeckDescriptor & rDeckDescriptor) const298 Image TabBar::GetItemImage (const DeckDescriptor& rDeckDescriptor) const
299 {
300 return Tools::GetImage(
301 rDeckDescriptor.msIconURL,
302 rDeckDescriptor.msHighContrastIconURL,
303 mxFrame);
304 }
305
306
307
308
309
IMPL_LINK(TabBar::Item,HandleClick,Button *,EMPTYARG)310 IMPL_LINK(TabBar::Item, HandleClick, Button*, EMPTYARG)
311 {
312 try
313 {
314 maDeckActivationFunctor(msDeckId);
315 }
316 catch( const ::com::sun::star::uno::Exception&) {} // workaround for #i123198#
317
318 return 1;
319 }
320
321
322
323
GetDeckIdForIndex(const sal_Int32 nIndex) const324 const ::rtl::OUString TabBar::GetDeckIdForIndex (const sal_Int32 nIndex) const
325 {
326 if (nIndex<0 || static_cast<size_t>(nIndex)>=maItems.size())
327 throw RuntimeException();
328 else
329 return maItems[nIndex].msDeckId;
330 }
331
332
333
334
ToggleHideFlag(const sal_Int32 nIndex)335 void TabBar::ToggleHideFlag (const sal_Int32 nIndex)
336 {
337 if (nIndex<0 || static_cast<size_t>(nIndex)>=maItems.size())
338 throw RuntimeException();
339 else
340 {
341 maItems[nIndex].mbIsHidden = ! maItems[nIndex].mbIsHidden;
342 ResourceManager::Instance().SetIsDeckEnabled(
343 maItems[nIndex].msDeckId,
344 maItems[nIndex].mbIsHidden);
345 Layout();
346 }
347 }
348
349
350
351
RestoreHideFlags(void)352 void TabBar::RestoreHideFlags (void)
353 {
354 bool bNeedsLayout (false);
355 for(ItemContainer::iterator iItem(maItems.begin()),iEnd(maItems.end());
356 iItem!=iEnd;
357 ++iItem)
358 {
359 if (iItem->mbIsHidden != iItem->mbIsHiddenByDefault)
360 {
361 iItem->mbIsHidden = iItem->mbIsHiddenByDefault;
362 bNeedsLayout = true;
363 }
364 }
365 if (bNeedsLayout)
366 Layout();
367 }
368
369
370
371
UpdateFocusManager(FocusManager & rFocusManager)372 void TabBar::UpdateFocusManager (FocusManager& rFocusManager)
373 {
374 ::std::vector<Button*> aButtons;
375 aButtons.reserve(maItems.size()+1);
376
377 aButtons.push_back(mpMenuButton.get());
378 for(ItemContainer::const_iterator
379 iItem(maItems.begin()), iEnd(maItems.end());
380 iItem!=iEnd;
381 ++iItem)
382 {
383 aButtons.push_back(iItem->mpButton.get());
384 }
385 rFocusManager.SetButtons(aButtons);
386 }
387
388
389
390
IMPL_LINK(TabBar,OnToolboxClicked,void *,EMPTYARG)391 IMPL_LINK(TabBar, OnToolboxClicked, void*, EMPTYARG)
392 {
393 if ( ! mpMenuButton)
394 return 0;
395
396 ::std::vector<DeckMenuData> aMenuData;
397
398 for(ItemContainer::const_iterator iItem(maItems.begin()),iEnd(maItems.end());
399 iItem!=iEnd;
400 ++iItem)
401 {
402 const DeckDescriptor* pDeckDescriptor = ResourceManager::Instance().GetDeckDescriptor(iItem->msDeckId);
403 if (pDeckDescriptor != NULL)
404 {
405 DeckMenuData aData;
406 aData.msDisplayName = pDeckDescriptor->msTitle;
407 aData.msDeckId = pDeckDescriptor->msId;
408 aData.mbIsCurrentDeck = iItem->mpButton->IsChecked();
409 aData.mbIsActive = !iItem->mbIsHidden;
410 aData.mbIsEnabled = iItem->mpButton->IsEnabled();
411
412 aMenuData.push_back(aData);
413 }
414 }
415
416 maPopupMenuProvider(
417 Rectangle(
418 mpMenuButton->GetPosPixel(),
419 mpMenuButton->GetSizePixel()),
420 aMenuData);
421 mpMenuButton->Check(sal_False);
422
423 return 0;
424 }
425
426
427
428 } } // end of namespace sfx2::sidebar
429