1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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
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
},
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
)
156 while ( GroupIDCommandGroupMap
[i
].nGroupID
!= 0 )
158 s_aHashMap
.insert( GroupHashMap::value_type(
159 GroupIDCommandGroupMap
[i
].nGroupID
,
160 GroupIDCommandGroupMap
[i
].nCommandGroup
));
163 bGroupIDMapInitialized
= true;
166 GroupHashMap::const_iterator pIter
= s_aHashMap
.find( nGroupID
);
167 if ( pIter
!= s_aHashMap
.end() )
168 return pIter
->second
;
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
183 if ( m_nInReschedule
== 0 )
186 Application::Reschedule();
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
;
201 SfxStatusIndicator(SfxBaseController
* pController
, SfxWorkWindow
* pWork
)
202 : xOwner( pController
)
203 , pWorkWindow( pWork
)
209 Reference
< lang::XComponent
> xComponent(
210 (static_cast< ::cppu::OWeakObject
* >(pController
)), uno::UNO_QUERY
);
212 xComponent
->addEventListener(this);
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
;
233 if ( !xProgress
.is() )
234 xProgress
= pWorkWindow
->GetStatusIndicator();
236 if ( xProgress
.is() )
237 xProgress
->start( aText
, nRange
);
239 _nStartTime
= Get10ThSec();
244 void SAL_CALL
SfxStatusIndicator::end() throw(RuntimeException
, std::exception
)
246 SolarMutexGuard aGuard
;
249 if ( !xProgress
.is() )
250 xProgress
= pWorkWindow
->GetStatusIndicator();
252 if ( xProgress
.is() )
259 void SAL_CALL
SfxStatusIndicator::setText(const OUString
& aText
) throw(RuntimeException
, std::exception
)
261 SolarMutexGuard aGuard
;
264 if ( !xProgress
.is() )
265 xProgress
= pWorkWindow
->GetStatusIndicator();
267 if ( xProgress
.is() )
268 xProgress
->setText( aText
);
274 void SAL_CALL
SfxStatusIndicator::setValue( sal_Int32 nValue
) throw(RuntimeException
, std::exception
)
276 SolarMutexGuard aGuard
;
281 if ( !xProgress
.is() )
282 xProgress
= pWorkWindow
->GetStatusIndicator();
284 if ( xProgress
.is() )
285 xProgress
->setValue( nValue
);
287 bool bReschedule
= (( Get10ThSec() - _nStartTime
) > TIMEOUT_START_RESCHEDULE
);
293 void SAL_CALL
SfxStatusIndicator::reset() throw(RuntimeException
, std::exception
)
295 SolarMutexGuard aGuard
;
298 if ( !xProgress
.is() )
299 xProgress
= pWorkWindow
->GetStatusIndicator();
301 if ( xProgress
.is() )
308 void SAL_CALL
SfxStatusIndicator::disposing( const lang::EventObject
& /*Source*/ ) throw(RuntimeException
, std::exception
)
310 SolarMutexGuard aGuard
;
316 // declaration IMPL_SfxBaseController_ListenerHelper
319 class IMPL_SfxBaseController_ListenerHelper
: public ::cppu::WeakImplHelper
< frame::XFrameActionListener
>
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
;
329 SfxBaseController
* m_pController
;
331 } ; // class IMPL_SfxBaseController_ListenerContainer
333 class IMPL_SfxBaseController_CloseListenerHelper
: public ::cppu::WeakImplHelper
< util::XCloseListener
>
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
;
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();
369 bool bCanClose
= pShell
->PrepareClose( false );
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
);
377 pShell
->TakeOwnership_Impl();
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
;
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
;
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()
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!" );
516 if ( nViewNo
< rDocFac
.GetViewFactoryCount() )
517 sViewName
= rDocFac
.GetViewFactory( nViewNo
).GetAPIViewName();
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" );
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());
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
;
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
;
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
);
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!");
606 Reference
< util::XCloseBroadcaster
> xCloseable( xModel
, uno::UNO_QUERY
);
607 if ( xCloseable
.is() )
608 xCloseable
->addCloseListener( m_pData
->m_xCloseListener
);
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
)
626 if ( !m_pData
->m_pViewShell
)
628 m_pData
->m_bSuspendState
= true;
632 if ( !m_pData
->m_pViewShell
->PrepareClose() )
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();
649 ConnectSfxFrame_Impl( E_DISCONNECT
);
650 m_pData
->m_bSuspendState
= true;
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;
671 // SfxBaseController -> XController
674 uno::Any
SfxBaseController::getViewData() throw( RuntimeException
, std::exception
)
678 SolarMutexGuard aGuard
;
679 if ( m_pData
->m_pViewShell
)
681 m_pData
->m_pViewShell
->WriteUserData( sData
) ;
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
)
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
;
746 xFrame
= ( pChildWin
->GetFrame() );
748 xFrame
->setName( sTargetFrameName
);
750 Reference
< XDispatchProvider
> xProv( xFrame
, uno::UNO_QUERY
);
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
);
767 pSlot
= rSlotPool
.GetUnoSlot( aURL
.Path
);
768 if ( pSlot
&& ( !pAct
->GetFrame().IsInPlace() || !pSlot
->IsMode( SfxSlotMode::CONTAINER
) ) )
769 return pAct
->GetBindings().GetDispatch( pSlot
, aURL
, bMasterCommand
);
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();
787 pFrame
= SfxViewFrame::GetNext( *pFrame
) )
789 if ( pFrame
->GetFrame().GetFrameInterface() == xParentFrame
)
791 pParentFrame
= pFrame
;
798 SfxSlotPool
& rFrameSlotPool
= SfxSlotPool::GetSlotPool( pParentFrame
);
799 const SfxSlot
* pSlot2( nullptr );
800 if ( bMasterCommand
)
801 pSlot2
= rFrameSlotPool
.GetUnoSlot( aMasterCommand
);
803 pSlot2
= rFrameSlotPool
.GetUnoSlot( aURL
.Path
);
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
);
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 );
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();
844 pFrame
= SfxViewFrame::GetNext( *pFrame
) )
846 if ( pFrame
->GetFrame().GetFrameInterface() == xParentFrame
)
848 pParentFrame
= pFrame
;
855 SfxSlotPool
& rSlotPool2
= SfxSlotPool::GetSlotPool( pParentFrame
);
856 const SfxSlot
* pSlot2
= rSlotPool2
.GetUnoSlot( aURL
.Path
);
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
) );
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
);
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();
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(),
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(),
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());
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
&)
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;
1003 lang::EventObject aObject
;
1004 aObject
.Source
= *this ;
1006 SfxObjectShell
* pDoc
= pFrame
->GetObjectShell() ;
1007 SfxViewFrame
*pView
= SfxViewFrame::GetFirst(pDoc
);
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
)
1013 pView
= SfxViewFrame::GetNext( *pView
, pDoc
);
1016 SfxGetpApp()->NotifyEvent( SfxViewEventHint(SFX_EVENT_CLOSEVIEW
, GlobalEventConfig::GetEventName( GlobalEventId::CLOSEVIEW
), pDoc
, Reference
< frame::XController2
>( this ) ) );
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
);
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
);
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();
1162 if ( pSfxSlot
->GetMode() & nMode
)
1164 sal_Int16 nCommandGroup
= MapGroupIDToCommandGroup( pSfxSlot
->GetGroupId() );
1165 aGroupList
.push_back( nCommandGroup
);
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();
1196 sal_Int16 nCommandGroup
= MapGroupIDToCommandGroup( pSfxSlot
->GetGroupId() );
1197 if ( nCommandGroup
== nCmdGroup
)
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
);
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() )
1290 if ( SfxViewFrame::Current() == pViewFrame
)
1291 pViewFrame
->GetDispatcher()->Update_Impl( true );
1293 vcl::Window
* pFrameWin
= &pViewFrame
->GetWindow();
1294 if ( pFrameWin
!= &pViewFrame
->GetFrame().GetWindow() )
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();
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();
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
1331 if ( nPluginMode
== 3 )
1332 pViewFrame
->Resize( true );
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
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() )
1398 const SfxViewFactory
* pViewFactory
= rDocFactory
.GetViewFactoryByViewName( sViewId
);
1399 if ( pViewFactory
== nullptr )
1402 if ( pViewFactory
->GetOrdinal() == pViewFrame
->GetCurViewId() )
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
) );
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
;
1508 OUString SAL_CALL
SfxBaseController::getTitle()
1509 throw (RuntimeException
, std::exception
)
1511 return impl_getTitleHelper()->getTitle ();
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: */