1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: BasicPaneFactory.cxx,v $
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
;
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
79 Reference
<XResource
> mxPane
;
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
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
>
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
);
161 xCC
->removeResourceFactoryForReference(this);
162 xCC
->removeConfigurationChangeListener(this);
163 mxConfigurationControllerWeak
= Reference
<XConfigurationController
>();
166 for (PaneContainer::const_iterator iDescriptor
= mpPaneContainer
->begin();
167 iDescriptor
!= mpPaneContainer
->end();
170 if (iDescriptor
->mbIsReleased
)
172 Reference
<XComponent
> xComponent (iDescriptor
->mxPane
, UNO_QUERY
);
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.
251 xCC
->addConfigurationChangeListener(
253 FrameworkHelper::msConfigurationUpdateStartEvent
,
254 makeAny(gnConfigurationUpdateStartEvent
));
255 xCC
->addConfigurationChangeListener(
257 FrameworkHelper::msConfigurationUpdateEndEvent
,
258 makeAny(gnConfigurationUpdateEndEvent
));
261 catch (RuntimeException
&)
263 Reference
<XConfigurationController
> xCC (mxConfigurationControllerWeak
);
265 xCC
->removeResourceFactoryForReference(this);
273 //===== XPaneFactory ==========================================================
275 Reference
<XResource
> SAL_CALL
BasicPaneFactory::createResource (
276 const Reference
<XResourceId
>& rxPaneId
)
277 throw (RuntimeException
)
281 Reference
<XResource
> xPane
;
283 // Based on the ResourceURL of the given ResourceId look up the
284 // corresponding factory descriptor.
285 PaneContainer::iterator
iDescriptor (
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
;
301 // Create a new pane.
302 switch (iDescriptor
->mePaneId
)
305 xPane
= CreateFrameWindowPane(rxPaneId
);
308 case FullScreenPaneId
:
309 xPane
= CreateFullScreenPane(mxComponentContext
, rxPaneId
);
312 case LeftImpressPaneId
:
315 xPane
= CreateChildWindowPane(
320 iDescriptor
->mxPane
= xPane
;
322 // Listen for the pane being disposed.
323 Reference
<lang::XComponent
> xComponent (xPane
, UNO_QUERY
);
325 xComponent
->addEventListener(this);
327 iDescriptor
->mbIsReleased
= false;
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"),
347 void SAL_CALL
BasicPaneFactory::releaseResource (
348 const Reference
<XResource
>& rxPane
)
349 throw (RuntimeException
)
353 // Based on the given XPane reference look up the corresponding factory
355 PaneContainer::iterator
iDescriptor (
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
368 ChildWindowPane
* pChildWindowPane
= dynamic_cast<ChildWindowPane
*>(rxPane
.get());
369 if (pChildWindowPane
!= NULL
)
371 iDescriptor
->mbIsReleased
= true;
372 pChildWindowPane
->Hide();
376 iDescriptor
->mxPane
= NULL
;
377 Reference
<XComponent
> xComponent (rxPane
, UNO_QUERY
);
380 // We are disposing the pane and do not have to be informed of
382 xComponent
->removeEventListener(this);
383 xComponent
->dispose();
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."),
403 //===== XConfigurationChangeListener ==========================================
405 void SAL_CALL
BasicPaneFactory::notifyConfigurationChange (
406 const ConfigurationChangeEvent
& rEvent
)
407 throw (RuntimeException
)
409 sal_Int32 nEventType
= 0;
410 rEvent
.UserData
>>= 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();
426 mbFirstUpdateSeen
= true;
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();
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
>();
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 (
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());
495 Reference
<XResource
> BasicPaneFactory::CreateFullScreenPane (
496 const Reference
<XComponentContext
>& rxComponentContext
,
497 const Reference
<XResourceId
>& rxPaneId
)
499 Reference
<XResource
> xPane (
503 mpViewShellBase
->GetViewWindow()));
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();
530 pShell
.reset(new LeftDrawPaneShell());
531 nChildWindowId
= ::sd::LeftPaneDrawChildWindow::GetChildWindowId();
535 pShell
.reset(new RightPaneShell());
536 nChildWindowId
= ::sd::RightPaneChildWindow::GetChildWindowId();
543 // With shell and child window id create the ChildWindowPane
545 if (pShell
.get() != NULL
)
547 xPane
= new ChildWindowPane(
561 bool BasicPaneFactory::IsBoundToChildWindow (const Reference
<XResourceId
>& rxResourceId
) const
563 if ( ! rxResourceId
.is())
566 Reference
<XResourceId
> xAnchorId (rxResourceId
->getAnchor());
567 if ( ! xAnchorId
.is())
570 const OUString
sAnchorURL (xAnchorId
->getResourceURL());
571 if (sAnchorURL
== FrameworkHelper::msLeftImpressPaneURL
)
573 else if (sAnchorURL
== FrameworkHelper::msLeftDrawPaneURL
)
575 else if (sAnchorURL
== FrameworkHelper::msRightPaneURL
)
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