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