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