xref: /aoo41x/main/sfx2/source/sidebar/TabBar.cxx (revision f35c6d02)
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 RadioButton* TabBar::CreateTabItem (const DeckDescriptor& rDeckDescriptor)
274 {
275     RadioButton* pItem = ControlFactory::CreateTabItem(this);
276     pItem->SetHelpText(rDeckDescriptor.msHelpText);
277     pItem->SetQuickHelpText(rDeckDescriptor.msHelpText);
278 
279     return pItem;
280 }
281 
282 
283 
284 Image TabBar::GetItemImage (const DeckDescriptor& rDeckDescriptor) const
285 {
286     return Tools::GetImage(
287         rDeckDescriptor.msIconURL,
288         rDeckDescriptor.msHighContrastIconURL,
289         mxFrame);
290 }
291 
292 
293 
294 
295 
296 IMPL_LINK(TabBar::Item, HandleClick, Button*, EMPTYARG)
297 {
298     maDeckActivationFunctor(msDeckId);
299     return 1;
300 }
301 
302 
303 
304 
305 const ::rtl::OUString TabBar::GetDeckIdForIndex (const sal_Int32 nIndex) const
306 {
307     if (nIndex<0 || static_cast<size_t>(nIndex)>=maItems.size())
308         throw RuntimeException();
309     else
310         return maItems[nIndex].msDeckId;
311 }
312 
313 
314 
315 
316 void TabBar::ToggleHideFlag (const sal_Int32 nIndex)
317 {
318     if (nIndex<0 || static_cast<size_t>(nIndex)>=maItems.size())
319         throw RuntimeException();
320     else
321     {
322         maItems[nIndex].mbIsHidden = ! maItems[nIndex].mbIsHidden;
323         ResourceManager::Instance().SetIsDeckEnabled(
324             maItems[nIndex].msDeckId,
325             maItems[nIndex].mbIsHidden);
326         Layout();
327     }
328 }
329 
330 
331 
332 
333 void TabBar::RestoreHideFlags (void)
334 {
335     bool bNeedsLayout (false);
336     for(ItemContainer::iterator iItem(maItems.begin()),iEnd(maItems.end());
337         iItem!=iEnd;
338         ++iItem)
339     {
340         if (iItem->mbIsHidden != iItem->mbIsHiddenByDefault)
341         {
342             iItem->mbIsHidden = iItem->mbIsHiddenByDefault;
343             bNeedsLayout = true;
344         }
345     }
346     if (bNeedsLayout)
347         Layout();
348 }
349 
350 
351 
352 
353 void TabBar::UpdateFocusManager (FocusManager& rFocusManager)
354 {
355     ::std::vector<Button*> aButtons;
356     aButtons.reserve(maItems.size()+1);
357 
358     aButtons.push_back(mpMenuButton.get());
359     for(ItemContainer::const_iterator
360             iItem(maItems.begin()), iEnd(maItems.end());
361         iItem!=iEnd;
362         ++iItem)
363     {
364         aButtons.push_back(iItem->mpButton.get());
365     }
366     rFocusManager.SetButtons(aButtons);
367 }
368 
369 
370 
371 
372 IMPL_LINK(TabBar, OnToolboxClicked, void*, EMPTYARG)
373 {
374     ::std::vector<DeckMenuData> aSelectionData;
375     ::std::vector<DeckMenuData> aShowData;
376 
377     for(ItemContainer::const_iterator iItem(maItems.begin()),iEnd(maItems.end());
378         iItem!=iEnd;
379         ++iItem)
380     {
381         const DeckDescriptor* pDeckDescriptor = ResourceManager::Instance().GetDeckDescriptor(iItem->msDeckId);
382         if (pDeckDescriptor != NULL)
383         {
384             if ( ! iItem->mbIsHidden)
385                 aSelectionData.push_back(
386                     DeckMenuData(
387                         pDeckDescriptor->msTitle,
388                         pDeckDescriptor->msId,
389                         iItem->mpButton->IsChecked()));
390 
391             aShowData.push_back(
392                 DeckMenuData(
393                     pDeckDescriptor->msTitle,
394                     pDeckDescriptor->msId,
395                     !iItem->mbIsHidden));
396         }
397     }
398 
399     maPopupMenuProvider(
400         Rectangle(
401             mpMenuButton->GetPosPixel(),
402             mpMenuButton->GetSizePixel()),
403         aSelectionData,
404         aShowData);
405 
406     return 0;
407 }
408 
409 
410 
411 } } // end of namespace sfx2::sidebar
412