xref: /trunk/main/sfx2/source/sidebar/TabBar.cxx (revision 5c37a1f2)
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 
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 
81 TabBar::~TabBar (void)
82 {
83 }
84 
85 
86 
87 
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 
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 
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 
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 
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 (mpMenuButton != NULL)
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 
237 void TabBar::HighlightDeck (const ::rtl::OUString& rsDeckId)
238 {
239     Item* pItem = GetItemForId(rsDeckId);
240     if (pItem != NULL)
241         pItem->mpButton->Check();
242 }
243 
244 
245 
246 
247 TabBar::Item* TabBar::GetItemForId (const ::rtl::OUString& rsDeckId)
248 {
249     for (ItemContainer::iterator iItem(maItems.begin()),iEnd(maItems.end());
250          iItem!=iEnd;
251          ++iItem)
252     {
253         if (iItem->msDeckId.equals(rsDeckId))
254             return &*iItem;
255     }
256     return NULL;
257 }
258 
259 
260 
261 
262 void TabBar::DataChanged (const DataChangedEvent& rDataChangedEvent)
263 {
264     SetBackground(Theme::GetPaint(Theme::Paint_TabBarBackground).GetWallpaper());
265     UpdateButtonIcons();
266 
267     Window::DataChanged(rDataChangedEvent);
268 }
269 
270 
271 
272 
273 long TabBar::Notify (NotifyEvent&)
274 {
275     return sal_False;
276 }
277 
278 
279 
280 
281 RadioButton* TabBar::CreateTabItem (const DeckDescriptor& rDeckDescriptor)
282 {
283     RadioButton* pItem = ControlFactory::CreateTabItem(this);
284     pItem->SetHelpText(rDeckDescriptor.msHelpText);
285     pItem->SetQuickHelpText(rDeckDescriptor.msHelpText);
286 
287     return pItem;
288 }
289 
290 
291 
292 Image TabBar::GetItemImage (const DeckDescriptor& rDeckDescriptor) const
293 {
294     return Tools::GetImage(
295         rDeckDescriptor.msIconURL,
296         rDeckDescriptor.msHighContrastIconURL,
297         mxFrame);
298 }
299 
300 
301 
302 
303 
304 IMPL_LINK(TabBar::Item, HandleClick, Button*, EMPTYARG)
305 {
306     maDeckActivationFunctor(msDeckId);
307     return 1;
308 }
309 
310 
311 
312 
313 const ::rtl::OUString TabBar::GetDeckIdForIndex (const sal_Int32 nIndex) const
314 {
315     if (nIndex<0 || static_cast<size_t>(nIndex)>=maItems.size())
316         throw RuntimeException();
317     else
318         return maItems[nIndex].msDeckId;
319 }
320 
321 
322 
323 
324 void TabBar::ToggleHideFlag (const sal_Int32 nIndex)
325 {
326     if (nIndex<0 || static_cast<size_t>(nIndex)>=maItems.size())
327         throw RuntimeException();
328     else
329     {
330         maItems[nIndex].mbIsHidden = ! maItems[nIndex].mbIsHidden;
331         ResourceManager::Instance().SetIsDeckEnabled(
332             maItems[nIndex].msDeckId,
333             maItems[nIndex].mbIsHidden);
334         Layout();
335     }
336 }
337 
338 
339 
340 
341 void TabBar::RestoreHideFlags (void)
342 {
343     bool bNeedsLayout (false);
344     for(ItemContainer::iterator iItem(maItems.begin()),iEnd(maItems.end());
345         iItem!=iEnd;
346         ++iItem)
347     {
348         if (iItem->mbIsHidden != iItem->mbIsHiddenByDefault)
349         {
350             iItem->mbIsHidden = iItem->mbIsHiddenByDefault;
351             bNeedsLayout = true;
352         }
353     }
354     if (bNeedsLayout)
355         Layout();
356 }
357 
358 
359 
360 
361 void TabBar::UpdateFocusManager (FocusManager& rFocusManager)
362 {
363     ::std::vector<Button*> aButtons;
364     aButtons.reserve(maItems.size()+1);
365 
366     aButtons.push_back(mpMenuButton.get());
367     for(ItemContainer::const_iterator
368             iItem(maItems.begin()), iEnd(maItems.end());
369         iItem!=iEnd;
370         ++iItem)
371     {
372         aButtons.push_back(iItem->mpButton.get());
373     }
374     rFocusManager.SetButtons(aButtons);
375 }
376 
377 
378 
379 
380 IMPL_LINK(TabBar, OnToolboxClicked, void*, EMPTYARG)
381 {
382     ::std::vector<DeckMenuData> aSelectionData;
383     ::std::vector<DeckMenuData> aShowData;
384 
385     for(ItemContainer::const_iterator iItem(maItems.begin()),iEnd(maItems.end());
386         iItem!=iEnd;
387         ++iItem)
388     {
389         const DeckDescriptor* pDeckDescriptor = ResourceManager::Instance().GetDeckDescriptor(iItem->msDeckId);
390         if (pDeckDescriptor != NULL)
391         {
392             if ( ! iItem->mbIsHidden)
393                 aSelectionData.push_back(
394                     DeckMenuData(
395                         pDeckDescriptor->msTitle,
396                         pDeckDescriptor->msId,
397                         iItem->mpButton->IsChecked()));
398 
399             aShowData.push_back(
400                 DeckMenuData(
401                     pDeckDescriptor->msTitle,
402                     pDeckDescriptor->msId,
403                     !iItem->mbIsHidden));
404         }
405     }
406 
407     maPopupMenuProvider(
408         Rectangle(
409             mpMenuButton->GetPosPixel(),
410             mpMenuButton->GetSizePixel()),
411         aSelectionData,
412         aShowData);
413 
414     return 0;
415 }
416 
417 
418 
419 } } // end of namespace sfx2::sidebar
420