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