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 "SidebarController.hxx" 25 #include "Deck.hxx" 26 #include "DeckConfiguration.hxx" 27 #include "DeckTitleBar.hxx" 28 #include "Panel.hxx" 29 #include "SidebarPanel.hxx" 30 #include "SidebarResource.hxx" 31 #include "TabBar.hxx" 32 #include "sfx2/sidebar/Theme.hxx" 33 #include "SidebarDockingWindow.hxx" 34 #include "Context.hxx" 35 36 #include "sfxresid.hxx" 37 #include "sfx2/sfxsids.hrc" 38 #include "sfx2/titledockwin.hxx" 39 #include "sfxlocal.hrc" 40 #include <vcl/floatwin.hxx> 41 #include "splitwin.hxx" 42 #include <svl/smplhint.hxx> 43 #include <tools/link.hxx> 44 #include <comphelper/componentfactory.hxx> 45 #include <comphelper/processfactory.hxx> 46 #include <comphelper/componentcontext.hxx> 47 #include <comphelper/namedvaluecollection.hxx> 48 49 #include <com/sun/star/ui/ContextChangeEventMultiplexer.hpp> 50 #include <com/sun/star/ui/ContextChangeEventObject.hpp> 51 #include <com/sun/star/ui/XUIElementFactory.hpp> 52 #include <com/sun/star/lang/XInitialization.hpp> 53 54 #include <boost/bind.hpp> 55 #include <boost/scoped_array.hpp> 56 57 58 using namespace css; 59 using namespace cssu; 60 using ::rtl::OUString; 61 62 #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString))) 63 64 namespace sfx2 { namespace sidebar { 65 66 namespace { 67 enum MenuId 68 { 69 MID_UNLOCK_TASK_PANEL = 1, 70 MID_LOCK_TASK_PANEL, 71 MID_CUSTOMIZATION, 72 MID_RESTORE_DEFAULT, 73 MID_FIRST_PANEL, 74 MID_FIRST_HIDE = 1000 75 }; 76 } 77 78 79 SidebarController::SidebarController ( 80 SidebarDockingWindow* pParentWindow, 81 const cssu::Reference<css::frame::XFrame>& rxFrame) 82 : SidebarControllerInterfaceBase(m_aMutex), 83 mpCurrentConfiguration(), 84 mpParentWindow(pParentWindow), 85 mpTabBar(new TabBar( 86 mpParentWindow, 87 rxFrame, 88 ::boost::bind(&SidebarController::SwitchToDeck, this, _1), 89 ::boost::bind(&SidebarController::ShowPopupMenu, this, _1,_2,_3))), 90 mxFrame(rxFrame), 91 maCurrentContext(OUString(), OUString()), 92 msCurrentDeckId(A2S("PropertyDeck")), 93 maPropertyChangeForwarder(::boost::bind(&SidebarController::BroadcastPropertyChange, this)), 94 mbIsDeckClosed(false), 95 mnSavedSidebarWidth(pParentWindow->GetSizePixel().Width()) 96 { 97 if (pParentWindow == NULL) 98 { 99 OSL_ASSERT(pParentWindow!=NULL); 100 return; 101 } 102 103 // Listen for context change events. 104 cssu::Reference<css::ui::XContextChangeEventMultiplexer> xMultiplexer ( 105 css::ui::ContextChangeEventMultiplexer::get( 106 ::comphelper::getProcessComponentContext())); 107 if (xMultiplexer.is()) 108 xMultiplexer->addContextChangeEventListener( 109 static_cast<css::ui::XContextChangeEventListener*>(this), 110 mxFrame->getController()); 111 112 // Listen for window events. 113 mpParentWindow->AddEventListener(LINK(this, SidebarController, WindowEventHandler)); 114 115 // Listen for theme property changes. 116 Theme::GetPropertySet()->addPropertyChangeListener( 117 A2S(""), 118 static_cast<css::beans::XPropertyChangeListener*>(this)); 119 } 120 121 122 123 124 SidebarController::~SidebarController (void) 125 { 126 } 127 128 129 130 131 void SAL_CALL SidebarController::disposing (void) 132 { 133 cssu::Reference<css::ui::XContextChangeEventMultiplexer> xMultiplexer ( 134 css::ui::ContextChangeEventMultiplexer::get( 135 ::comphelper::getProcessComponentContext())); 136 if (xMultiplexer.is()) 137 xMultiplexer->removeAllContextChangeEventListeners( 138 static_cast<css::ui::XContextChangeEventListener*>(this)); 139 140 if (mpParentWindow != NULL) 141 { 142 mpParentWindow->RemoveEventListener(LINK(this, SidebarController, WindowEventHandler)); 143 mpParentWindow = NULL; 144 } 145 146 if (mpCurrentConfiguration) 147 { 148 mpCurrentConfiguration->Dispose(); 149 mpCurrentConfiguration.reset(); 150 } 151 152 Theme::GetPropertySet()->removePropertyChangeListener( 153 A2S(""), 154 static_cast<css::beans::XPropertyChangeListener*>(this)); 155 } 156 157 158 159 160 void SAL_CALL SidebarController::notifyContextChangeEvent (const css::ui::ContextChangeEventObject& rEvent) 161 throw(cssu::RuntimeException) 162 { 163 UpdateConfigurations( 164 Context( 165 rEvent.ApplicationName, 166 rEvent.ContextName)); 167 } 168 169 170 171 172 void SAL_CALL SidebarController::disposing (const css::lang::EventObject& rEventObject) 173 throw(cssu::RuntimeException) 174 { 175 (void)rEventObject; 176 177 if (mpCurrentConfiguration) 178 { 179 mpCurrentConfiguration->Dispose(); 180 mpCurrentConfiguration.reset(); 181 } 182 mpTabBar.reset(); 183 } 184 185 186 187 188 void SAL_CALL SidebarController::propertyChange (const css::beans::PropertyChangeEvent& rEvent) 189 throw(cssu::RuntimeException) 190 { 191 (void)rEvent; 192 193 maPropertyChangeForwarder.RequestCall(); 194 } 195 196 197 198 199 void SAL_CALL SidebarController::requestLayout (void) 200 throw(cssu::RuntimeException) 201 { 202 if (mpCurrentConfiguration && mpCurrentConfiguration->mpDeck!=NULL) 203 mpCurrentConfiguration->mpDeck->RequestLayout(); 204 RestrictWidth(); 205 } 206 207 208 209 210 void SidebarController::BroadcastPropertyChange (void) 211 { 212 DataChangedEvent aEvent (DATACHANGED_USER); 213 mpParentWindow->NotifyAllChilds(aEvent); 214 mpParentWindow->Invalidate(INVALIDATE_CHILDREN); 215 } 216 217 218 219 220 void SidebarController::NotifyResize (void) 221 { 222 if (mpTabBar == NULL) 223 { 224 OSL_ASSERT(mpTabBar!=NULL); 225 return; 226 } 227 228 Window* pParentWindow = mpTabBar->GetParent(); 229 230 const sal_Int32 nWidth (pParentWindow->GetSizePixel().Width()); 231 const sal_Int32 nHeight (pParentWindow->GetSizePixel().Height()); 232 233 // Place the deck. 234 Deck* pDeck = NULL; 235 if (mpCurrentConfiguration != NULL && ! mbIsDeckClosed) 236 { 237 pDeck = mpCurrentConfiguration->mpDeck; 238 if (pDeck == NULL) 239 { 240 OSL_ASSERT(mpCurrentConfiguration->mpDeck!=NULL); 241 } 242 } 243 if (pDeck != NULL) 244 { 245 pDeck->SetPosSizePixel(0,0, nWidth-TabBar::GetDefaultWidth(), nHeight); 246 pDeck->Show(); 247 pDeck->RequestLayout(); 248 } 249 250 // Place the tab bar. 251 mpTabBar->SetPosSizePixel(nWidth-TabBar::GetDefaultWidth(),0,TabBar::GetDefaultWidth(),nHeight); 252 mpTabBar->Show(); 253 254 // Determine if the closer of the deck can be shown. 255 if (pDeck!=NULL) 256 { 257 DeckTitleBar* pTitleBar = pDeck->GetTitleBar(); 258 if (pTitleBar != NULL && pTitleBar->IsVisible()) 259 pTitleBar->SetCloserVisible(CanModifyChildWindowWidth()); 260 } 261 262 if (nWidth > TabBar::GetDefaultWidth()) 263 mnSavedSidebarWidth = nWidth; 264 265 RestrictWidth(); 266 #ifdef DEBUG 267 if (mpCurrentConfiguration != NULL) 268 { 269 mpCurrentConfiguration->mpDeck->PrintWindowTree(); 270 sal_Int32 nPanelIndex (0); 271 for (::std::vector<Panel*>::const_iterator 272 iPanel(mpCurrentConfiguration->maPanels.begin()), 273 iEnd(mpCurrentConfiguration->maPanels.end()); 274 iPanel!=iEnd; 275 ++iPanel,++nPanelIndex) 276 { 277 OSL_TRACE("panel %d:", nPanelIndex); 278 (*iPanel)->PrintWindowTree(); 279 } 280 } 281 #endif 282 } 283 284 285 286 287 void SidebarController::UpdateConfigurations (const Context& rContext) 288 { 289 if (maCurrentContext != rContext) 290 { 291 maCurrentContext = rContext; 292 293 // Notify the tab bar about the updated set of decks. 294 ResourceManager::IdContainer aDeckIds; 295 ResourceManager::Instance().GetMatchingDecks ( 296 aDeckIds, 297 rContext, 298 mxFrame); 299 mpTabBar->SetDecks(aDeckIds); 300 301 // Check if the current deck is among the matching decks. 302 bool bCurrentDeckMatches (false); 303 for (ResourceManager::IdContainer::const_iterator 304 iDeck(aDeckIds.begin()), 305 iEnd(aDeckIds.end()); 306 iDeck!=iEnd; 307 ++iDeck) 308 { 309 if (iDeck->equals(msCurrentDeckId)) 310 { 311 bCurrentDeckMatches = true; 312 break; 313 } 314 } 315 316 DeckDescriptor const* pDeckDescriptor = NULL; 317 if ( ! bCurrentDeckMatches) 318 { 319 pDeckDescriptor = ResourceManager::Instance().GetBestMatchingDeck(rContext, mxFrame); 320 msCurrentDeckId = pDeckDescriptor->msId; 321 } 322 else 323 pDeckDescriptor = ResourceManager::Instance().GetDeckDescriptor(msCurrentDeckId); 324 if (pDeckDescriptor != NULL) 325 { 326 msCurrentDeckId = pDeckDescriptor->msId; 327 SwitchToDeck(*pDeckDescriptor, rContext); 328 } 329 } 330 } 331 332 333 334 335 void SidebarController::SwitchToDeck ( 336 const ::rtl::OUString& rsDeckId) 337 { 338 if ( ! msCurrentDeckId.equals(rsDeckId) || mbIsDeckClosed) 339 { 340 const DeckDescriptor* pDeckDescriptor = ResourceManager::Instance().GetDeckDescriptor(rsDeckId); 341 if (pDeckDescriptor != NULL) 342 SwitchToDeck(*pDeckDescriptor, maCurrentContext); 343 } 344 } 345 346 347 348 349 void SidebarController::SwitchToDeck ( 350 const DeckDescriptor& rDeckDescriptor, 351 const Context& rContext) 352 { 353 if ( ! msCurrentDeckId.equals(rDeckDescriptor.msId)) 354 { 355 // When the deck changes then destroy the deck and all panels 356 // and create everything new. 357 if (mpCurrentConfiguration) 358 { 359 mpCurrentConfiguration->Dispose(); 360 mpCurrentConfiguration.reset(); 361 } 362 363 msCurrentDeckId = rDeckDescriptor.msId; 364 } 365 366 // Reopen the deck when necessary. 367 OpenDeck(); 368 369 // Determine the panels to display in the deck. 370 ResourceManager::IdContainer aPanelIds; 371 ResourceManager::Instance().GetMatchingPanels( 372 aPanelIds, 373 rContext, 374 rDeckDescriptor.msId, 375 mxFrame); 376 377 // Provide a configuration and Deck object. 378 if ( ! mpCurrentConfiguration) 379 { 380 mpCurrentConfiguration.reset(new DeckConfiguration); 381 mpCurrentConfiguration->mpDeck = new Deck( 382 rDeckDescriptor, 383 mpParentWindow, 384 ::boost::bind(&SidebarController::CloseDeck, this)); 385 } 386 387 // Update the panel list. 388 const sal_Int32 nNewPanelCount (aPanelIds.size()); 389 ::std::vector<Panel*> aNewPanels; 390 ::std::vector<Panel*> aCurrentPanels; 391 if (mpCurrentConfiguration) 392 aCurrentPanels.swap(mpCurrentConfiguration->maPanels); 393 aNewPanels.resize(nNewPanelCount); 394 sal_Int32 nWriteIndex (0); 395 for (sal_Int32 nReadIndex=0; nReadIndex<nNewPanelCount; ++nReadIndex) 396 { 397 const OUString& rsPanelId (aPanelIds[nReadIndex]); 398 399 // Find the corresponding panel among the currently active 400 // panels. 401 ::std::vector<Panel*>::iterator iPanel (::std::find_if( 402 aCurrentPanels.begin(), 403 aCurrentPanels.end(), 404 ::boost::bind(&Panel::HasIdPredicate, _1, ::boost::cref(rsPanelId)))); 405 if (iPanel != aCurrentPanels.end()) 406 { 407 // Panel already exists in current configuration. Move it 408 // to new configuration. 409 aNewPanels[nWriteIndex] = *iPanel; 410 aCurrentPanels[::std::distance(aCurrentPanels.begin(), iPanel)] = NULL; 411 } 412 else 413 { 414 // Panel does not yet exist. Create it. 415 aNewPanels[nWriteIndex] = CreatePanel( 416 rsPanelId, 417 mpCurrentConfiguration->mpDeck->GetPanelParentWindow()); 418 } 419 if (aNewPanels[nWriteIndex] != NULL) 420 ++nWriteIndex; 421 } 422 aNewPanels.resize(nWriteIndex); 423 424 // Destroy all panels that are not used in the new configuration. 425 for (::std::vector<Panel*>::const_iterator iPanel(aCurrentPanels.begin()),iEnd(aCurrentPanels.end()); 426 iPanel!=iEnd; 427 ++iPanel) 428 { 429 if (*iPanel != NULL) 430 (*iPanel)->Dispose(); 431 } 432 433 // Activate the deck and the new set of panels. 434 mpCurrentConfiguration->maPanels.swap(aNewPanels); 435 mpCurrentConfiguration->mpDeck->SetPosSizePixel( 436 0, 437 0, 438 mpParentWindow->GetSizePixel().Width()-TabBar::GetDefaultWidth(), 439 mpParentWindow->GetSizePixel().Height()); 440 mpCurrentConfiguration->mpDeck->SetPanels(mpCurrentConfiguration->maPanels); 441 mpCurrentConfiguration->mpDeck->Show(); 442 443 // Tell the tab bar to highlight the button associated with the 444 // deck. 445 mpTabBar->HighlightDeck(rDeckDescriptor.msId); 446 447 mpParentWindow->SetText(rDeckDescriptor.msTitle); 448 449 NotifyResize(); 450 } 451 452 453 454 455 Panel* SidebarController::CreatePanel ( 456 const OUString& rsPanelId, 457 ::Window* pParentWindow) 458 { 459 const PanelDescriptor* pPanelDescriptor = ResourceManager::Instance().GetPanelDescriptor(rsPanelId); 460 if (pPanelDescriptor == NULL) 461 return NULL; 462 463 #ifdef DEBUG 464 // Prevent the panel not being created in the same memory of an old panel. 465 ::boost::scoped_array<char> pUnused (new char[sizeof(Panel)]); 466 OSL_TRACE("allocated memory at %x", pUnused.get()); 467 #endif 468 469 // Create the panel which is the parent window of the UIElement. 470 Panel* pPanel = new Panel( 471 *pPanelDescriptor, 472 pParentWindow, 473 ::boost::bind(&Deck::RequestLayout,mpCurrentConfiguration->mpDeck)); 474 475 // Create the XUIElement. 476 Reference<ui::XUIElement> xUIElement (CreateUIElement( 477 pPanel->GetComponentInterface(), 478 pPanelDescriptor->msImplementationURL, 479 pPanel)); 480 if (xUIElement.is()) 481 { 482 // Initialize the panel and add it to the active deck. 483 pPanel->SetUIElement(xUIElement); 484 } 485 else 486 { 487 delete pPanel; 488 pPanel = NULL; 489 } 490 491 return pPanel; 492 } 493 494 495 496 497 Reference<ui::XUIElement> SidebarController::CreateUIElement ( 498 const Reference<awt::XWindowPeer>& rxWindow, 499 const ::rtl::OUString& rsImplementationURL, 500 Panel* pPanel) 501 { 502 try 503 { 504 const ::comphelper::ComponentContext aComponentContext (::comphelper::getProcessServiceFactory()); 505 const Reference<ui::XUIElementFactory> xUIElementFactory ( 506 aComponentContext.createComponent("com.sun.star.ui.UIElementFactoryManager"), 507 UNO_QUERY_THROW); 508 509 // Create the XUIElement. 510 ::comphelper::NamedValueCollection aCreationArguments; 511 aCreationArguments.put("Frame", makeAny(mxFrame)); 512 aCreationArguments.put("ParentWindow", makeAny(rxWindow)); 513 SfxDockingWindow* pSfxDockingWindow = dynamic_cast<SfxDockingWindow*>(mpParentWindow); 514 if (pSfxDockingWindow != NULL) 515 aCreationArguments.put("SfxBindings", makeAny(sal_uInt64(&pSfxDockingWindow->GetBindings()))); 516 aCreationArguments.put("Theme", Theme::GetPropertySet()); 517 aCreationArguments.put("Sidebar", makeAny(Reference<ui::XSidebar>(static_cast<ui::XSidebar*>(this)))); 518 519 Reference<ui::XUIElement> xUIElement( 520 xUIElementFactory->createUIElement( 521 rsImplementationURL, 522 Sequence<beans::PropertyValue>(aCreationArguments.getPropertyValues())), 523 UNO_QUERY_THROW); 524 525 return xUIElement; 526 } 527 catch(Exception& rException) 528 { 529 OSL_TRACE("caught exception: %s", 530 OUStringToOString(rException.Message, RTL_TEXTENCODING_ASCII_US).getStr()); 531 // For some reason we can not create the actual panel. 532 // Probably because its factory was not properly registered. 533 // TODO: provide feedback to developer to better pinpoint the 534 // source of the error. 535 536 return NULL; 537 } 538 } 539 540 541 542 543 IMPL_LINK(SidebarController, WindowEventHandler, VclWindowEvent*, pEvent) 544 { 545 if (pEvent != NULL) 546 { 547 switch (pEvent->GetId()) 548 { 549 case VCLEVENT_WINDOW_GETFOCUS: 550 case VCLEVENT_WINDOW_LOSEFOCUS: 551 break; 552 553 case VCLEVENT_WINDOW_SHOW: 554 case VCLEVENT_WINDOW_RESIZE: 555 NotifyResize(); 556 break; 557 558 case VCLEVENT_WINDOW_DATACHANGED: 559 // Force an update of deck and tab bar to reflect 560 // changes in theme (high contrast mode). 561 Theme::HandleDataChange(); 562 mpParentWindow->Invalidate(); 563 break; 564 565 case SFX_HINT_DYING: 566 dispose(); 567 break; 568 569 default: 570 break; 571 } 572 } 573 574 return sal_True; 575 } 576 577 578 579 580 void SidebarController::ShowPopupMenu ( 581 const Rectangle& rButtonBox, 582 const ::std::vector<TabBar::DeckMenuData>& rDeckSelectionData, 583 const ::std::vector<TabBar::DeckMenuData>& rDeckShowData) const 584 { 585 ::boost::shared_ptr<PopupMenu> pMenu = CreatePopupMenu(rDeckSelectionData, rDeckShowData); 586 pMenu->SetSelectHdl(LINK(this, SidebarController, OnMenuItemSelected)); 587 588 // pass toolbox button rect so the menu can stay open on button up 589 Rectangle aBox (rButtonBox); 590 aBox.Move(mpTabBar->GetPosPixel().X(), 0); 591 pMenu->Execute(mpParentWindow, aBox, POPUPMENU_EXECUTE_DOWN); 592 } 593 594 595 596 597 ::boost::shared_ptr<PopupMenu> SidebarController::CreatePopupMenu ( 598 const ::std::vector<TabBar::DeckMenuData>& rDeckSelectionData, 599 const ::std::vector<TabBar::DeckMenuData>& rDeckShowData) const 600 { 601 ::boost::shared_ptr<PopupMenu> pMenu (new PopupMenu()); 602 FloatingWindow* pMenuWindow = dynamic_cast<FloatingWindow*>(pMenu->GetWindow()); 603 if (pMenuWindow != NULL) 604 { 605 pMenuWindow->SetPopupModeFlags(pMenuWindow->GetPopupModeFlags() | FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE); 606 } 607 608 SidebarResource aLocalResource; 609 610 // Add one entry for every tool panel element to individually make 611 // them visible or hide them. 612 { 613 sal_Int32 nIndex (MID_FIRST_PANEL); 614 for(::std::vector<TabBar::DeckMenuData>::const_iterator 615 iItem(rDeckSelectionData.begin()), 616 iEnd(rDeckSelectionData.end()); 617 iItem!=iEnd; 618 ++iItem) 619 { 620 pMenu->InsertItem(nIndex, iItem->get<0>(), MIB_RADIOCHECK); 621 pMenu->CheckItem(nIndex, iItem->get<2>()); 622 ++nIndex; 623 } 624 } 625 626 pMenu->InsertSeparator(); 627 628 // Add entry for docking or un-docking the tool panel. 629 if (mpParentWindow->IsFloatingMode()) 630 pMenu->InsertItem(MID_LOCK_TASK_PANEL, String(SfxResId(STR_SFX_DOCK))); 631 else 632 pMenu->InsertItem(MID_UNLOCK_TASK_PANEL, String(SfxResId(STR_SFX_UNDOCK))); 633 634 // Add sub menu for customization (hiding of deck tabs.) 635 PopupMenu* pCustomizationMenu = new PopupMenu(); 636 { 637 sal_Int32 nIndex (MID_FIRST_HIDE); 638 for(::std::vector<TabBar::DeckMenuData>::const_iterator 639 iItem(rDeckShowData.begin()), 640 iEnd(rDeckShowData.end()); 641 iItem!=iEnd; 642 ++iItem) 643 { 644 pCustomizationMenu->InsertItem(nIndex, iItem->get<0>(), MIB_CHECKABLE); 645 pCustomizationMenu->CheckItem(nIndex, iItem->get<2>()); 646 ++nIndex; 647 } 648 } 649 650 pCustomizationMenu->InsertSeparator(); 651 pCustomizationMenu->InsertItem(MID_RESTORE_DEFAULT, String(SfxResId(STRING_RESTORE))); 652 653 pMenu->InsertItem(MID_CUSTOMIZATION, String(SfxResId(STRING_CUSTOMIZATION))); 654 pMenu->SetPopupMenu(MID_CUSTOMIZATION, pCustomizationMenu); 655 656 pMenu->RemoveDisabledEntries(sal_False, sal_False); 657 658 return pMenu; 659 } 660 661 662 663 664 IMPL_LINK(SidebarController, OnMenuItemSelected, Menu*, pMenu) 665 { 666 if (pMenu == NULL) 667 { 668 OSL_ENSURE(pMenu!=NULL, "sfx2::sidebar::SidebarController::OnMenuItemSelected: illegal menu!"); 669 return 0; 670 } 671 672 pMenu->Deactivate(); 673 const sal_Int32 nIndex (pMenu->GetCurItemId()); 674 switch (nIndex) 675 { 676 case MID_UNLOCK_TASK_PANEL: 677 mpParentWindow->SetFloatingMode(sal_True); 678 break; 679 680 case MID_LOCK_TASK_PANEL: 681 mpParentWindow->SetFloatingMode(sal_False); 682 break; 683 684 case MID_RESTORE_DEFAULT: 685 mpTabBar->RestoreHideFlags(); 686 break; 687 688 default: 689 { 690 try 691 { 692 if (nIndex >= MID_FIRST_PANEL && nIndex<MID_FIRST_HIDE) 693 SwitchToDeck(mpTabBar->GetDeckIdForIndex(nIndex - MID_FIRST_PANEL)); 694 else if (nIndex >=MID_FIRST_HIDE) 695 mpTabBar->ToggleHideFlag(nIndex-MID_FIRST_HIDE); 696 } 697 catch (RuntimeException&) 698 { 699 } 700 } 701 break; 702 } 703 704 return 1; 705 } 706 707 708 709 710 void SidebarController::CloseDeck (void) 711 { 712 if ( ! mbIsDeckClosed) 713 { 714 mbIsDeckClosed = true; 715 if ( ! mpParentWindow->IsFloatingMode()) 716 mnSavedSidebarWidth = SetChildWindowWidth(TabBar::GetDefaultWidth()); 717 mpParentWindow->SetStyle(mpParentWindow->GetStyle() & ~WB_SIZEABLE); 718 719 if (mpCurrentConfiguration && mpCurrentConfiguration->mpDeck!=NULL) 720 mpCurrentConfiguration->mpDeck->Hide(); 721 722 NotifyResize(); 723 } 724 } 725 726 727 728 729 void SidebarController::OpenDeck (void) 730 { 731 if (mbIsDeckClosed) 732 { 733 mbIsDeckClosed = false; 734 SetChildWindowWidth(mnSavedSidebarWidth); 735 736 if (mpCurrentConfiguration && mpCurrentConfiguration->mpDeck!=NULL) 737 mpCurrentConfiguration->mpDeck->Show(); 738 739 NotifyResize(); 740 } 741 } 742 743 744 745 746 bool SidebarController::CanModifyChildWindowWidth (void) const 747 { 748 SfxSplitWindow* pSplitWindow = dynamic_cast<SfxSplitWindow*>(mpParentWindow->GetParent()); 749 if (pSplitWindow == NULL) 750 { 751 OSL_ASSERT(pSplitWindow!=NULL); 752 return 0; 753 } 754 755 sal_uInt16 nRow (0xffff); 756 sal_uInt16 nColumn (0xffff); 757 pSplitWindow->GetWindowPos(mpParentWindow, nColumn, nRow); 758 759 sal_uInt16 nRowCount (pSplitWindow->GetWindowCount(nColumn)); 760 761 return nRowCount == 1; 762 } 763 764 765 766 767 sal_Int32 SidebarController::SetChildWindowWidth (const sal_Int32 nNewWidth) 768 { 769 SfxSplitWindow* pSplitWindow = dynamic_cast<SfxSplitWindow*>(mpParentWindow->GetParent()); 770 if (pSplitWindow == NULL) 771 return 0; 772 773 sal_uInt16 nRow (0xffff); 774 sal_uInt16 nColumn (0xffff); 775 pSplitWindow->GetWindowPos(mpParentWindow, nColumn, nRow); 776 const long nColumnWidth (pSplitWindow->GetLineSize(nColumn)); 777 778 Window* pWindow = mpParentWindow; 779 const Point aWindowPosition (pWindow->GetPosPixel()); 780 const Size aWindowSize (pWindow->GetSizePixel()); 781 782 pSplitWindow->MoveWindow( 783 mpParentWindow, 784 Size(nNewWidth, aWindowSize.Height()), 785 nColumn, 786 nRow); 787 788 return static_cast<sal_Int32>(nColumnWidth); 789 } 790 791 792 793 794 void SidebarController::RestrictWidth (void) 795 { 796 SfxSplitWindow* pSplitWindow = dynamic_cast<SfxSplitWindow*>(mpParentWindow->GetParent()); 797 if (pSplitWindow != NULL) 798 { 799 const sal_uInt16 nId (pSplitWindow->GetItemId(mpParentWindow)); 800 const sal_uInt16 nSetId (pSplitWindow->GetSet(nId)); 801 // Minimum width is always that of the tabbar. 802 const sal_Int32 nMinimumWidth (TabBar::GetDefaultWidth()); 803 // Maximum width depends on whether the deck is open or closed. 804 const sal_Int32 nMaximumWidth ( 805 mbIsDeckClosed 806 ? TabBar::GetDefaultWidth() 807 : 400); 808 pSplitWindow->SetItemSizeRange( 809 nSetId, 810 Range(nMinimumWidth, nMaximumWidth)); 811 if (nMinimumWidth == nMaximumWidth) 812 pSplitWindow->SetItemSize(nSetId, nMinimumWidth); 813 } 814 } 815 816 817 } } // end of namespace sfx2::sidebar 818