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 "ControlFactory.hxx" 27 #include "DeckDescriptor.hxx" 28 #include "Paint.hxx" 29 #include "Theme.hxx" 30 #include "sfx2/imagemgr.hxx" 31 32 #include <vcl/gradient.hxx> 33 #include <vcl/image.hxx> 34 #include <comphelper/processfactory.hxx> 35 #include <comphelper/componentcontext.hxx> 36 #include <comphelper/namedvaluecollection.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 #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString))) 48 49 50 namespace sfx2 { namespace sidebar { 51 52 TabBar::TabBar ( 53 Window* pParentWindow, 54 const Reference<frame::XFrame>& rxFrame, 55 const ::boost::function<void(const DeckDescriptor&)>& rDeckActivationFunctor, 56 const ::boost::function<void(const Rectangle&)>& rPopupMenuProvider) 57 : Window(pParentWindow), 58 mxFrame(rxFrame), 59 mpMenuButton(ControlFactory::CreateMenuButton(this)), 60 maItems(), 61 maDeckActivationFunctor(rDeckActivationFunctor), 62 maPopupMenuProvider(rPopupMenuProvider) 63 { 64 SetBackground(Theme::GetTabBarBackground().GetWallpaper()); 65 66 mpMenuButton->SetHelpText(A2S("This is the menu button")); 67 mpMenuButton->SetQuickHelpText(A2S("This is the menu button")); 68 mpMenuButton->SetModeImage( 69 Theme::GetMenuImage(), 70 Theme::IsHighContrastMode() 71 ? BMP_COLOR_HIGHCONTRAST 72 : BMP_COLOR_NORMAL); 73 mpMenuButton->SetClickHdl(LINK(this, TabBar, OnToolboxClicked)); 74 } 75 76 77 78 79 TabBar::~TabBar (void) 80 { 81 } 82 83 84 85 86 void TabBar::Paint (const Rectangle& rUpdateArea) 87 { 88 Window::Paint(rUpdateArea); 89 90 const sal_Int32 nVerticalPadding (Theme::GetTabMenuPadding()); 91 const sal_Int32 nHorizontalPadding (Theme::GetTabMenuSeparatorPadding()); 92 SetLineColor(Theme::GetTabMenuSeparatorColor()); 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 const SvBorder aPadding (Theme::GetTabBarPadding()); 104 return Theme::GetTabItemSize().Width() + aPadding.Left() + aPadding.Right(); 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::GetMenuImage(), 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 (Theme::GetTabBarPadding()); 176 sal_Int32 nX (aPadding.Top()); 177 sal_Int32 nY (aPadding.Left()); 178 179 if (mpMenuButton != NULL) 180 { 181 mpMenuButton->SetPosSizePixel( 182 Point(nX,nY), 183 Theme::GetTabItemSize()); 184 mpMenuButton->Show(); 185 nY += mpMenuButton->GetSizePixel().Height() + 1 + Theme::GetTabMenuPadding(); 186 mnMenuSeparatorY = nY - Theme::GetTabMenuPadding()/2 - 1; 187 } 188 189 for(ItemContainer::const_iterator 190 iItem(maItems.begin()), iEnd(maItems.end()); 191 iItem!=iEnd; 192 ++iItem) 193 { 194 if (iItem->mbIsHidden) 195 continue; 196 197 Button& rButton (*iItem->mpButton); 198 199 // Place and size the icon. 200 rButton.SetPosSizePixel( 201 Point(nX,nY), 202 Theme::GetTabItemSize()); 203 rButton.Show(); 204 205 nY += rButton.GetSizePixel().Height() + 1 + aPadding.Bottom(); 206 } 207 Invalidate(); 208 } 209 210 211 212 213 void TabBar::HighlightDeck (const ::rtl::OUString& rsDeckId) 214 { 215 for (ItemContainer::const_iterator iItem(maItems.begin()),iEnd(maItems.end()); 216 iItem!=iEnd; 217 ++iItem) 218 { 219 if (iItem->maDeckDescriptor.msId.equals(rsDeckId)) 220 { 221 iItem->mpButton->Check(); 222 break; 223 } 224 } 225 } 226 227 228 229 230 void TabBar::DataChanged (const DataChangedEvent& rDataChangedEvent) 231 { 232 if (rDataChangedEvent.GetType() == DATACHANGED_SETTINGS 233 && (rDataChangedEvent.GetFlags() & SETTINGS_STYLE)!= 0) 234 { 235 UpdateButtonIcons(); 236 Invalidate(); 237 } 238 else 239 Window::DataChanged(rDataChangedEvent); 240 } 241 242 243 244 245 RadioButton* TabBar::CreateTabItem (const DeckDescriptor& rDeckDescriptor) 246 { 247 RadioButton* pItem = ControlFactory::CreateTabItem(this); 248 pItem->SetHelpText(rDeckDescriptor.msHelpText); 249 pItem->SetQuickHelpText(rDeckDescriptor.msHelpText); 250 251 return pItem; 252 } 253 254 255 256 257 Image TabBar::GetItemImage (const DeckDescriptor& rDeckDescriptor) const 258 { 259 const bool bIsHighContrastModeActive (Theme::IsHighContrastMode()); 260 const ::rtl::OUString sIconURL ( 261 bIsHighContrastModeActive 262 ? rDeckDescriptor.msHighContrastIconURL 263 : rDeckDescriptor.msIconURL); 264 if (sIconURL.getLength() > 0) 265 { 266 static const sal_Char* sCommandImagePrefix = "private:commandimage/"; 267 static const sal_Int32 nCommandImagePrefixLen = strlen(sCommandImagePrefix); 268 if (sIconURL.compareToAscii(sCommandImagePrefix, nCommandImagePrefixLen) == 0) 269 { 270 ::rtl::OUStringBuffer aCommandName; 271 aCommandName.appendAscii(".uno:"); 272 aCommandName.append(sIconURL.copy(nCommandImagePrefixLen)); 273 const ::rtl::OUString sCommandName (aCommandName.makeStringAndClear()); 274 275 const Image aPanelImage (GetImage(mxFrame, sCommandName, sal_False, bIsHighContrastModeActive)); 276 return aPanelImage; 277 } 278 else 279 { 280 const ::comphelper::ComponentContext aContext (::comphelper::getProcessServiceFactory()); 281 const Reference<graphic::XGraphicProvider> xGraphicProvider ( 282 aContext.createComponent("com.sun.star.graphic.GraphicProvider"), 283 UNO_QUERY); 284 if ( xGraphicProvider.is()) 285 { 286 ::comphelper::NamedValueCollection aMediaProperties; 287 aMediaProperties.put("URL", sIconURL); 288 const Reference<graphic::XGraphic> xGraphic ( 289 xGraphicProvider->queryGraphic(aMediaProperties.getPropertyValues()), 290 UNO_QUERY); 291 if (xGraphic.is()) 292 return Image(xGraphic); 293 } 294 } 295 } 296 return Image(); 297 } 298 299 300 301 302 IMPL_LINK(TabBar::Item, HandleClick, Button*, pButton) 303 { 304 maDeckActivationFunctor(maDeckDescriptor); 305 return 1; 306 } 307 308 309 310 311 void TabBar::AddPopupMenuEntries ( 312 PopupMenu& rMenu, 313 const sal_Int32 nFirstIndex) 314 { 315 sal_Int32 nIndex (nFirstIndex); 316 for(ItemContainer::const_iterator iItem(maItems.begin()),iEnd(maItems.end()); 317 iItem!=iEnd; 318 ++iItem) 319 { 320 rMenu.InsertItem(nIndex, iItem->maDeckDescriptor.msTitle, MIB_RADIOCHECK); 321 rMenu.CheckItem(nIndex, iItem->mpButton->IsChecked()); 322 ++nIndex; 323 } 324 } 325 326 327 328 329 void TabBar::AddCustomizationMenuEntries ( 330 PopupMenu& rMenu, 331 const sal_Int32 nFirstIndex) 332 { 333 sal_Int32 nIndex (nFirstIndex); 334 for(ItemContainer::const_iterator iItem(maItems.begin()),iEnd(maItems.end()); 335 iItem!=iEnd; 336 ++iItem) 337 { 338 rMenu.InsertItem(nIndex, iItem->maDeckDescriptor.msTitle, MIB_CHECKABLE); 339 rMenu.CheckItem(nIndex, !iItem->mbIsHidden); 340 ++nIndex; 341 } 342 } 343 344 345 346 347 const DeckDescriptor& TabBar::GetDeckDescriptorForIndex (const sal_Int32 nIndex) const 348 { 349 if (nIndex<0 || nIndex>=maItems.size()) 350 throw RuntimeException(); 351 else 352 return maItems[nIndex].maDeckDescriptor; 353 } 354 355 356 357 358 void TabBar::ToggleHideFlag (const sal_Int32 nIndex) 359 { 360 if (nIndex<0 || nIndex>=maItems.size()) 361 throw RuntimeException(); 362 else 363 { 364 maItems[nIndex].mbIsHidden = ! maItems[nIndex].mbIsHidden; 365 Layout(); 366 } 367 } 368 369 370 371 372 void TabBar::RestoreHideFlags (void) 373 { 374 bool bNeedsLayout (false); 375 for(ItemContainer::iterator iItem(maItems.begin()),iEnd(maItems.end()); 376 iItem!=iEnd; 377 ++iItem) 378 { 379 if (iItem->mbIsHidden != iItem->mbIsHiddenByDefault) 380 { 381 iItem->mbIsHidden = iItem->mbIsHiddenByDefault; 382 bNeedsLayout = true; 383 } 384 } 385 if (bNeedsLayout) 386 Layout(); 387 } 388 389 390 391 392 IMPL_LINK(TabBar, OnToolboxClicked, void*, pToolBox) 393 { 394 // mpMenuButton->EndSelection(); 395 maPopupMenuProvider( 396 Rectangle( 397 mpMenuButton->GetPosPixel(), 398 mpMenuButton->GetSizePixel())); 399 400 return 0; 401 } 402 403 404 405 } } // end of namespace sfx2::sidebar 406