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