xref: /aoo41x/main/sfx2/source/sidebar/TabBar.cxx (revision 65908a7e)
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 "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::IdContainer& rDeckIds)
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(rDeckIds.size());
128     sal_Int32 nIndex (0);
129     for (ResourceManager::IdContainer::const_iterator
130              iDeckId(rDeckIds.begin()),
131              iEnd(rDeckIds.end());
132          iDeckId!=iEnd;
133          ++iDeckId)
134     {
135         const DeckDescriptor* pDescriptor = ResourceManager::Instance().GetDeckDescriptor(*iDeckId);
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 
151     UpdateButtonIcons();
152     Layout();
153 }
154 
155 
156 
157 
158 void TabBar::UpdateButtonIcons (void)
159 {
160     const BmpColorMode eColorMode (
161         Theme::IsHighContrastMode()
162             ? BMP_COLOR_HIGHCONTRAST
163             : BMP_COLOR_NORMAL);
164 
165     mpMenuButton->SetModeImage(Theme::GetImage(Theme::Image_TabBarMenu), eColorMode);
166 
167     for(ItemContainer::const_iterator
168             iItem(maItems.begin()), iEnd(maItems.end());
169         iItem!=iEnd;
170         ++iItem)
171     {
172         const DeckDescriptor* pDeckDescriptor = ResourceManager::Instance().GetDeckDescriptor(iItem->msDeckId);
173         if (pDeckDescriptor != NULL)
174             iItem->mpButton->SetModeImage(
175                 GetItemImage(*pDeckDescriptor),
176                 eColorMode);
177     }
178 
179     Invalidate();
180 }
181 
182 
183 
184 
185 void TabBar::Layout (void)
186 {
187     const SvBorder aPadding (
188         Theme::GetInteger(Theme::Int_TabBarLeftPadding),
189         Theme::GetInteger(Theme::Int_TabBarTopPadding),
190         Theme::GetInteger(Theme::Int_TabBarRightPadding),
191         Theme::GetInteger(Theme::Int_TabBarBottomPadding));
192     sal_Int32 nX (aPadding.Top());
193     sal_Int32 nY (aPadding.Left());
194     const Size aTabItemSize (
195         Theme::GetInteger(Theme::Int_TabItemWidth),
196         Theme::GetInteger(Theme::Int_TabItemHeight));
197 
198     // Place the menu button and the separator.
199     if (mpMenuButton != NULL)
200     {
201         mpMenuButton->SetPosSizePixel(
202             Point(nX,nY),
203             aTabItemSize);
204         mpMenuButton->Show();
205         nY += mpMenuButton->GetSizePixel().Height() + 1 + Theme::GetInteger(Theme::Int_TabMenuPadding);
206         mnMenuSeparatorY = nY - Theme::GetInteger(Theme::Int_TabMenuPadding)/2 - 1;
207     }
208 
209     // Place the deck selection buttons.
210     for(ItemContainer::const_iterator
211             iItem(maItems.begin()), iEnd(maItems.end());
212         iItem!=iEnd;
213         ++iItem)
214     {
215         Button& rButton (*iItem->mpButton);
216         rButton.Show( ! iItem->mbIsHidden);
217 
218         if (iItem->mbIsHidden)
219             continue;
220 
221         // Place and size the icon.
222         rButton.SetPosSizePixel(
223             Point(nX,nY),
224             aTabItemSize);
225         rButton.Show();
226 
227         nY += rButton.GetSizePixel().Height() + 1 + aPadding.Bottom();
228     }
229     Invalidate();
230 }
231 
232 
233 
234 
235 void TabBar::HighlightDeck (const ::rtl::OUString& rsDeckId)
236 {
237     for (ItemContainer::const_iterator iItem(maItems.begin()),iEnd(maItems.end());
238          iItem!=iEnd;
239          ++iItem)
240     {
241         if (iItem->msDeckId.equals(rsDeckId))
242         {
243             iItem->mpButton->Check();
244             break;
245         }
246     }
247 }
248 
249 
250 
251 
252 void TabBar::DataChanged (const DataChangedEvent& rDataChangedEvent)
253 {
254     SetBackground(Theme::GetPaint(Theme::Paint_TabBarBackground).GetWallpaper());
255     UpdateButtonIcons();
256 
257     Window::DataChanged(rDataChangedEvent);
258 }
259 
260 
261 
262 
263 RadioButton* TabBar::CreateTabItem (const DeckDescriptor& rDeckDescriptor)
264 {
265     RadioButton* pItem = ControlFactory::CreateTabItem(this);
266     pItem->SetHelpText(rDeckDescriptor.msHelpText);
267     pItem->SetQuickHelpText(rDeckDescriptor.msHelpText);
268 
269     return pItem;
270 }
271 
272 
273 
274 Image TabBar::GetItemImage (const DeckDescriptor& rDeckDescriptor) const
275 {
276     return Tools::GetImage(
277         rDeckDescriptor.msIconURL,
278         rDeckDescriptor.msHighContrastIconURL,
279         mxFrame);
280 }
281 
282 
283 
284 
285 
286 IMPL_LINK(TabBar::Item, HandleClick, Button*, EMPTYARG)
287 {
288     maDeckActivationFunctor(msDeckId);
289     return 1;
290 }
291 
292 
293 
294 
295 const ::rtl::OUString TabBar::GetDeckIdForIndex (const sal_Int32 nIndex) const
296 {
297     if (nIndex<0 || static_cast<size_t>(nIndex)>=maItems.size())
298         throw RuntimeException();
299     else
300         return maItems[nIndex].msDeckId;
301 }
302 
303 
304 
305 
306 void TabBar::ToggleHideFlag (const sal_Int32 nIndex)
307 {
308     if (nIndex<0 || static_cast<size_t>(nIndex)>=maItems.size())
309         throw RuntimeException();
310     else
311     {
312         maItems[nIndex].mbIsHidden = ! maItems[nIndex].mbIsHidden;
313         ResourceManager::Instance().SetIsDeckEnabled(
314             maItems[nIndex].msDeckId,
315             maItems[nIndex].mbIsHidden);
316         Layout();
317     }
318 }
319 
320 
321 
322 
323 void TabBar::RestoreHideFlags (void)
324 {
325     bool bNeedsLayout (false);
326     for(ItemContainer::iterator iItem(maItems.begin()),iEnd(maItems.end());
327         iItem!=iEnd;
328         ++iItem)
329     {
330         if (iItem->mbIsHidden != iItem->mbIsHiddenByDefault)
331         {
332             iItem->mbIsHidden = iItem->mbIsHiddenByDefault;
333             bNeedsLayout = true;
334         }
335     }
336     if (bNeedsLayout)
337         Layout();
338 }
339 
340 
341 
342 
343 void TabBar::UpdateFocusManager (FocusManager& rFocusManager)
344 {
345     ::std::vector<Button*> aButtons;
346     aButtons.reserve(maItems.size()+1);
347 
348     aButtons.push_back(mpMenuButton.get());
349     for(ItemContainer::const_iterator
350             iItem(maItems.begin()), iEnd(maItems.end());
351         iItem!=iEnd;
352         ++iItem)
353     {
354         aButtons.push_back(iItem->mpButton.get());
355     }
356     rFocusManager.SetButtons(aButtons);
357 }
358 
359 
360 
361 
362 IMPL_LINK(TabBar, OnToolboxClicked, void*, EMPTYARG)
363 {
364     ::std::vector<DeckMenuData> aSelectionData;
365     ::std::vector<DeckMenuData> aShowData;
366 
367     for(ItemContainer::const_iterator iItem(maItems.begin()),iEnd(maItems.end());
368         iItem!=iEnd;
369         ++iItem)
370     {
371         const DeckDescriptor* pDeckDescriptor = ResourceManager::Instance().GetDeckDescriptor(iItem->msDeckId);
372         if (pDeckDescriptor != NULL)
373         {
374             if ( ! iItem->mbIsHidden)
375                 aSelectionData.push_back(
376                     DeckMenuData(
377                         pDeckDescriptor->msTitle,
378                         pDeckDescriptor->msId,
379                         iItem->mpButton->IsChecked()));
380 
381             aShowData.push_back(
382                 DeckMenuData(
383                     pDeckDescriptor->msTitle,
384                     pDeckDescriptor->msId,
385                     !iItem->mbIsHidden));
386         }
387     }
388 
389     maPopupMenuProvider(
390         Rectangle(
391             mpMenuButton->GetPosPixel(),
392             mpMenuButton->GetSizePixel()),
393         aSelectionData,
394         aShowData);
395 
396     return 0;
397 }
398 
399 
400 
401 } } // end of namespace sfx2::sidebar
402