merge the formfield patch from ooo-build
[ooovba.git] / sd / source / ui / framework / factories / BasicPaneFactory.cxx
blob125143974c8cab862ce5b5509c9e9272eb918a4b
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: BasicPaneFactory.cxx,v $
11 * $Revision: 1.3 $
13 * This file is part of OpenOffice.org.
15 * OpenOffice.org is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License version 3
17 * only, as published by the Free Software Foundation.
19 * OpenOffice.org is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Lesser General Public License version 3 for more details
23 * (a copy is included in the LICENSE file that accompanied this code).
25 * You should have received a copy of the GNU Lesser General Public License
26 * version 3 along with OpenOffice.org. If not, see
27 * <http://www.openoffice.org/license.html>
28 * for a copy of the LGPLv3 License.
30 ************************************************************************/
32 #include "precompiled_sd.hxx"
34 #include "BasicPaneFactory.hxx"
36 #include "ChildWindowPane.hxx"
37 #include "FrameWindowPane.hxx"
38 #include "FullScreenPane.hxx"
40 #include "framework/FrameworkHelper.hxx"
41 #include "ViewShellBase.hxx"
42 #include "PaneChildWindows.hxx"
43 #include "DrawController.hxx"
44 #include "DrawDocShell.hxx"
45 #include <com/sun/star/drawing/framework/XControllerManager.hpp>
46 #include <boost/bind.hpp>
49 using namespace ::com::sun::star;
50 using namespace ::com::sun::star::uno;
51 using namespace ::com::sun::star::drawing::framework;
53 using ::rtl::OUString;
54 using ::sd::framework::FrameworkHelper;
56 namespace {
57 enum PaneId {
58 CenterPaneId,
59 FullScreenPaneId,
60 LeftImpressPaneId,
61 LeftDrawPaneId,
62 RightPaneId
65 static const sal_Int32 gnConfigurationUpdateStartEvent(0);
66 static const sal_Int32 gnConfigurationUpdateEndEvent(1);
69 namespace sd { namespace framework {
72 /** Store URL, XPane reference and (local) PaneId for every pane factory
73 that is registered at the PaneController.
75 class BasicPaneFactory::PaneDescriptor
77 public:
78 OUString msPaneURL;
79 Reference<XResource> mxPane;
80 PaneId mePaneId;
81 /** The mbReleased flag is set when the pane has been released. Some
82 panes are just hidden and destroyed. When the pane is reused this
83 flag is reset.
85 bool mbIsReleased;
86 bool mbIsChildWindow;
88 bool CompareURL (const OUString& rsPaneURL) { return msPaneURL.equals(rsPaneURL); }
89 bool ComparePane (const Reference<XResource>& rxPane) { return mxPane==rxPane; }
93 class BasicPaneFactory::PaneContainer
94 : public ::std::vector<PaneDescriptor>
96 public:
97 PaneContainer (void) {}
102 Reference<XInterface> SAL_CALL BasicPaneFactory_createInstance (
103 const Reference<XComponentContext>& rxContext)
105 return Reference<XInterface>(static_cast<XWeak*>(new BasicPaneFactory(rxContext)));
111 ::rtl::OUString BasicPaneFactory_getImplementationName (void) throw(RuntimeException)
113 return ::rtl::OUString(
114 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Draw.framework.BasicPaneFactory"));
120 Sequence<rtl::OUString> SAL_CALL BasicPaneFactory_getSupportedServiceNames (void)
121 throw (RuntimeException)
123 static const ::rtl::OUString sServiceName(
124 ::rtl::OUString::createFromAscii("com.sun.star.drawing.framework.BasicPaneFactory"));
125 return Sequence<rtl::OUString>(&sServiceName, 1);
131 //===== PaneFactory ===========================================================
133 BasicPaneFactory::BasicPaneFactory (
134 const Reference<XComponentContext>& rxContext)
135 : BasicPaneFactoryInterfaceBase(m_aMutex),
136 mxComponentContext(rxContext),
137 mxConfigurationControllerWeak(),
138 mpViewShellBase(NULL),
139 mpPaneContainer(new PaneContainer),
140 mbFirstUpdateSeen(false),
141 mpUpdateLockManager()
149 BasicPaneFactory::~BasicPaneFactory (void)
156 void SAL_CALL BasicPaneFactory::disposing (void)
158 Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
159 if (xCC.is())
161 xCC->removeResourceFactoryForReference(this);
162 xCC->removeConfigurationChangeListener(this);
163 mxConfigurationControllerWeak = Reference<XConfigurationController>();
166 for (PaneContainer::const_iterator iDescriptor = mpPaneContainer->begin();
167 iDescriptor != mpPaneContainer->end();
168 ++iDescriptor)
170 if (iDescriptor->mbIsReleased)
172 Reference<XComponent> xComponent (iDescriptor->mxPane, UNO_QUERY);
173 if (xComponent.is())
175 xComponent->removeEventListener(this);
176 xComponent->dispose();
185 void SAL_CALL BasicPaneFactory::initialize (const Sequence<Any>& aArguments)
186 throw (Exception, RuntimeException)
188 if (aArguments.getLength() > 0)
192 // Get the XController from the first argument.
193 Reference<frame::XController> xController (aArguments[0], UNO_QUERY_THROW);
194 mxControllerWeak = xController;
196 // Tunnel through the controller to obtain access to the ViewShellBase.
199 Reference<lang::XUnoTunnel> xTunnel (xController, UNO_QUERY_THROW);
200 DrawController* pController
201 = reinterpret_cast<DrawController*>(
202 (sal::static_int_cast<sal_uIntPtr>(
203 xTunnel->getSomething(DrawController::getUnoTunnelId()))));
204 mpViewShellBase = pController->GetViewShellBase();
205 mpUpdateLockManager = mpViewShellBase->GetUpdateLockManager();
207 catch(RuntimeException&)
210 Reference<XControllerManager> xCM (xController, UNO_QUERY_THROW);
211 Reference<XConfigurationController> xCC (xCM->getConfigurationController());
212 mxConfigurationControllerWeak = xCC;
214 // Add pane factories for the two left panes (one for Impress and one for
215 // Draw), the center pane, and the right pane.
216 if (xController.is() && xCC.is())
218 PaneDescriptor aDescriptor;
219 aDescriptor.msPaneURL = FrameworkHelper::msCenterPaneURL;
220 aDescriptor.mePaneId = CenterPaneId;
221 aDescriptor.mbIsReleased = false;
222 aDescriptor.mbIsChildWindow = false;
223 mpPaneContainer->push_back(aDescriptor);
224 xCC->addResourceFactory(aDescriptor.msPaneURL, this);
226 aDescriptor.msPaneURL = FrameworkHelper::msFullScreenPaneURL;
227 aDescriptor.mePaneId = FullScreenPaneId;
228 mpPaneContainer->push_back(aDescriptor);
229 xCC->addResourceFactory(aDescriptor.msPaneURL, this);
231 aDescriptor.msPaneURL = FrameworkHelper::msLeftImpressPaneURL;
232 aDescriptor.mePaneId = LeftImpressPaneId;
233 aDescriptor.mbIsChildWindow = true;
234 mpPaneContainer->push_back(aDescriptor);
235 xCC->addResourceFactory(aDescriptor.msPaneURL, this);
237 aDescriptor.msPaneURL = FrameworkHelper::msLeftDrawPaneURL;
238 aDescriptor.mePaneId = LeftDrawPaneId;
239 mpPaneContainer->push_back(aDescriptor);
240 xCC->addResourceFactory(aDescriptor.msPaneURL, this);
242 aDescriptor.msPaneURL = FrameworkHelper::msRightPaneURL;
243 aDescriptor.mePaneId = RightPaneId;
244 mpPaneContainer->push_back(aDescriptor);
245 xCC->addResourceFactory(aDescriptor.msPaneURL, this);
248 // Register as configuration change listener.
249 if (xCC.is())
251 xCC->addConfigurationChangeListener(
252 this,
253 FrameworkHelper::msConfigurationUpdateStartEvent,
254 makeAny(gnConfigurationUpdateStartEvent));
255 xCC->addConfigurationChangeListener(
256 this,
257 FrameworkHelper::msConfigurationUpdateEndEvent,
258 makeAny(gnConfigurationUpdateEndEvent));
261 catch (RuntimeException&)
263 Reference<XConfigurationController> xCC (mxConfigurationControllerWeak);
264 if (xCC.is())
265 xCC->removeResourceFactoryForReference(this);
273 //===== XPaneFactory ==========================================================
275 Reference<XResource> SAL_CALL BasicPaneFactory::createResource (
276 const Reference<XResourceId>& rxPaneId)
277 throw (RuntimeException)
279 ThrowIfDisposed();
281 Reference<XResource> xPane;
283 // Based on the ResourceURL of the given ResourceId look up the
284 // corresponding factory descriptor.
285 PaneContainer::iterator iDescriptor (
286 ::std::find_if (
287 mpPaneContainer->begin(),
288 mpPaneContainer->end(),
289 ::boost::bind(&PaneDescriptor::CompareURL, _1, rxPaneId->getResourceURL())));
291 if (iDescriptor != mpPaneContainer->end())
293 if (iDescriptor->mxPane.is())
295 // The pane has already been created and is still active (has
296 // not yet been released). This should not happen.
297 xPane = iDescriptor->mxPane;
299 else
301 // Create a new pane.
302 switch (iDescriptor->mePaneId)
304 case CenterPaneId:
305 xPane = CreateFrameWindowPane(rxPaneId);
306 break;
308 case FullScreenPaneId:
309 xPane = CreateFullScreenPane(mxComponentContext, rxPaneId);
310 break;
312 case LeftImpressPaneId:
313 case LeftDrawPaneId:
314 case RightPaneId:
315 xPane = CreateChildWindowPane(
316 rxPaneId,
317 *iDescriptor);
318 break;
320 iDescriptor->mxPane = xPane;
322 // Listen for the pane being disposed.
323 Reference<lang::XComponent> xComponent (xPane, UNO_QUERY);
324 if (xComponent.is())
325 xComponent->addEventListener(this);
327 iDescriptor->mbIsReleased = false;
329 else
331 // The requested pane can not be created by any of the factories
332 // managed by the called BasicPaneFactory object.
333 throw lang::IllegalArgumentException(
334 ::rtl::OUString::createFromAscii(
335 "BasicPaneFactory::createPane() called for unknown resource id"),
336 NULL,
340 return xPane;
347 void SAL_CALL BasicPaneFactory::releaseResource (
348 const Reference<XResource>& rxPane)
349 throw (RuntimeException)
351 ThrowIfDisposed();
353 // Based on the given XPane reference look up the corresponding factory
354 // descriptor.
355 PaneContainer::iterator iDescriptor (
356 ::std::find_if(
357 mpPaneContainer->begin(),
358 mpPaneContainer->end(),
359 ::boost::bind(&PaneDescriptor::ComparePane, _1, rxPane)));
361 if (iDescriptor != mpPaneContainer->end())
363 // The given pane was created by one of the factories. Child
364 // windows are just hidden and will be reused when requested later.
365 // Other windows are disposed and their reference is reset so that
366 // on the next createPane() call for the same pane type the pane is
367 // created anew.
368 ChildWindowPane* pChildWindowPane = dynamic_cast<ChildWindowPane*>(rxPane.get());
369 if (pChildWindowPane != NULL)
371 iDescriptor->mbIsReleased = true;
372 pChildWindowPane->Hide();
374 else
376 iDescriptor->mxPane = NULL;
377 Reference<XComponent> xComponent (rxPane, UNO_QUERY);
378 if (xComponent.is())
380 // We are disposing the pane and do not have to be informed of
381 // that.
382 xComponent->removeEventListener(this);
383 xComponent->dispose();
387 else
389 // The given XPane reference is either empty or the pane was not
390 // created by any of the factories managed by the called
391 // BasicPaneFactory object.
392 throw lang::IllegalArgumentException(
393 ::rtl::OUString::createFromAscii(
394 "BasicPaneFactory::releasePane() called for pane that that was not created by same factory."),
395 NULL,
403 //===== XConfigurationChangeListener ==========================================
405 void SAL_CALL BasicPaneFactory::notifyConfigurationChange (
406 const ConfigurationChangeEvent& rEvent)
407 throw (RuntimeException)
409 sal_Int32 nEventType = 0;
410 rEvent.UserData >>= nEventType;
411 switch (nEventType)
413 case gnConfigurationUpdateStartEvent:
414 // Lock UI updates while we are switching the views except for
415 // the first time after creation. Outherwise this leads to
416 // problems after reload (missing resizes for the side panes).
417 if (mbFirstUpdateSeen)
419 if (mpUpdateLockManager.get()!=NULL)
421 // ::osl::Guard< ::osl::Mutex > aGuard (::osl::Mutex::getGlobalMutex());
422 // mpUpdateLockManager->Lock();
425 else
426 mbFirstUpdateSeen = true;
427 break;
429 case gnConfigurationUpdateEndEvent:
430 // Unlock the update lock here when only the visibility of
431 // windows but not the view shells displayed in them have
432 // changed. Otherwise the UpdateLockManager takes care of
433 // unlocking at the right time.
434 if (mpUpdateLockManager.get() != NULL)
436 ::osl::Guard< ::osl::Mutex > aGuard (::osl::Mutex::getGlobalMutex());
437 // if (mpUpdateLockManager->IsLocked())
438 // mpUpdateLockManager->Unlock();
440 break;
447 //===== lang::XEventListener ==================================================
449 void SAL_CALL BasicPaneFactory::disposing (
450 const lang::EventObject& rEventObject)
451 throw (RuntimeException)
453 if (mxConfigurationControllerWeak == rEventObject.Source)
455 mxConfigurationControllerWeak = Reference<XConfigurationController>();
457 else
459 // Has one of the panes been disposed? If so, then release the
460 // reference to that pane, but not the pane descriptor.
461 Reference<XResource> xPane (rEventObject.Source, UNO_QUERY);
462 PaneContainer::iterator iDescriptor (
463 ::std::find_if (
464 mpPaneContainer->begin(),
465 mpPaneContainer->end(),
466 ::boost::bind(&PaneDescriptor::ComparePane, _1, xPane)));
467 if (iDescriptor != mpPaneContainer->end())
469 iDescriptor->mxPane = NULL;
477 //-----------------------------------------------------------------------------
479 Reference<XResource> BasicPaneFactory::CreateFrameWindowPane (
480 const Reference<XResourceId>& rxPaneId)
482 Reference<XResource> xPane;
484 if (mpViewShellBase != NULL)
486 xPane = new FrameWindowPane(rxPaneId, mpViewShellBase->GetViewWindow());
489 return xPane;
495 Reference<XResource> BasicPaneFactory::CreateFullScreenPane (
496 const Reference<XComponentContext>& rxComponentContext,
497 const Reference<XResourceId>& rxPaneId)
499 Reference<XResource> xPane (
500 new FullScreenPane(
501 rxComponentContext,
502 rxPaneId,
503 mpViewShellBase->GetViewWindow()));
505 return xPane;
511 Reference<XResource> BasicPaneFactory::CreateChildWindowPane (
512 const Reference<XResourceId>& rxPaneId,
513 const PaneDescriptor& rDescriptor)
515 Reference<XResource> xPane;
517 if (mpViewShellBase != NULL)
519 // Create the corresponding shell and determine the id of the child window.
520 USHORT nChildWindowId = 0;
521 ::std::auto_ptr<SfxShell> pShell;
522 switch (rDescriptor.mePaneId)
524 case LeftImpressPaneId:
525 pShell.reset(new LeftImpressPaneShell());
526 nChildWindowId = ::sd::LeftPaneImpressChildWindow::GetChildWindowId();
527 break;
529 case LeftDrawPaneId:
530 pShell.reset(new LeftDrawPaneShell());
531 nChildWindowId = ::sd::LeftPaneDrawChildWindow::GetChildWindowId();
532 break;
534 case RightPaneId:
535 pShell.reset(new RightPaneShell());
536 nChildWindowId = ::sd::RightPaneChildWindow::GetChildWindowId();
537 break;
539 default:
540 break;
543 // With shell and child window id create the ChildWindowPane
544 // wrapper.
545 if (pShell.get() != NULL)
547 xPane = new ChildWindowPane(
548 rxPaneId,
549 nChildWindowId,
550 *mpViewShellBase,
551 pShell);
555 return xPane;
561 bool BasicPaneFactory::IsBoundToChildWindow (const Reference<XResourceId>& rxResourceId) const
563 if ( ! rxResourceId.is())
564 return false;
566 Reference<XResourceId> xAnchorId (rxResourceId->getAnchor());
567 if ( ! xAnchorId.is())
568 return false;
570 const OUString sAnchorURL (xAnchorId->getResourceURL());
571 if (sAnchorURL == FrameworkHelper::msLeftImpressPaneURL)
572 return true;
573 else if (sAnchorURL == FrameworkHelper::msLeftDrawPaneURL)
574 return true;
575 else if (sAnchorURL == FrameworkHelper::msRightPaneURL)
576 return true;
577 else
578 return false;
584 void BasicPaneFactory::ThrowIfDisposed (void) const
585 throw (lang::DisposedException)
587 if (rBHelper.bDisposed || rBHelper.bInDispose)
589 throw lang::DisposedException (
590 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
591 "BasicPaneFactory object has already been disposed")),
592 const_cast<uno::XWeak*>(static_cast<const uno::XWeak*>(this)));
597 } } // end of namespace sd::framework