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 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 74 TabBar::~TabBar (void) 75 { 76 } 77 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 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 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 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 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 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 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 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 245 long TabBar::Notify (NotifyEvent&) 246 { 247 return sal_False; 248 } 249 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 259 Image TabBar::GetItemImage (const DeckDescriptor& rDeckDescriptor) const 260 { 261 return Tools::GetImage( 262 rDeckDescriptor.msIconURL, 263 rDeckDescriptor.msHighContrastIconURL, 264 mxFrame); 265 } 266 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 278 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 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 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 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 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