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