build fix
[LibreOffice.git] / sfx2 / source / view / sfxbasecontroller.cxx
blobc2cc85fe17c2527068d769a10d7da220a8b033c0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <time.h>
21 #include <sfx2/sfxbasecontroller.hxx>
23 #include <com/sun/star/awt/KeyEvent.hpp>
24 #include <com/sun/star/awt/KeyModifier.hpp>
25 #include <com/sun/star/awt/MouseEvent.hpp>
26 #include <com/sun/star/awt/MouseButton.hpp>
27 #include <com/sun/star/util/XCloseable.hpp>
28 #include <com/sun/star/util/XCloseBroadcaster.hpp>
29 #include <com/sun/star/util/XCloseListener.hpp>
30 #include <com/sun/star/util/CloseVetoException.hpp>
31 #include <com/sun/star/document/XCmisDocument.hpp>
32 #include <com/sun/star/document/XViewDataSupplier.hpp>
33 #include <cppuhelper/implbase.hxx>
34 #include <com/sun/star/frame/FrameActionEvent.hpp>
35 #include <com/sun/star/frame/FrameAction.hpp>
36 #include <com/sun/star/frame/CommandGroup.hpp>
37 #include <com/sun/star/frame/XFrame.hpp>
38 #include <com/sun/star/frame/XBorderResizeListener.hpp>
39 #include <com/sun/star/lang/DisposedException.hpp>
40 #include <com/sun/star/lang/EventObject.hpp>
41 #include <com/sun/star/lang/XEventListener.hpp>
42 #include <com/sun/star/lang/XComponent.hpp>
43 #include <com/sun/star/container/XIndexAccess.hpp>
44 #include <cppuhelper/interfacecontainer.hxx>
45 #include <cppuhelper/typeprovider.hxx>
46 #include <basic/sbstar.hxx>
47 #include <uno/mapping.hxx>
48 #include <sfx2/viewsh.hxx>
49 #include <sfx2/docfac.hxx>
50 #include <sfx2/viewfrm.hxx>
51 #include <sfx2/objsh.hxx>
52 #include <sfx2/app.hxx>
53 #include <sfx2/msgpool.hxx>
54 #include <sfx2/dispatch.hxx>
55 #include <sfx2/userinputinterception.hxx>
57 #include <viewimp.hxx>
58 #include <sfx2/unoctitm.hxx>
59 #include <sfx2/childwin.hxx>
60 #include <sfx2/sfxsids.hrc>
61 #include <sfx2/sfx.hrc>
62 #include <sfx2/sfxresid.hxx>
63 #include <workwin.hxx>
64 #include <sfx2/objface.hxx>
65 #include <sfx2/infobar.hxx>
67 #include <osl/mutex.hxx>
68 #include <tools/diagnose_ex.h>
69 #include <comphelper/sequence.hxx>
70 #include <rtl/ustrbuf.hxx>
71 #include <toolkit/helper/convert.hxx>
72 #include <framework/titlehelper.hxx>
73 #include <comphelper/processfactory.hxx>
74 #include <vcl/msgbox.hxx>
76 #include <sfx2/event.hxx>
77 #include <sfx2/viewfac.hxx>
78 #include "sfxbasecontroller_internal.hxx"
80 #include <unordered_map>
82 #include <com/sun/star/ui/XSidebarProvider.hpp>
83 #include <sfx2/sidebar/UnoSidebar.hxx>
85 #define TIMEOUT_START_RESCHEDULE 10L /* 10th s */
87 using namespace ::com::sun::star;
88 using ::com::sun::star::uno::Reference;
89 using ::com::sun::star::uno::RuntimeException;
90 using ::com::sun::star::uno::UNO_QUERY_THROW;
91 using ::com::sun::star::lang::DisposedException;
92 using ::com::sun::star::awt::XWindow;
93 using ::com::sun::star::frame::XController;
94 using ::com::sun::star::frame::XDispatchProvider;
95 using ::com::sun::star::document::XViewDataSupplier;
96 using ::com::sun::star::container::XIndexAccess;
97 using ::com::sun::star::beans::PropertyValue;
98 using ::com::sun::star::uno::Sequence;
99 using ::com::sun::star::uno::UNO_QUERY;
100 using ::com::sun::star::uno::Exception;
101 using ::com::sun::star::frame::XFrame;
102 using ::com::sun::star::frame::XFrameActionListener;
103 using ::com::sun::star::util::XCloseListener;
104 using ::com::sun::star::task::XStatusIndicator;
105 using ::com::sun::star::frame::XTitle;
106 using ::com::sun::star::ui::XSidebarProvider;
109 struct GroupIDToCommandGroup
111 sal_Int16 nGroupID;
112 sal_Int16 nCommandGroup;
115 static bool bGroupIDMapInitialized = false;
116 static const GroupIDToCommandGroup GroupIDCommandGroupMap[] =
118 { GID_INTERN , frame::CommandGroup::INTERNAL },
119 { GID_APPLICATION , frame::CommandGroup::APPLICATION },
120 { GID_DOCUMENT , frame::CommandGroup::DOCUMENT },
121 { GID_VIEW , frame::CommandGroup::VIEW },
122 { GID_EDIT , frame::CommandGroup::EDIT },
123 { GID_MACRO , frame::CommandGroup::MACRO },
124 { GID_OPTIONS , frame::CommandGroup::OPTIONS },
125 { GID_MATH , frame::CommandGroup::MATH },
126 { GID_NAVIGATOR , frame::CommandGroup::NAVIGATOR },
127 { GID_INSERT , frame::CommandGroup::INSERT },
128 { GID_FORMAT , frame::CommandGroup::FORMAT },
129 { GID_TEMPLATE , frame::CommandGroup::TEMPLATE },
130 { GID_TEXT , frame::CommandGroup::TEXT },
131 { GID_FRAME , frame::CommandGroup::FRAME },
132 { GID_GRAPHIC , frame::CommandGroup::GRAPHIC },
133 { GID_TABLE , frame::CommandGroup::TABLE },
134 { GID_ENUMERATION , frame::CommandGroup::ENUMERATION },
135 { GID_DATA , frame::CommandGroup::DATA },
136 { GID_SPECIAL , frame::CommandGroup::SPECIAL },
137 { GID_IMAGE , frame::CommandGroup::IMAGE },
138 { GID_CHART , frame::CommandGroup::CHART },
139 { GID_EXPLORER , frame::CommandGroup::EXPLORER },
140 { GID_CONNECTOR , frame::CommandGroup::CONNECTOR },
141 { GID_MODIFY , frame::CommandGroup::MODIFY },
142 { GID_DRAWING , frame::CommandGroup::DRAWING },
143 { GID_CONTROLS , frame::CommandGroup::CONTROLS },
144 { 0 , 0 }
147 typedef std::unordered_map< sal_Int16, sal_Int16 > GroupHashMap;
149 sal_Int16 MapGroupIDToCommandGroup( sal_Int16 nGroupID )
151 static GroupHashMap s_aHashMap;
153 if ( !bGroupIDMapInitialized )
155 sal_Int32 i = 0;
156 while ( GroupIDCommandGroupMap[i].nGroupID != 0 )
158 s_aHashMap.insert( GroupHashMap::value_type(
159 GroupIDCommandGroupMap[i].nGroupID,
160 GroupIDCommandGroupMap[i].nCommandGroup ));
161 ++i;
163 bGroupIDMapInitialized = true;
166 GroupHashMap::const_iterator pIter = s_aHashMap.find( nGroupID );
167 if ( pIter != s_aHashMap.end() )
168 return pIter->second;
169 else
170 return frame::CommandGroup::INTERNAL;
173 sal_uInt32 Get10ThSec()
175 sal_uInt32 n10Ticks = 10 * (sal_uInt32)clock();
176 return n10Ticks / CLOCKS_PER_SEC;
179 sal_Int32 m_nInReschedule = 0; /// static counter for rescheduling
181 void reschedule()
183 if ( m_nInReschedule == 0 )
185 ++m_nInReschedule;
186 Application::Reschedule();
187 --m_nInReschedule;
191 class SfxStatusIndicator : public ::cppu::WeakImplHelper< task::XStatusIndicator, lang::XEventListener >
193 friend class SfxBaseController;
194 Reference < XController > xOwner;
195 Reference < task::XStatusIndicator > xProgress;
196 SfxWorkWindow* pWorkWindow;
197 sal_Int32 _nRange;
198 sal_Int32 _nValue;
199 long _nStartTime;
200 public:
201 SfxStatusIndicator(SfxBaseController* pController, SfxWorkWindow* pWork)
202 : xOwner( pController )
203 , pWorkWindow( pWork )
204 , _nRange(0)
205 , _nValue(0)
206 , _nStartTime(0)
208 ++m_refCount;
209 Reference< lang::XComponent > xComponent(
210 (static_cast< ::cppu::OWeakObject* >(pController)), uno::UNO_QUERY );
211 if (xComponent.is())
212 xComponent->addEventListener(this);
213 --m_refCount;
216 virtual void SAL_CALL start(const OUString& aText, sal_Int32 nRange) throw(RuntimeException, std::exception) override;
217 virtual void SAL_CALL end() throw(RuntimeException, std::exception) override;
218 virtual void SAL_CALL setText(const OUString& aText) throw(RuntimeException, std::exception) override;
219 virtual void SAL_CALL setValue(sal_Int32 nValue) throw(RuntimeException, std::exception) override;
220 virtual void SAL_CALL reset() throw(RuntimeException, std::exception) override;
222 virtual void SAL_CALL disposing( const lang::EventObject& Source ) throw(RuntimeException, std::exception) override;
225 void SAL_CALL SfxStatusIndicator::start(const OUString& aText, sal_Int32 nRange) throw(RuntimeException, std::exception)
227 SolarMutexGuard aGuard;
228 if ( xOwner.is() )
230 _nRange = nRange;
231 _nValue = 0;
233 if ( !xProgress.is() )
234 xProgress = pWorkWindow->GetStatusIndicator();
236 if ( xProgress.is() )
237 xProgress->start( aText, nRange );
239 _nStartTime = Get10ThSec();
240 reschedule();
244 void SAL_CALL SfxStatusIndicator::end() throw(RuntimeException, std::exception)
246 SolarMutexGuard aGuard;
247 if ( xOwner.is() )
249 if ( !xProgress.is() )
250 xProgress = pWorkWindow->GetStatusIndicator();
252 if ( xProgress.is() )
253 xProgress->end();
255 reschedule();
259 void SAL_CALL SfxStatusIndicator::setText(const OUString& aText) throw(RuntimeException, std::exception)
261 SolarMutexGuard aGuard;
262 if ( xOwner.is() )
264 if ( !xProgress.is() )
265 xProgress = pWorkWindow->GetStatusIndicator();
267 if ( xProgress.is() )
268 xProgress->setText( aText );
270 reschedule();
274 void SAL_CALL SfxStatusIndicator::setValue( sal_Int32 nValue ) throw(RuntimeException, std::exception)
276 SolarMutexGuard aGuard;
277 if ( xOwner.is() )
279 _nValue = nValue;
281 if ( !xProgress.is() )
282 xProgress = pWorkWindow->GetStatusIndicator();
284 if ( xProgress.is() )
285 xProgress->setValue( nValue );
287 bool bReschedule = (( Get10ThSec() - _nStartTime ) > TIMEOUT_START_RESCHEDULE );
288 if ( bReschedule )
289 reschedule();
293 void SAL_CALL SfxStatusIndicator::reset() throw(RuntimeException, std::exception)
295 SolarMutexGuard aGuard;
296 if ( xOwner.is() )
298 if ( !xProgress.is() )
299 xProgress = pWorkWindow->GetStatusIndicator();
301 if ( xProgress.is() )
302 xProgress->reset();
304 reschedule();
308 void SAL_CALL SfxStatusIndicator::disposing( const lang::EventObject& /*Source*/ ) throw(RuntimeException, std::exception)
310 SolarMutexGuard aGuard;
311 xOwner = nullptr;
312 xProgress.clear();
316 // declaration IMPL_SfxBaseController_ListenerHelper
319 class IMPL_SfxBaseController_ListenerHelper : public ::cppu::WeakImplHelper< frame::XFrameActionListener >
321 public:
322 explicit IMPL_SfxBaseController_ListenerHelper( SfxBaseController* pController ) ;
323 virtual ~IMPL_SfxBaseController_ListenerHelper() override ;
324 virtual void SAL_CALL frameAction( const frame::FrameActionEvent& aEvent ) throw (RuntimeException, std::exception) override ;
325 virtual void SAL_CALL disposing( const lang::EventObject& aEvent ) throw (RuntimeException, std::exception) override ;
327 private:
329 SfxBaseController* m_pController ;
331 } ; // class IMPL_SfxBaseController_ListenerContainer
333 class IMPL_SfxBaseController_CloseListenerHelper : public ::cppu::WeakImplHelper< util::XCloseListener >
335 public:
336 explicit IMPL_SfxBaseController_CloseListenerHelper( SfxBaseController* pController ) ;
337 virtual ~IMPL_SfxBaseController_CloseListenerHelper() override ;
338 virtual void SAL_CALL queryClosing( const lang::EventObject& aEvent, sal_Bool bDeliverOwnership )
339 throw (RuntimeException, util::CloseVetoException, std::exception) override ;
340 virtual void SAL_CALL notifyClosing( const lang::EventObject& aEvent ) throw (RuntimeException, std::exception) override ;
341 virtual void SAL_CALL disposing( const lang::EventObject& aEvent ) throw (RuntimeException, std::exception) override ;
343 private:
345 SfxBaseController* m_pController;
347 } ; // class IMPL_SfxBaseController_ListenerContainer
349 IMPL_SfxBaseController_CloseListenerHelper::IMPL_SfxBaseController_CloseListenerHelper( SfxBaseController* pController )
350 : m_pController ( pController )
354 IMPL_SfxBaseController_CloseListenerHelper::~IMPL_SfxBaseController_CloseListenerHelper()
358 void SAL_CALL IMPL_SfxBaseController_CloseListenerHelper::disposing( const lang::EventObject& /*aEvent*/ ) throw( RuntimeException, std::exception )
362 void SAL_CALL IMPL_SfxBaseController_CloseListenerHelper::queryClosing( const lang::EventObject& aEvent, sal_Bool bDeliverOwnership )
363 throw (RuntimeException, util::CloseVetoException, std::exception)
365 SolarMutexGuard aGuard;
366 SfxViewShell* pShell = m_pController->GetViewShell_Impl();
367 if (pShell)
369 bool bCanClose = pShell->PrepareClose( false );
370 if ( !bCanClose )
372 if ( bDeliverOwnership && ( !pShell->GetWindow() || !pShell->GetWindow()->IsReallyVisible() ) )
374 // ignore Ownership in case of visible frame (will be closed by user)
375 Reference < frame::XModel > xModel( aEvent.Source, uno::UNO_QUERY );
376 if ( xModel.is() )
377 pShell->TakeOwnership_Impl();
378 else
379 pShell->TakeFrameOwnership_Impl();
382 throw util::CloseVetoException("Controller disagree ...",static_cast< ::cppu::OWeakObject*>(this));
387 void SAL_CALL IMPL_SfxBaseController_CloseListenerHelper::notifyClosing( const lang::EventObject& /*aEvent*/ ) throw (RuntimeException, std::exception)
392 // declaration IMPL_SfxBaseController_DataContainer
395 struct IMPL_SfxBaseController_DataContainer
397 Reference< XFrame > m_xFrame ;
398 Reference< XFrameActionListener > m_xListener ;
399 Reference< XCloseListener > m_xCloseListener ;
400 ::sfx2::UserInputInterception m_aUserInputInterception;
401 ::cppu::OMultiTypeInterfaceContainerHelper m_aListenerContainer ;
402 ::comphelper::OInterfaceContainerHelper2 m_aInterceptorContainer ;
403 Reference< XStatusIndicator > m_xIndicator ;
404 SfxViewShell* m_pViewShell ;
405 SfxBaseController* m_pController ;
406 bool m_bDisposing ;
407 bool m_bSuspendState ;
408 Reference< XTitle > m_xTitleHelper ;
409 Sequence< PropertyValue > m_aCreationArgs ;
411 IMPL_SfxBaseController_DataContainer( ::osl::Mutex& aMutex ,
412 SfxViewShell* pViewShell ,
413 SfxBaseController* pController )
414 : m_xListener ( new IMPL_SfxBaseController_ListenerHelper( pController ) )
415 , m_xCloseListener ( new IMPL_SfxBaseController_CloseListenerHelper( pController ) )
416 , m_aUserInputInterception ( *pController, aMutex )
417 , m_aListenerContainer ( aMutex )
418 , m_aInterceptorContainer ( aMutex )
419 , m_pViewShell ( pViewShell )
420 , m_pController ( pController )
421 , m_bDisposing ( false )
422 , m_bSuspendState ( false )
426 } ; // struct IMPL_SfxBaseController_DataContainer
429 // IMPL_SfxBaseController_ListenerHelper constructor
432 IMPL_SfxBaseController_ListenerHelper::IMPL_SfxBaseController_ListenerHelper( SfxBaseController* pController )
433 : m_pController ( pController )
438 // IMPL_SfxBaseController_ListenerHelper destructor
441 IMPL_SfxBaseController_ListenerHelper::~IMPL_SfxBaseController_ListenerHelper()
445 void SAL_CALL IMPL_SfxBaseController_ListenerHelper::frameAction( const frame::FrameActionEvent& aEvent ) throw( RuntimeException, std::exception )
447 SolarMutexGuard aGuard;
448 if (
449 ( m_pController != nullptr ) &&
450 ( aEvent.Frame == m_pController->getFrame() ) &&
451 ( m_pController->GetViewShell_Impl() && m_pController->GetViewShell_Impl()->GetWindow() != nullptr )
454 if ( aEvent.Action == frame::FrameAction_FRAME_UI_ACTIVATED )
456 if ( !m_pController->GetViewShell_Impl()->GetUIActiveIPClient_Impl() )
457 m_pController->GetViewShell_Impl()->GetViewFrame()->MakeActive_Impl( false );
459 else if ( aEvent.Action == frame::FrameAction_CONTEXT_CHANGED )
461 m_pController->GetViewShell_Impl()->GetViewFrame()->GetBindings().ContextChanged_Impl();
467 // IMPL_SfxBaseController_ListenerHelper -> XEventListener
470 void SAL_CALL IMPL_SfxBaseController_ListenerHelper::disposing( const lang::EventObject& /*aEvent*/ ) throw( RuntimeException, std::exception )
472 SolarMutexGuard aGuard;
473 if ( m_pController && m_pController->getFrame().is() )
474 m_pController->getFrame()->removeFrameActionListener( this ) ;
477 SfxBaseController::SfxBaseController( SfxViewShell* pViewShell )
478 : m_pData ( new IMPL_SfxBaseController_DataContainer( m_aMutex, pViewShell, this ))
480 m_pData->m_pViewShell->SetController( this );
484 // SfxBaseController -> destructor
487 SfxBaseController::~SfxBaseController()
489 delete m_pData;
493 // SfxBaseController -> XController2
496 Reference< XWindow > SAL_CALL SfxBaseController::getComponentWindow() throw (RuntimeException, std::exception)
498 SolarMutexGuard aGuard;
499 if ( !m_pData->m_pViewShell )
500 throw DisposedException();
502 return Reference< XWindow >( GetViewFrame_Impl().GetFrame().GetWindow().GetComponentInterface(), UNO_QUERY_THROW );
505 OUString SAL_CALL SfxBaseController::getViewControllerName() throw (RuntimeException, std::exception)
507 SolarMutexGuard aGuard;
508 if ( !m_pData->m_pViewShell || !m_pData->m_pViewShell->GetObjectShell() )
509 throw DisposedException();
511 const SfxObjectFactory& rDocFac( m_pData->m_pViewShell->GetObjectShell()->GetFactory() );
512 sal_uInt16 nViewNo = rDocFac.GetViewNo_Impl( GetViewFrame_Impl().GetCurViewId(), rDocFac.GetViewFactoryCount() );
513 OSL_ENSURE( nViewNo < rDocFac.GetViewFactoryCount(), "SfxBaseController::getViewControllerName: view ID not found in view factories!" );
515 OUString sViewName;
516 if ( nViewNo < rDocFac.GetViewFactoryCount() )
517 sViewName = rDocFac.GetViewFactory( nViewNo ).GetAPIViewName();
519 return sViewName;
522 Sequence< PropertyValue > SAL_CALL SfxBaseController::getCreationArguments() throw (RuntimeException, std::exception)
524 SolarMutexGuard aGuard;
525 if ( !m_pData->m_pViewShell || !m_pData->m_pViewShell->GetObjectShell() )
526 throw DisposedException();
528 return m_pData->m_aCreationArgs;
531 void SfxBaseController::SetCreationArguments_Impl( const Sequence< PropertyValue >& i_rCreationArgs )
533 OSL_ENSURE( m_pData->m_aCreationArgs.getLength() == 0, "SfxBaseController::SetCreationArguments_Impl: not intended to be called twice!" );
534 m_pData->m_aCreationArgs = i_rCreationArgs;
537 SfxViewFrame& SfxBaseController::GetViewFrame_Impl() const
539 ENSURE_OR_THROW( m_pData->m_pViewShell, "not to be called without a view shell" );
540 SfxViewFrame* pActFrame = m_pData->m_pViewShell->GetFrame();
541 ENSURE_OR_THROW( pActFrame, "a view shell without a view frame is pretty pathological" );
542 return *pActFrame;
546 Reference<XSidebarProvider> SAL_CALL SfxBaseController::getSidebar() throw (RuntimeException, std::exception)
548 SfxViewFrame& rViewFrame = GetViewFrame_Impl();
549 SfxFrame& rFrame = rViewFrame.GetFrame();
551 Reference<XSidebarProvider> rSidebar = new SfxUnoSidebar(rFrame.GetFrameInterface());
552 return rSidebar;
556 // SfxBaseController -> XController2 -> XController
559 void SAL_CALL SfxBaseController::attachFrame( const Reference< frame::XFrame >& xFrame ) throw( RuntimeException, std::exception )
561 Reference< frame::XFrame > xTemp( getFrame() ) ;
563 SolarMutexGuard aGuard;
564 if ( xTemp.is() )
566 xTemp->removeFrameActionListener( m_pData->m_xListener ) ;
567 Reference < util::XCloseBroadcaster > xCloseable( xTemp, uno::UNO_QUERY );
568 if ( xCloseable.is() )
569 xCloseable->removeCloseListener( m_pData->m_xCloseListener );
572 m_pData->m_xFrame = xFrame;
574 if ( xFrame.is() )
576 xFrame->addFrameActionListener( m_pData->m_xListener ) ;
577 Reference < util::XCloseBroadcaster > xCloseable( xFrame, uno::UNO_QUERY );
578 if ( xCloseable.is() )
579 xCloseable->addCloseListener( m_pData->m_xCloseListener );
581 if ( m_pData->m_pViewShell )
583 ConnectSfxFrame_Impl( E_CONNECT );
584 ShowInfoBars( );
586 // attaching the frame to the controller is the last step in the creation of a new view, so notify this
587 SfxViewEventHint aHint( SFX_EVENT_VIEWCREATED, GlobalEventConfig::GetEventName( GlobalEventId::VIEWCREATED ), m_pData->m_pViewShell->GetObjectShell(), Reference< frame::XController2 >( this ) );
588 SfxGetpApp()->NotifyEvent( aHint );
594 // SfxBaseController -> XController
597 sal_Bool SAL_CALL SfxBaseController::attachModel( const Reference< frame::XModel >& xModel ) throw( RuntimeException, std::exception )
599 if ( m_pData->m_pViewShell && xModel.is() && xModel != m_pData->m_pViewShell->GetObjectShell()->GetModel() )
601 // don't allow to reattach a model!
602 OSL_FAIL("Can't reattach model!");
603 return false;
606 Reference < util::XCloseBroadcaster > xCloseable( xModel, uno::UNO_QUERY );
607 if ( xCloseable.is() )
608 xCloseable->addCloseListener( m_pData->m_xCloseListener );
609 return true;
613 // SfxBaseController -> XController
616 sal_Bool SAL_CALL SfxBaseController::suspend( sal_Bool bSuspend ) throw( RuntimeException, std::exception )
618 SolarMutexGuard aGuard;
620 // ignore duplicate calls, which doesn't change anything real
621 if (bool(bSuspend) == m_pData->m_bSuspendState)
622 return true;
624 if ( bSuspend )
626 if ( !m_pData->m_pViewShell )
628 m_pData->m_bSuspendState = true;
629 return true;
632 if ( !m_pData->m_pViewShell->PrepareClose() )
633 return false;
635 if ( getFrame().is() )
636 getFrame()->removeFrameActionListener( m_pData->m_xListener ) ;
637 SfxViewFrame* pActFrame = m_pData->m_pViewShell->GetFrame() ;
639 // More Views on the same document?
640 SfxObjectShell* pDocShell = m_pData->m_pViewShell->GetObjectShell() ;
641 bool bOther = false ;
643 for ( const SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocShell ); !bOther && pFrame; pFrame = SfxViewFrame::GetNext( *pFrame, pDocShell ) )
644 bOther = (pFrame != pActFrame);
646 bool bRet = bOther || pDocShell->PrepareClose();
647 if ( bRet )
649 ConnectSfxFrame_Impl( E_DISCONNECT );
650 m_pData->m_bSuspendState = true;
653 return bRet;
655 else
657 if ( getFrame().is() )
658 getFrame()->addFrameActionListener( m_pData->m_xListener ) ;
660 if ( m_pData->m_pViewShell )
662 ConnectSfxFrame_Impl( E_RECONNECT );
665 m_pData->m_bSuspendState = false;
666 return true ;
671 // SfxBaseController -> XController
674 uno::Any SfxBaseController::getViewData() throw( RuntimeException, std::exception )
676 uno::Any aAny;
677 OUString sData;
678 SolarMutexGuard aGuard;
679 if ( m_pData->m_pViewShell )
681 m_pData->m_pViewShell->WriteUserData( sData ) ;
682 aAny <<= sData ;
685 return aAny ;
689 // SfxBaseController -> XController
692 void SAL_CALL SfxBaseController::restoreViewData( const uno::Any& aValue ) throw( RuntimeException, std::exception )
694 SolarMutexGuard aGuard;
695 if ( m_pData->m_pViewShell )
697 OUString sData;
698 aValue >>= sData ;
699 m_pData->m_pViewShell->ReadUserData( sData ) ;
704 // SfxBaseController -> XController
707 Reference< frame::XFrame > SAL_CALL SfxBaseController::getFrame() throw( RuntimeException, std::exception )
709 SolarMutexGuard aGuard;
710 return m_pData->m_xFrame;
714 // SfxBaseController -> XController
717 Reference< frame::XModel > SAL_CALL SfxBaseController::getModel() throw( RuntimeException, std::exception )
719 SolarMutexGuard aGuard;
720 return m_pData->m_pViewShell ? m_pData->m_pViewShell->GetObjectShell()->GetModel() : Reference < frame::XModel > () ;
724 // SfxBaseController -> XDispatchProvider
727 Reference< frame::XDispatch > SAL_CALL SfxBaseController::queryDispatch( const util::URL& aURL ,
728 const OUString& sTargetFrameName,
729 sal_Int32 eSearchFlags ) throw( RuntimeException, std::exception )
731 SolarMutexGuard aGuard;
732 Reference< frame::XDispatch > xDisp;
733 if ( m_pData->m_pViewShell )
735 SfxViewFrame* pAct = m_pData->m_pViewShell->GetViewFrame() ;
736 if ( !m_pData->m_bDisposing )
738 if ( sTargetFrameName == "_beamer" )
740 SfxViewFrame *pFrame = m_pData->m_pViewShell->GetViewFrame();
741 if ( eSearchFlags & ( frame::FrameSearchFlag::CREATE ))
742 pFrame->SetChildWindow( SID_BROWSER, true );
743 SfxChildWindow* pChildWin = pFrame->GetChildWindow( SID_BROWSER );
744 Reference < frame::XFrame > xFrame;
745 if ( pChildWin )
746 xFrame = ( pChildWin->GetFrame() );
747 if ( xFrame.is() )
748 xFrame->setName( sTargetFrameName );
750 Reference< XDispatchProvider > xProv( xFrame, uno::UNO_QUERY );
751 if ( xProv.is() )
752 return xProv->queryDispatch( aURL, sTargetFrameName, frame::FrameSearchFlag::SELF );
755 if ( aURL.Protocol == ".uno:" )
757 OUString aMasterCommand = SfxOfficeDispatch::GetMasterUnoCommand( aURL );
758 bool bMasterCommand( !aMasterCommand.isEmpty() );
760 pAct = m_pData->m_pViewShell->GetViewFrame() ;
761 SfxSlotPool& rSlotPool = SfxSlotPool::GetSlotPool( pAct );
763 const SfxSlot* pSlot( nullptr );
764 if ( bMasterCommand )
765 pSlot = rSlotPool.GetUnoSlot( aMasterCommand );
766 else
767 pSlot = rSlotPool.GetUnoSlot( aURL.Path );
768 if ( pSlot && ( !pAct->GetFrame().IsInPlace() || !pSlot->IsMode( SfxSlotMode::CONTAINER ) ) )
769 return pAct->GetBindings().GetDispatch( pSlot, aURL, bMasterCommand );
770 else
772 // try to find parent SfxViewFrame
773 Reference< frame::XFrame > xParentFrame;
774 Reference< frame::XFrame > xOwnFrame = pAct->GetFrame().GetFrameInterface();
775 if ( xOwnFrame.is() )
776 xParentFrame.set( xOwnFrame->getCreator(), uno::UNO_QUERY );
778 if ( xParentFrame.is() )
780 // TODO/LATER: in future probably SfxViewFrame hierarchy should be the same as XFrame hierarchy
781 // SfxViewFrame* pParentFrame = pAct->GetParentViewFrame();
783 // search the related SfxViewFrame
784 SfxViewFrame* pParentFrame = nullptr;
785 for ( SfxViewFrame* pFrame = SfxViewFrame::GetFirst();
786 pFrame;
787 pFrame = SfxViewFrame::GetNext( *pFrame ) )
789 if ( pFrame->GetFrame().GetFrameInterface() == xParentFrame )
791 pParentFrame = pFrame;
792 break;
796 if ( pParentFrame )
798 SfxSlotPool& rFrameSlotPool = SfxSlotPool::GetSlotPool( pParentFrame );
799 const SfxSlot* pSlot2( nullptr );
800 if ( bMasterCommand )
801 pSlot2 = rFrameSlotPool.GetUnoSlot( aMasterCommand );
802 else
803 pSlot2 = rFrameSlotPool.GetUnoSlot( aURL.Path );
805 if ( pSlot2 )
806 return pParentFrame->GetBindings().GetDispatch( pSlot2, aURL, bMasterCommand );
811 else if ( aURL.Protocol == "slot:" )
813 sal_uInt16 nId = (sal_uInt16) aURL.Path.toInt32();
815 pAct = m_pData->m_pViewShell->GetViewFrame() ;
816 if (nId >= SID_VERB_START && nId <= SID_VERB_END)
818 const SfxSlot* pSlot = m_pData->m_pViewShell->GetVerbSlot_Impl(nId);
819 if ( pSlot )
820 return pAct->GetBindings().GetDispatch( pSlot, aURL, false );
823 SfxSlotPool& rSlotPool = SfxSlotPool::GetSlotPool( pAct );
824 const SfxSlot* pSlot = rSlotPool.GetSlot( nId );
825 if ( pSlot && ( !pAct->GetFrame().IsInPlace() || !pSlot->IsMode( SfxSlotMode::CONTAINER ) ) )
826 return pAct->GetBindings().GetDispatch( pSlot, aURL, false );
827 else
829 // try to find parent SfxViewFrame
830 Reference< frame::XFrame > xParentFrame;
831 Reference< frame::XFrame > xOwnFrame = pAct->GetFrame().GetFrameInterface();
832 if ( xOwnFrame.is() )
833 xParentFrame.set( xOwnFrame->getCreator(), uno::UNO_QUERY );
835 if ( xParentFrame.is() )
837 // TODO/LATER: in future probably SfxViewFrame hierarchy should be the same as XFrame hierarchy
838 // SfxViewFrame* pParentFrame = pAct->GetParentViewFrame();
840 // search the related SfxViewFrame
841 SfxViewFrame* pParentFrame = nullptr;
842 for ( SfxViewFrame* pFrame = SfxViewFrame::GetFirst();
843 pFrame;
844 pFrame = SfxViewFrame::GetNext( *pFrame ) )
846 if ( pFrame->GetFrame().GetFrameInterface() == xParentFrame )
848 pParentFrame = pFrame;
849 break;
853 if ( pParentFrame )
855 SfxSlotPool& rSlotPool2 = SfxSlotPool::GetSlotPool( pParentFrame );
856 const SfxSlot* pSlot2 = rSlotPool2.GetUnoSlot( aURL.Path );
857 if ( pSlot2 )
858 return pParentFrame->GetBindings().GetDispatch( pSlot2, aURL, false );
863 else if( sTargetFrameName == "_self" || sTargetFrameName.isEmpty() )
865 // check for already loaded URL ... but with additional jumpmark!
866 Reference< frame::XModel > xModel = getModel();
867 if( xModel.is() && !aURL.Mark.isEmpty() )
869 SfxSlotPool& rSlotPool = SfxSlotPool::GetSlotPool( pAct );
870 const SfxSlot* pSlot = rSlotPool.GetSlot( SID_JUMPTOMARK );
871 if( !aURL.Main.isEmpty() && aURL.Main == xModel->getURL() && pSlot )
872 return Reference< frame::XDispatch >( new SfxOfficeDispatch( pAct->GetBindings(), pAct->GetDispatcher(), pSlot, aURL) );
878 return xDisp;
882 // SfxBaseController -> XDispatchProvider
885 uno::Sequence< Reference< frame::XDispatch > > SAL_CALL SfxBaseController::queryDispatches( const uno::Sequence< frame::DispatchDescriptor >& seqDescripts ) throw( RuntimeException, std::exception )
887 // Create return list - which must have same size then the given descriptor
888 // It's not allowed to pack it!
889 sal_Int32 nCount = seqDescripts.getLength();
890 uno::Sequence< Reference< frame::XDispatch > > lDispatcher( nCount );
892 for( sal_Int32 i=0; i<nCount; ++i )
894 lDispatcher[i] = queryDispatch( seqDescripts[i].FeatureURL ,
895 seqDescripts[i].FrameName ,
896 seqDescripts[i].SearchFlags );
899 return lDispatcher;
903 // SfxBaseController -> XControllerBorder
906 frame::BorderWidths SAL_CALL SfxBaseController::getBorder()
907 throw ( RuntimeException, std::exception )
909 frame::BorderWidths aResult;
911 SolarMutexGuard aGuard;
912 if ( m_pData->m_pViewShell )
914 SvBorder aBorder = m_pData->m_pViewShell->GetBorderPixel();
915 aResult.Left = aBorder.Left();
916 aResult.Top = aBorder.Top();
917 aResult.Right = aBorder.Right();
918 aResult.Bottom = aBorder.Bottom();
921 return aResult;
924 void SAL_CALL SfxBaseController::addBorderResizeListener( const Reference< frame::XBorderResizeListener >& xListener )
925 throw ( RuntimeException, std::exception )
927 m_pData->m_aListenerContainer.addInterface( cppu::UnoType<frame::XBorderResizeListener>::get(),
928 xListener );
931 void SAL_CALL SfxBaseController::removeBorderResizeListener( const Reference< frame::XBorderResizeListener >& xListener )
932 throw ( RuntimeException, std::exception )
934 m_pData->m_aListenerContainer.removeInterface( cppu::UnoType<frame::XBorderResizeListener>::get(),
935 xListener );
938 awt::Rectangle SAL_CALL SfxBaseController::queryBorderedArea( const awt::Rectangle& aPreliminaryRectangle )
939 throw ( RuntimeException, std::exception )
941 SolarMutexGuard aGuard;
942 if ( m_pData->m_pViewShell )
944 Rectangle aTmpRect = VCLRectangle( aPreliminaryRectangle );
945 m_pData->m_pViewShell->QueryObjAreaPixel( aTmpRect );
946 return AWTRectangle( aTmpRect );
949 return aPreliminaryRectangle;
952 void SfxBaseController::BorderWidthsChanged_Impl()
954 ::cppu::OInterfaceContainerHelper* pContainer = m_pData->m_aListenerContainer.getContainer(
955 cppu::UnoType<frame::XBorderResizeListener>::get());
956 if ( pContainer )
958 frame::BorderWidths aBWidths = getBorder();
959 Reference< uno::XInterface > xThis( static_cast< ::cppu::OWeakObject* >(this), uno::UNO_QUERY );
961 ::cppu::OInterfaceIteratorHelper pIterator(*pContainer);
962 while (pIterator.hasMoreElements())
966 static_cast<frame::XBorderResizeListener*>(pIterator.next())->borderWidthsChanged( xThis, aBWidths );
968 catch (const RuntimeException&)
970 pIterator.remove();
977 // SfxBaseController -> XComponent
980 void SAL_CALL SfxBaseController::dispose() throw( RuntimeException, std::exception )
982 SolarMutexGuard aGuard;
983 Reference< XController > xTmp( this );
984 m_pData->m_bDisposing = true ;
986 lang::EventObject aEventObject;
987 aEventObject.Source = *this ;
988 m_pData->m_aListenerContainer.disposeAndClear( aEventObject ) ;
990 if ( m_pData->m_pController && m_pData->m_pController->getFrame().is() )
991 m_pData->m_pController->getFrame()->removeFrameActionListener( m_pData->m_xListener ) ;
993 if ( m_pData->m_pViewShell )
995 SfxViewFrame* pFrame = m_pData->m_pViewShell->GetViewFrame() ;
996 if ( pFrame && pFrame->GetViewShell() == m_pData->m_pViewShell )
997 pFrame->GetFrame().SetIsClosing_Impl();
998 m_pData->m_pViewShell->DiscardClients_Impl();
999 m_pData->m_pViewShell->pImpl->m_bControllerSet = false;
1001 if ( pFrame )
1003 lang::EventObject aObject;
1004 aObject.Source = *this ;
1006 SfxObjectShell* pDoc = pFrame->GetObjectShell() ;
1007 SfxViewFrame *pView = SfxViewFrame::GetFirst(pDoc);
1008 while( pView )
1010 // if there is another ViewFrame or currently the ViewShell in my ViewFrame is switched (PagePreview)
1011 if ( pView != pFrame || pView->GetViewShell() != m_pData->m_pViewShell )
1012 break;
1013 pView = SfxViewFrame::GetNext( *pView, pDoc );
1016 SfxGetpApp()->NotifyEvent( SfxViewEventHint(SFX_EVENT_CLOSEVIEW, GlobalEventConfig::GetEventName( GlobalEventId::CLOSEVIEW ), pDoc, Reference< frame::XController2 >( this ) ) );
1017 if ( !pView )
1018 SfxGetpApp()->NotifyEvent( SfxEventHint(SFX_EVENT_CLOSEDOC, GlobalEventConfig::GetEventName( GlobalEventId::CLOSEDOC ), pDoc) );
1020 Reference< frame::XModel > xModel = pDoc->GetModel();
1021 Reference < util::XCloseable > xCloseable( xModel, uno::UNO_QUERY );
1022 if ( xModel.is() )
1024 xModel->disconnectController( this );
1025 if ( xCloseable.is() )
1026 xCloseable->removeCloseListener( m_pData->m_xCloseListener );
1029 Reference < frame::XFrame > aXFrame;
1030 attachFrame( aXFrame );
1032 m_pData->m_xListener->disposing( aObject );
1033 SfxViewShell *pShell = m_pData->m_pViewShell;
1034 m_pData->m_pViewShell = nullptr;
1035 if ( pFrame->GetViewShell() == pShell )
1037 // Enter registrations only allowed if we are the owner!
1038 if ( pFrame->GetFrame().OwnsBindings_Impl() )
1039 pFrame->GetBindings().ENTERREGISTRATIONS();
1040 pFrame->GetFrame().SetFrameInterface_Impl( aXFrame );
1041 pFrame->GetFrame().DoClose_Impl();
1048 // SfxBaseController -> XComponent
1051 void SAL_CALL SfxBaseController::addEventListener( const Reference< lang::XEventListener >& aListener ) throw( RuntimeException, std::exception )
1053 m_pData->m_aListenerContainer.addInterface( cppu::UnoType<lang::XEventListener>::get(), aListener );
1057 // SfxBaseController -> XComponent
1060 void SAL_CALL SfxBaseController::removeEventListener( const Reference< lang::XEventListener >& aListener ) throw( RuntimeException, std::exception )
1062 m_pData->m_aListenerContainer.removeInterface( cppu::UnoType<lang::XEventListener>::get(), aListener );
1065 void SfxBaseController::ReleaseShell_Impl()
1067 SolarMutexGuard aGuard;
1068 if ( m_pData->m_pViewShell )
1070 SfxObjectShell* pDoc = m_pData->m_pViewShell->GetObjectShell() ;
1071 Reference< frame::XModel > xModel = pDoc->GetModel();
1072 Reference < util::XCloseable > xCloseable( xModel, uno::UNO_QUERY );
1073 if ( xModel.is() )
1075 xModel->disconnectController( this );
1076 if ( xCloseable.is() )
1077 xCloseable->removeCloseListener( m_pData->m_xCloseListener );
1079 m_pData->m_pViewShell = nullptr;
1081 Reference < frame::XFrame > aXFrame;
1082 attachFrame( aXFrame );
1086 SfxViewShell* SfxBaseController::GetViewShell_Impl() const
1088 return m_pData->m_pViewShell;
1091 Reference< task::XStatusIndicator > SAL_CALL SfxBaseController::getStatusIndicator( ) throw (RuntimeException, std::exception)
1093 SolarMutexGuard aGuard;
1094 if ( m_pData->m_pViewShell && !m_pData->m_xIndicator.is() )
1095 m_pData->m_xIndicator = new SfxStatusIndicator( this, m_pData->m_pViewShell->GetViewFrame()->GetFrame().GetWorkWindow_Impl() );
1096 return m_pData->m_xIndicator;
1099 void SAL_CALL SfxBaseController::registerContextMenuInterceptor( const Reference< ui::XContextMenuInterceptor >& xInterceptor ) throw( RuntimeException, std::exception )
1102 m_pData->m_aInterceptorContainer.addInterface( xInterceptor );
1104 SolarMutexGuard aGuard;
1105 if ( m_pData->m_pViewShell )
1106 m_pData->m_pViewShell->AddContextMenuInterceptor_Impl( xInterceptor );
1109 void SAL_CALL SfxBaseController::releaseContextMenuInterceptor( const Reference< ui::XContextMenuInterceptor >& xInterceptor ) throw( RuntimeException, std::exception )
1112 m_pData->m_aInterceptorContainer.removeInterface( xInterceptor );
1114 SolarMutexGuard aGuard;
1115 if ( m_pData->m_pViewShell )
1116 m_pData->m_pViewShell->RemoveContextMenuInterceptor_Impl( xInterceptor );
1119 void SAL_CALL SfxBaseController::addKeyHandler( const Reference< awt::XKeyHandler >& xHandler ) throw (RuntimeException, std::exception)
1121 SolarMutexGuard aGuard;
1122 m_pData->m_aUserInputInterception.addKeyHandler( xHandler );
1125 void SAL_CALL SfxBaseController::removeKeyHandler( const Reference< awt::XKeyHandler >& xHandler ) throw (RuntimeException, std::exception)
1127 SolarMutexGuard aGuard;
1128 m_pData->m_aUserInputInterception.removeKeyHandler( xHandler );
1131 void SAL_CALL SfxBaseController::addMouseClickHandler( const Reference< awt::XMouseClickHandler >& xHandler ) throw (RuntimeException, std::exception)
1133 SolarMutexGuard aGuard;
1134 m_pData->m_aUserInputInterception.addMouseClickHandler( xHandler );
1137 void SAL_CALL SfxBaseController::removeMouseClickHandler( const Reference< awt::XMouseClickHandler >& xHandler ) throw (RuntimeException, std::exception)
1139 SolarMutexGuard aGuard;
1140 m_pData->m_aUserInputInterception.removeMouseClickHandler( xHandler );
1143 uno::Sequence< sal_Int16 > SAL_CALL SfxBaseController::getSupportedCommandGroups()
1144 throw (RuntimeException, std::exception)
1146 SolarMutexGuard aGuard;
1148 std::vector< sal_Int16 > aGroupList;
1149 SfxViewFrame* pViewFrame( m_pData->m_pViewShell->GetFrame() );
1150 SfxSlotPool* pPool = &SfxSlotPool::GetSlotPool( pViewFrame );
1152 SfxSlotPool* pSlotPool = pPool ? pPool : &SFX_SLOTPOOL();
1153 const SfxSlotMode nMode( SfxSlotMode::TOOLBOXCONFIG|SfxSlotMode::ACCELCONFIG|SfxSlotMode::MENUCONFIG );
1155 // Select Group ( Group 0 is internal )
1156 for ( sal_uInt16 i=0; i<pSlotPool->GetGroupCount(); i++ )
1158 pSlotPool->SeekGroup( i );
1159 const SfxSlot* pSfxSlot = pSlotPool->FirstSlot();
1160 while ( pSfxSlot )
1162 if ( pSfxSlot->GetMode() & nMode )
1164 sal_Int16 nCommandGroup = MapGroupIDToCommandGroup( pSfxSlot->GetGroupId() );
1165 aGroupList.push_back( nCommandGroup );
1166 break;
1168 pSfxSlot = pSlotPool->NextSlot();
1172 return comphelper::containerToSequence( aGroupList );
1175 uno::Sequence< frame::DispatchInformation > SAL_CALL SfxBaseController::getConfigurableDispatchInformation( sal_Int16 nCmdGroup )
1176 throw (RuntimeException, std::exception)
1178 std::list< frame::DispatchInformation > aCmdList;
1180 SolarMutexGuard aGuard;
1181 if ( m_pData->m_pViewShell )
1183 const SfxSlotMode nMode( SfxSlotMode::TOOLBOXCONFIG|SfxSlotMode::ACCELCONFIG|SfxSlotMode::MENUCONFIG );
1185 SfxViewFrame* pViewFrame( m_pData->m_pViewShell->GetFrame() );
1186 SfxSlotPool* pPool( &SfxSlotPool::GetSlotPool( pViewFrame ));
1187 OUString aCmdPrefix( ".uno:" );
1189 SfxSlotPool* pSlotPool = pPool ? pPool : &SFX_SLOTPOOL();
1190 for ( sal_uInt16 i=0; i<pSlotPool->GetGroupCount(); i++ )
1192 pSlotPool->SeekGroup( i );
1193 const SfxSlot* pSfxSlot = pSlotPool->FirstSlot();
1194 if ( pSfxSlot )
1196 sal_Int16 nCommandGroup = MapGroupIDToCommandGroup( pSfxSlot->GetGroupId() );
1197 if ( nCommandGroup == nCmdGroup )
1199 while ( pSfxSlot )
1201 if ( pSfxSlot->GetMode() & nMode )
1203 frame::DispatchInformation aCmdInfo;
1204 OUStringBuffer aBuf( aCmdPrefix );
1205 aBuf.appendAscii( pSfxSlot->GetUnoName() );
1206 aCmdInfo.Command = aBuf.makeStringAndClear();
1207 aCmdInfo.GroupId = nCommandGroup;
1208 aCmdList.push_back( aCmdInfo );
1210 pSfxSlot = pSlotPool->NextSlot();
1217 return comphelper::containerToSequence( aCmdList );
1220 bool SfxBaseController::HandleEvent_Impl( NotifyEvent& rEvent )
1222 return m_pData->m_aUserInputInterception.handleNotifyEvent( rEvent );
1225 bool SfxBaseController::HasKeyListeners_Impl()
1227 return m_pData->m_aUserInputInterception.hasKeyHandlers();
1230 bool SfxBaseController::HasMouseClickListeners_Impl()
1232 return m_pData->m_aUserInputInterception.hasMouseClickListeners();
1235 void SfxBaseController::ConnectSfxFrame_Impl( const ConnectSfxFrame i_eConnect )
1237 ENSURE_OR_THROW( m_pData->m_pViewShell, "not to be called without a view shell" );
1238 SfxViewFrame* pViewFrame = m_pData->m_pViewShell->GetFrame();
1239 ENSURE_OR_THROW( pViewFrame, "a view shell without a view frame is pretty pathological" );
1241 const bool bConnect = ( i_eConnect != E_DISCONNECT );
1243 // disable window and dispatcher
1244 pViewFrame->Enable( bConnect );
1245 pViewFrame->GetDispatcher()->Lock( !bConnect );
1247 if ( bConnect )
1249 if ( i_eConnect == E_CONNECT )
1251 if ( ( m_pData->m_pViewShell->GetObjectShell() != nullptr )
1252 && ( m_pData->m_pViewShell->GetObjectShell()->GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
1255 SfxViewFrame* pViewFrm = m_pData->m_pViewShell->GetViewFrame();
1256 if ( !pViewFrm->GetFrame().IsInPlace() )
1258 // for outplace embedded objects, we want the layout manager to keep the content window
1259 // size constant, if possible
1262 Reference< beans::XPropertySet > xFrameProps( m_pData->m_xFrame, uno::UNO_QUERY_THROW );
1263 Reference< beans::XPropertySet > xLayouterProps(
1264 xFrameProps->getPropertyValue("LayoutManager"), uno::UNO_QUERY_THROW );
1265 xLayouterProps->setPropertyValue("PreserveContentSize", uno::makeAny( true ) );
1267 catch (const uno::Exception&)
1269 DBG_UNHANDLED_EXCEPTION();
1275 // upon DISCONNECT, we did *not* pop the shells from the stack (this is done elsewhere), so upon
1276 // RECONNECT, we're not allowed to push them
1277 if ( i_eConnect != E_RECONNECT )
1279 pViewFrame->GetDispatcher()->Push( *m_pData->m_pViewShell );
1280 if ( m_pData->m_pViewShell->GetSubShell() )
1281 pViewFrame->GetDispatcher()->Push( *m_pData->m_pViewShell->GetSubShell() );
1282 m_pData->m_pViewShell->PushSubShells_Impl();
1283 pViewFrame->GetDispatcher()->Flush();
1286 vcl::Window* pEditWin = m_pData->m_pViewShell->GetWindow();
1287 if ( pEditWin && m_pData->m_pViewShell->IsShowView_Impl() )
1288 pEditWin->Show();
1290 if ( SfxViewFrame::Current() == pViewFrame )
1291 pViewFrame->GetDispatcher()->Update_Impl( true );
1293 vcl::Window* pFrameWin = &pViewFrame->GetWindow();
1294 if ( pFrameWin != &pViewFrame->GetFrame().GetWindow() )
1295 pFrameWin->Show();
1297 if ( i_eConnect == E_CONNECT )
1299 ::comphelper::NamedValueCollection aDocumentArgs( getModel()->getArgs() );
1301 const sal_Int16 nPluginMode = aDocumentArgs.getOrDefault( "PluginMode", sal_Int16( 0 ) );
1302 const bool bHasPluginMode = ( nPluginMode != 0 );
1304 SfxFrame& rFrame = pViewFrame->GetFrame();
1305 SfxObjectShell& rDoc = *m_pData->m_pViewShell->GetObjectShell();
1306 if ( !rFrame.IsMarkedHidden_Impl() )
1308 if ( rDoc.IsHelpDocument() || ( nPluginMode == 2 ) )
1309 pViewFrame->GetDispatcher()->HideUI();
1310 else
1311 pViewFrame->GetDispatcher()->HideUI( false );
1313 if ( rFrame.IsInPlace() )
1314 pViewFrame->LockAdjustPosSizePixel();
1316 if ( nPluginMode == 3 )
1317 rFrame.GetWorkWindow_Impl()->SetInternalDockingAllowed( false );
1319 if ( !rFrame.IsInPlace() )
1320 pViewFrame->GetDispatcher()->Update_Impl();
1321 pViewFrame->Show();
1322 rFrame.GetWindow().Show();
1323 if ( !rFrame.IsInPlace() || ( nPluginMode == 3 ) )
1324 pViewFrame->MakeActive_Impl( rFrame.GetFrameInterface()->isActive() );
1326 if ( rFrame.IsInPlace() )
1328 pViewFrame->UnlockAdjustPosSizePixel();
1329 // force resize for OLE server to fix layout problems of writer and math
1330 // see i53651
1331 if ( nPluginMode == 3 )
1332 pViewFrame->Resize( true );
1335 else
1337 DBG_ASSERT( !rFrame.IsInPlace() && !bHasPluginMode, "Special modes not compatible with hidden mode!" );
1338 rFrame.GetWindow().Show();
1341 // UpdateTitle now, hidden TopFrames have otherwise no Name!
1342 pViewFrame->UpdateTitle();
1344 if ( !rFrame.IsInPlace() )
1345 pViewFrame->Resize( true );
1347 ::comphelper::NamedValueCollection aViewArgs(getCreationArguments());
1349 // sometimes we want to avoid adding to the recent documents
1350 bool bAllowPickListEntry = aViewArgs.getOrDefault("PickListEntry", true);
1351 m_pData->m_pViewShell->GetObjectShell()->AvoidRecentDocs(!bAllowPickListEntry);
1353 // if there's a JumpMark given, then, well, jump to it
1354 const OUString sJumpMark = aViewArgs.getOrDefault( "JumpMark", OUString() );
1355 const bool bHasJumpMark = !sJumpMark.isEmpty();
1356 OSL_ENSURE( ( !m_pData->m_pViewShell->GetObjectShell()->IsLoading() )
1357 || ( sJumpMark.isEmpty() ),
1358 "SfxBaseController::ConnectSfxFrame_Impl: so this code wasn't dead?" );
1359 // Before CWS autorecovery, there was code which postponed jumping to the Mark to a later time
1360 // (SfxObjectShell::PositionView_Impl), but it seems this branch was never used, since this method
1361 // here is never called before the load process finished. At least not with a non-empty jump mark
1362 if ( !sJumpMark.isEmpty() )
1363 m_pData->m_pViewShell->JumpToMark( sJumpMark );
1365 // if no plugin mode and no jump mark was supplied, check whether the document itself can provide view data, and
1366 // if so, forward it to the view/shell.
1367 if ( !bHasPluginMode && !bHasJumpMark )
1369 // Note that this might not be the ideal place here. Restoring view data should, IMO, be the
1370 // responsibility of the loader, not an implementation detail buried here deep within the controller's
1371 // implementation.
1372 // What I think should be done to replace the below code:
1373 // - change SfxBaseController::restoreViewData to also accept a PropertyValue[] (it currently accepts
1374 // a string only), and forward it to its ViewShell's ReadUserDataSequence
1375 // - change the frame loader so that when a new document is loaded (as opposed to an existing
1376 // document being loaded into a new frame), the model's view data is examine the very same
1377 // way as below, and the proper view data is set via XController::restoreViewData
1378 // - extend SfxViewFrame::SwitchToViewShell_Impl. Currently, it cares for the case where a non-PrintPreview
1379 // view is exchanged, and sets the old view's data at the model. It should also care for the other
1380 // way, were the PrintPreview view is left: in this case, the new view should also be initialized
1381 // with the model's view data
1384 Reference< XViewDataSupplier > xViewDataSupplier( getModel(), UNO_QUERY_THROW );
1385 Reference< XIndexAccess > xViewData( xViewDataSupplier->getViewData() );
1387 // find the view data item whose ViewId matches the ID of the view we're just connecting to
1388 const SfxObjectFactory& rDocFactory( rDoc.GetFactory() );
1389 const sal_Int32 nCount = xViewData.is() ? xViewData->getCount() : 0;
1390 sal_Int32 nViewDataIndex = 0;
1391 for ( sal_Int32 i=0; i<nCount; ++i )
1393 const ::comphelper::NamedValueCollection aViewData( xViewData->getByIndex(i) );
1394 OUString sViewId( aViewData.getOrDefault( "ViewId", OUString() ) );
1395 if ( sViewId.isEmpty() )
1396 continue;
1398 const SfxViewFactory* pViewFactory = rDocFactory.GetViewFactoryByViewName( sViewId );
1399 if ( pViewFactory == nullptr )
1400 continue;
1402 if ( pViewFactory->GetOrdinal() == pViewFrame->GetCurViewId() )
1404 nViewDataIndex = i;
1405 break;
1408 if ( nViewDataIndex < nCount )
1410 Sequence< PropertyValue > aViewData;
1411 OSL_VERIFY( xViewData->getByIndex( nViewDataIndex ) >>= aViewData );
1412 if ( aViewData.getLength() > 0 )
1413 m_pData->m_pViewShell->ReadUserDataSequence( aViewData );
1416 catch (const Exception&)
1418 DBG_UNHANDLED_EXCEPTION();
1424 // invalidate slot corresponding to the view shell
1425 const sal_uInt16 nViewNo = m_pData->m_pViewShell->GetObjectShell()->GetFactory().GetViewNo_Impl( pViewFrame->GetCurViewId(), USHRT_MAX );
1426 DBG_ASSERT( nViewNo != USHRT_MAX, "view shell id not found" );
1427 if ( nViewNo != USHRT_MAX )
1428 pViewFrame->GetBindings().Invalidate( nViewNo + SID_VIEWSHELL0 );
1431 void SfxBaseController::ShowInfoBars( )
1433 if ( m_pData->m_pViewShell )
1435 // CMIS verifications
1436 Reference< document::XCmisDocument > xCmisDoc( m_pData->m_pViewShell->GetObjectShell()->GetModel(), uno::UNO_QUERY );
1437 if ( xCmisDoc.is( ) && xCmisDoc->canCheckOut( ) )
1439 uno::Sequence< document::CmisProperty> aCmisProperties = xCmisDoc->getCmisProperties( );
1441 if ( xCmisDoc->isVersionable( ) && aCmisProperties.hasElements( ) )
1443 // Loop over the CMIS Properties to find cmis:isVersionSeriesCheckedOut
1444 // and find if it is a Google Drive file.
1445 bool bIsGoogleFile = false;
1446 bool bCheckedOut = false;
1447 for ( sal_Int32 i = 0; i < aCmisProperties.getLength(); ++i )
1449 if ( aCmisProperties[i].Id == "cmis:isVersionSeriesCheckedOut" ) {
1450 uno::Sequence< sal_Bool > bTmp;
1451 aCmisProperties[i].Value >>= bTmp;
1452 bCheckedOut = bTmp[0];
1454 // if it is a Google Drive file, we don't need the checkout bar,
1455 // still need the checkout feature for the version dialog.
1456 if ( aCmisProperties[i].Name == "title" )
1457 bIsGoogleFile = true;
1460 if ( !bCheckedOut && !bIsGoogleFile )
1462 // Get the Frame and show the InfoBar if not checked out
1463 SfxViewFrame* pViewFrame = m_pData->m_pViewShell->GetFrame();
1464 SfxInfoBarWindow* pInfoBar = pViewFrame->AppendInfoBar( "checkout", SfxResId( STR_NONCHECKEDOUT_DOCUMENT ) );
1465 if (pInfoBar)
1467 VclPtrInstance<PushButton> xBtn(&pViewFrame->GetWindow());
1468 xBtn->SetText(SfxResId(STR_CHECKOUT));
1469 xBtn->SetSizePixel(xBtn->GetOptimalSize());
1470 xBtn->SetClickHdl(LINK(this, SfxBaseController, CheckOutHandler));
1471 pInfoBar->addButton(xBtn);
1479 IMPL_LINK_NOARG ( SfxBaseController, CheckOutHandler, Button*, void )
1481 if ( m_pData->m_pViewShell )
1482 m_pData->m_pViewShell->GetObjectShell()->CheckOut( );
1486 Reference< frame::XTitle > SfxBaseController::impl_getTitleHelper ()
1488 SolarMutexGuard aGuard;
1490 if ( ! m_pData->m_xTitleHelper.is ())
1492 Reference< frame::XModel > xModel = getModel ();
1493 Reference< frame::XUntitledNumbers > xUntitledProvider(xModel , uno::UNO_QUERY );
1494 Reference< frame::XController > xThis (static_cast< frame::XController* >(this), uno::UNO_QUERY_THROW);
1496 ::framework::TitleHelper* pHelper = new ::framework::TitleHelper(::comphelper::getProcessComponentContext());
1497 m_pData->m_xTitleHelper.set(static_cast< ::cppu::OWeakObject* >(pHelper), uno::UNO_QUERY_THROW);
1499 pHelper->setOwner (xThis );
1500 pHelper->connectWithUntitledNumbers (xUntitledProvider);
1503 return m_pData->m_xTitleHelper;
1507 // frame::XTitle
1508 OUString SAL_CALL SfxBaseController::getTitle()
1509 throw (RuntimeException, std::exception)
1511 return impl_getTitleHelper()->getTitle ();
1515 // frame::XTitle
1516 void SAL_CALL SfxBaseController::setTitle(const OUString& sTitle)
1517 throw (RuntimeException, std::exception)
1519 impl_getTitleHelper()->setTitle (sTitle);
1523 // frame::XTitleChangeBroadcaster
1524 void SAL_CALL SfxBaseController::addTitleChangeListener(const Reference< frame::XTitleChangeListener >& xListener)
1525 throw (RuntimeException, std::exception)
1527 Reference< frame::XTitleChangeBroadcaster > xBroadcaster(impl_getTitleHelper(), uno::UNO_QUERY);
1528 if (xBroadcaster.is ())
1529 xBroadcaster->addTitleChangeListener (xListener);
1533 // frame::XTitleChangeBroadcaster
1534 void SAL_CALL SfxBaseController::removeTitleChangeListener(const Reference< frame::XTitleChangeListener >& xListener)
1535 throw (RuntimeException, std::exception)
1537 Reference< frame::XTitleChangeBroadcaster > xBroadcaster(impl_getTitleHelper(), uno::UNO_QUERY);
1538 if (xBroadcaster.is ())
1539 xBroadcaster->removeTitleChangeListener (xListener);
1542 void SfxBaseController::initialize( const css::uno::Sequence< css::uno::Any >& /*aArguments*/ ) throw (css::uno::RuntimeException, std::exception)
1546 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */