xref: /trunk/main/sfx2/source/sidebar/TabBar.cxx (revision b862c97c)
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