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