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
CompareURL(const OUString & rsPaneURL)80 bool CompareURL (const OUString& rsPaneURL) { return msPaneURL.equals(rsPaneURL); }
ComparePane(const Reference<XResource> & rxPane)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:
PaneContainer(void)89 PaneContainer (void) {}
90 };
91
92
93
BasicPaneFactory_createInstance(const Reference<XComponentContext> & rxContext)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
BasicPaneFactory_getImplementationName(void)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
BasicPaneFactory_getSupportedServiceNames(void)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
BasicPaneFactory(const Reference<XComponentContext> & rxContext)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
~BasicPaneFactory(void)141 BasicPaneFactory::~BasicPaneFactory (void)
142 {
143 }
144
145
146
147
disposing(void)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
initialize(const Sequence<Any> & aArguments)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
createResource(const Reference<XResourceId> & rxPaneId)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
releaseResource(const Reference<XResource> & rxPane)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
notifyConfigurationChange(const ConfigurationChangeEvent & rEvent)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
disposing(const lang::EventObject & rEventObject)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
CreateFrameWindowPane(const Reference<XResourceId> & rxPaneId)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
CreateFullScreenPane(const Reference<XComponentContext> & rxComponentContext,const Reference<XResourceId> & rxPaneId)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
CreateChildWindowPane(const Reference<XResourceId> & rxPaneId,const PaneDescriptor & rDescriptor)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
ThrowIfDisposed(void) const539 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