1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include "precompiled_sd.hxx" 29 30 #include "BasicPaneFactory.hxx" 31 32 #include "ChildWindowPane.hxx" 33 #include "FrameWindowPane.hxx" 34 #include "FullScreenPane.hxx" 35 36 #include "framework/FrameworkHelper.hxx" 37 #include "ViewShellBase.hxx" 38 #include "PaneChildWindows.hxx" 39 #include "DrawController.hxx" 40 #include "DrawDocShell.hxx" 41 #include <com/sun/star/drawing/framework/XControllerManager.hpp> 42 #include <boost/bind.hpp> 43 44 45 using namespace ::com::sun::star; 46 using namespace ::com::sun::star::uno; 47 using namespace ::com::sun::star::lang; 48 using namespace ::com::sun::star::drawing::framework; 49 50 using ::rtl::OUString; 51 using ::sd::framework::FrameworkHelper; 52 53 namespace { 54 enum PaneId { 55 CenterPaneId, 56 FullScreenPaneId, 57 LeftImpressPaneId, 58 LeftDrawPaneId, 59 RightPaneId 60 }; 61 62 static const sal_Int32 gnConfigurationUpdateStartEvent(0); 63 static const sal_Int32 gnConfigurationUpdateEndEvent(1); 64 } 65 66 namespace sd { namespace framework { 67 68 69 /** Store URL, XPane reference and (local) PaneId for every pane factory 70 that is registered at the PaneController. 71 */ 72 class BasicPaneFactory::PaneDescriptor 73 { 74 public: 75 OUString msPaneURL; 76 Reference<XResource> mxPane; 77 PaneId mePaneId; 78 /** The mbReleased flag is set when the pane has been released. Some 79 panes are just hidden and destroyed. When the pane is reused this 80 flag is reset. 81 */ 82 bool mbIsReleased; 83 bool mbIsChildWindow; 84 85 bool CompareURL (const OUString& rsPaneURL) { return msPaneURL.equals(rsPaneURL); } 86 bool ComparePane (const Reference<XResource>& rxPane) { return mxPane==rxPane; } 87 }; 88 89 90 class BasicPaneFactory::PaneContainer 91 : public ::std::vector<PaneDescriptor> 92 { 93 public: 94 PaneContainer (void) {} 95 }; 96 97 98 99 Reference<XInterface> SAL_CALL BasicPaneFactory_createInstance ( 100 const Reference<XComponentContext>& rxContext) 101 { 102 return Reference<XInterface>(static_cast<XWeak*>(new BasicPaneFactory(rxContext))); 103 } 104 105 106 107 108 ::rtl::OUString BasicPaneFactory_getImplementationName (void) throw(RuntimeException) 109 { 110 return ::rtl::OUString( 111 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Draw.framework.BasicPaneFactory")); 112 } 113 114 115 116 117 Sequence<rtl::OUString> SAL_CALL BasicPaneFactory_getSupportedServiceNames (void) 118 throw (RuntimeException) 119 { 120 static const ::rtl::OUString sServiceName( 121 ::rtl::OUString::createFromAscii("com.sun.star.drawing.framework.BasicPaneFactory")); 122 return Sequence<rtl::OUString>(&sServiceName, 1); 123 } 124 125 126 127 128 //===== PaneFactory =========================================================== 129 130 BasicPaneFactory::BasicPaneFactory ( 131 const Reference<XComponentContext>& rxContext) 132 : BasicPaneFactoryInterfaceBase(m_aMutex), 133 mxComponentContext(rxContext), 134 mxConfigurationControllerWeak(), 135 mpViewShellBase(NULL), 136 mpPaneContainer(new PaneContainer), 137 mbFirstUpdateSeen(false), 138 mpUpdateLockManager() 139 { 140 } 141 142 143 144 145 146 BasicPaneFactory::~BasicPaneFactory (void) 147 { 148 } 149 150 151 152 153 void SAL_CALL BasicPaneFactory::disposing (void) 154 { 155 Reference<XConfigurationController> xCC (mxConfigurationControllerWeak); 156 if (xCC.is()) 157 { 158 xCC->removeResourceFactoryForReference(this); 159 xCC->removeConfigurationChangeListener(this); 160 mxConfigurationControllerWeak = Reference<XConfigurationController>(); 161 } 162 163 for (PaneContainer::const_iterator iDescriptor = mpPaneContainer->begin(); 164 iDescriptor != mpPaneContainer->end(); 165 ++iDescriptor) 166 { 167 if (iDescriptor->mbIsReleased) 168 { 169 Reference<XComponent> xComponent (iDescriptor->mxPane, UNO_QUERY); 170 if (xComponent.is()) 171 { 172 xComponent->removeEventListener(this); 173 xComponent->dispose(); 174 } 175 } 176 } 177 } 178 179 180 181 182 void SAL_CALL BasicPaneFactory::initialize (const Sequence<Any>& aArguments) 183 throw (Exception, RuntimeException) 184 { 185 if (aArguments.getLength() > 0) 186 { 187 try 188 { 189 // Get the XController from the first argument. 190 Reference<frame::XController> xController (aArguments[0], UNO_QUERY_THROW); 191 mxControllerWeak = xController; 192 193 // Tunnel through the controller to obtain access to the ViewShellBase. 194 try 195 { 196 Reference<lang::XUnoTunnel> xTunnel (xController, UNO_QUERY_THROW); 197 DrawController* pController 198 = reinterpret_cast<DrawController*>( 199 (sal::static_int_cast<sal_uIntPtr>( 200 xTunnel->getSomething(DrawController::getUnoTunnelId())))); 201 mpViewShellBase = pController->GetViewShellBase(); 202 mpUpdateLockManager = mpViewShellBase->GetUpdateLockManager(); 203 } 204 catch(RuntimeException&) 205 {} 206 207 Reference<XControllerManager> xCM (xController, UNO_QUERY_THROW); 208 Reference<XConfigurationController> xCC (xCM->getConfigurationController()); 209 mxConfigurationControllerWeak = xCC; 210 211 // Add pane factories for the two left panes (one for Impress and one for 212 // Draw), the center pane, and the right pane. 213 if (xController.is() && xCC.is()) 214 { 215 PaneDescriptor aDescriptor; 216 aDescriptor.msPaneURL = FrameworkHelper::msCenterPaneURL; 217 aDescriptor.mePaneId = CenterPaneId; 218 aDescriptor.mbIsReleased = false; 219 aDescriptor.mbIsChildWindow = false; 220 mpPaneContainer->push_back(aDescriptor); 221 xCC->addResourceFactory(aDescriptor.msPaneURL, this); 222 223 aDescriptor.msPaneURL = FrameworkHelper::msFullScreenPaneURL; 224 aDescriptor.mePaneId = FullScreenPaneId; 225 mpPaneContainer->push_back(aDescriptor); 226 xCC->addResourceFactory(aDescriptor.msPaneURL, this); 227 228 aDescriptor.msPaneURL = FrameworkHelper::msLeftImpressPaneURL; 229 aDescriptor.mePaneId = LeftImpressPaneId; 230 aDescriptor.mbIsChildWindow = true; 231 mpPaneContainer->push_back(aDescriptor); 232 xCC->addResourceFactory(aDescriptor.msPaneURL, this); 233 234 aDescriptor.msPaneURL = FrameworkHelper::msLeftDrawPaneURL; 235 aDescriptor.mePaneId = LeftDrawPaneId; 236 mpPaneContainer->push_back(aDescriptor); 237 xCC->addResourceFactory(aDescriptor.msPaneURL, this); 238 239 aDescriptor.msPaneURL = FrameworkHelper::msRightPaneURL; 240 aDescriptor.mePaneId = RightPaneId; 241 mpPaneContainer->push_back(aDescriptor); 242 xCC->addResourceFactory(aDescriptor.msPaneURL, this); 243 } 244 245 // Register as configuration change listener. 246 if (xCC.is()) 247 { 248 xCC->addConfigurationChangeListener( 249 this, 250 FrameworkHelper::msConfigurationUpdateStartEvent, 251 makeAny(gnConfigurationUpdateStartEvent)); 252 xCC->addConfigurationChangeListener( 253 this, 254 FrameworkHelper::msConfigurationUpdateEndEvent, 255 makeAny(gnConfigurationUpdateEndEvent)); 256 } 257 } 258 catch (RuntimeException&) 259 { 260 Reference<XConfigurationController> xCC (mxConfigurationControllerWeak); 261 if (xCC.is()) 262 xCC->removeResourceFactoryForReference(this); 263 } 264 } 265 } 266 267 268 269 270 //===== XPaneFactory ========================================================== 271 272 Reference<XResource> SAL_CALL BasicPaneFactory::createResource ( 273 const Reference<XResourceId>& rxPaneId) 274 throw (RuntimeException, IllegalArgumentException, WrappedTargetException) 275 { 276 ThrowIfDisposed(); 277 278 Reference<XResource> xPane; 279 280 // Based on the ResourceURL of the given ResourceId look up the 281 // corresponding factory descriptor. 282 PaneContainer::iterator iDescriptor ( 283 ::std::find_if ( 284 mpPaneContainer->begin(), 285 mpPaneContainer->end(), 286 ::boost::bind(&PaneDescriptor::CompareURL, _1, rxPaneId->getResourceURL()))); 287 288 if (iDescriptor != mpPaneContainer->end()) 289 { 290 if (iDescriptor->mxPane.is()) 291 { 292 // The pane has already been created and is still active (has 293 // not yet been released). This should not happen. 294 xPane = iDescriptor->mxPane; 295 } 296 else 297 { 298 // Create a new pane. 299 switch (iDescriptor->mePaneId) 300 { 301 case CenterPaneId: 302 xPane = CreateFrameWindowPane(rxPaneId); 303 break; 304 305 case FullScreenPaneId: 306 xPane = CreateFullScreenPane(mxComponentContext, rxPaneId); 307 break; 308 309 case LeftImpressPaneId: 310 case LeftDrawPaneId: 311 case RightPaneId: 312 xPane = CreateChildWindowPane( 313 rxPaneId, 314 *iDescriptor); 315 break; 316 } 317 iDescriptor->mxPane = xPane; 318 319 // Listen for the pane being disposed. 320 Reference<lang::XComponent> xComponent (xPane, UNO_QUERY); 321 if (xComponent.is()) 322 xComponent->addEventListener(this); 323 } 324 iDescriptor->mbIsReleased = false; 325 } 326 else 327 { 328 // The requested pane can not be created by any of the factories 329 // managed by the called BasicPaneFactory object. 330 throw lang::IllegalArgumentException( 331 ::rtl::OUString::createFromAscii( 332 "BasicPaneFactory::createPane() called for unknown resource id"), 333 NULL, 334 0); 335 } 336 337 return xPane; 338 } 339 340 341 342 343 344 void SAL_CALL BasicPaneFactory::releaseResource ( 345 const Reference<XResource>& rxPane) 346 throw (RuntimeException) 347 { 348 ThrowIfDisposed(); 349 350 // Based on the given XPane reference look up the corresponding factory 351 // descriptor. 352 PaneContainer::iterator iDescriptor ( 353 ::std::find_if( 354 mpPaneContainer->begin(), 355 mpPaneContainer->end(), 356 ::boost::bind(&PaneDescriptor::ComparePane, _1, rxPane))); 357 358 if (iDescriptor != mpPaneContainer->end()) 359 { 360 // The given pane was created by one of the factories. Child 361 // windows are just hidden and will be reused when requested later. 362 // Other windows are disposed and their reference is reset so that 363 // on the next createPane() call for the same pane type the pane is 364 // created anew. 365 ChildWindowPane* pChildWindowPane = dynamic_cast<ChildWindowPane*>(rxPane.get()); 366 if (pChildWindowPane != NULL) 367 { 368 iDescriptor->mbIsReleased = true; 369 pChildWindowPane->Hide(); 370 } 371 else 372 { 373 iDescriptor->mxPane = NULL; 374 Reference<XComponent> xComponent (rxPane, UNO_QUERY); 375 if (xComponent.is()) 376 { 377 // We are disposing the pane and do not have to be informed of 378 // that. 379 xComponent->removeEventListener(this); 380 xComponent->dispose(); 381 } 382 } 383 } 384 else 385 { 386 // The given XPane reference is either empty or the pane was not 387 // created by any of the factories managed by the called 388 // BasicPaneFactory object. 389 throw lang::IllegalArgumentException( 390 ::rtl::OUString::createFromAscii( 391 "BasicPaneFactory::releasePane() called for pane that that was not created by same factory."), 392 NULL, 393 0); 394 } 395 } 396 397 398 399 400 //===== XConfigurationChangeListener ========================================== 401 402 void SAL_CALL BasicPaneFactory::notifyConfigurationChange ( 403 const ConfigurationChangeEvent& rEvent) 404 throw (RuntimeException) 405 { 406 sal_Int32 nEventType = 0; 407 rEvent.UserData >>= nEventType; 408 switch (nEventType) 409 { 410 case gnConfigurationUpdateStartEvent: 411 // Lock UI updates while we are switching the views except for 412 // the first time after creation. Outherwise this leads to 413 // problems after reload (missing resizes for the side panes). 414 if (mbFirstUpdateSeen) 415 { 416 if (mpUpdateLockManager.get()!=NULL) 417 { 418 // ::osl::Guard< ::osl::Mutex > aGuard (::osl::Mutex::getGlobalMutex()); 419 // mpUpdateLockManager->Lock(); 420 } 421 } 422 else 423 mbFirstUpdateSeen = true; 424 break; 425 426 case gnConfigurationUpdateEndEvent: 427 // Unlock the update lock here when only the visibility of 428 // windows but not the view shells displayed in them have 429 // changed. Otherwise the UpdateLockManager takes care of 430 // unlocking at the right time. 431 if (mpUpdateLockManager.get() != NULL) 432 { 433 ::osl::Guard< ::osl::Mutex > aGuard (::osl::Mutex::getGlobalMutex()); 434 // if (mpUpdateLockManager->IsLocked()) 435 // mpUpdateLockManager->Unlock(); 436 } 437 break; 438 } 439 } 440 441 442 443 444 //===== lang::XEventListener ================================================== 445 446 void SAL_CALL BasicPaneFactory::disposing ( 447 const lang::EventObject& rEventObject) 448 throw (RuntimeException) 449 { 450 if (mxConfigurationControllerWeak == rEventObject.Source) 451 { 452 mxConfigurationControllerWeak = Reference<XConfigurationController>(); 453 } 454 else 455 { 456 // Has one of the panes been disposed? If so, then release the 457 // reference to that pane, but not the pane descriptor. 458 Reference<XResource> xPane (rEventObject.Source, UNO_QUERY); 459 PaneContainer::iterator iDescriptor ( 460 ::std::find_if ( 461 mpPaneContainer->begin(), 462 mpPaneContainer->end(), 463 ::boost::bind(&PaneDescriptor::ComparePane, _1, xPane))); 464 if (iDescriptor != mpPaneContainer->end()) 465 { 466 iDescriptor->mxPane = NULL; 467 } 468 } 469 } 470 471 472 473 474 //----------------------------------------------------------------------------- 475 476 Reference<XResource> BasicPaneFactory::CreateFrameWindowPane ( 477 const Reference<XResourceId>& rxPaneId) 478 { 479 Reference<XResource> xPane; 480 481 if (mpViewShellBase != NULL) 482 { 483 xPane = new FrameWindowPane(rxPaneId, mpViewShellBase->GetViewWindow()); 484 } 485 486 return xPane; 487 } 488 489 490 491 492 Reference<XResource> BasicPaneFactory::CreateFullScreenPane ( 493 const Reference<XComponentContext>& rxComponentContext, 494 const Reference<XResourceId>& rxPaneId) 495 { 496 Reference<XResource> xPane ( 497 new FullScreenPane( 498 rxComponentContext, 499 rxPaneId, 500 mpViewShellBase->GetViewWindow())); 501 502 return xPane; 503 } 504 505 506 507 508 Reference<XResource> BasicPaneFactory::CreateChildWindowPane ( 509 const Reference<XResourceId>& rxPaneId, 510 const PaneDescriptor& rDescriptor) 511 { 512 Reference<XResource> xPane; 513 514 if (mpViewShellBase != NULL) 515 { 516 // Create the corresponding shell and determine the id of the child window. 517 sal_uInt16 nChildWindowId = 0; 518 ::std::auto_ptr<SfxShell> pShell; 519 switch (rDescriptor.mePaneId) 520 { 521 case LeftImpressPaneId: 522 pShell.reset(new LeftImpressPaneShell()); 523 nChildWindowId = ::sd::LeftPaneImpressChildWindow::GetChildWindowId(); 524 break; 525 526 case LeftDrawPaneId: 527 pShell.reset(new LeftDrawPaneShell()); 528 nChildWindowId = ::sd::LeftPaneDrawChildWindow::GetChildWindowId(); 529 break; 530 531 case RightPaneId: 532 pShell.reset(new ToolPanelPaneShell()); 533 nChildWindowId = ::sd::ToolPanelChildWindow::GetChildWindowId(); 534 break; 535 536 default: 537 break; 538 } 539 540 // With shell and child window id create the ChildWindowPane 541 // wrapper. 542 if (pShell.get() != NULL) 543 { 544 xPane = new ChildWindowPane( 545 rxPaneId, 546 nChildWindowId, 547 *mpViewShellBase, 548 pShell); 549 } 550 } 551 552 return xPane; 553 } 554 555 void BasicPaneFactory::ThrowIfDisposed (void) const 556 throw (lang::DisposedException) 557 { 558 if (rBHelper.bDisposed || rBHelper.bInDispose) 559 { 560 throw lang::DisposedException ( 561 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 562 "BasicPaneFactory object has already been disposed")), 563 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this))); 564 } 565 } 566 567 568 } } // end of namespace sd::framework 569