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