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>
22 #include <com/sun/star/awt/XWindowPeer.hpp>
23 #include <com/sun/star/beans/XPropertySet.hpp>
24 #include <com/sun/star/util/XCloseable.hpp>
25 #include <com/sun/star/util/XCloseBroadcaster.hpp>
26 #include <com/sun/star/util/XCloseListener.hpp>
27 #include <com/sun/star/util/CloseVetoException.hpp>
28 #include <com/sun/star/document/XCmisDocument.hpp>
29 #include <com/sun/star/document/XViewDataSupplier.hpp>
30 #include <cppuhelper/implbase.hxx>
31 #include <com/sun/star/frame/FrameActionEvent.hpp>
32 #include <com/sun/star/frame/FrameAction.hpp>
33 #include <com/sun/star/frame/FrameSearchFlag.hpp>
34 #include <com/sun/star/frame/CommandGroup.hpp>
35 #include <com/sun/star/frame/XFrame.hpp>
36 #include <com/sun/star/frame/XBorderResizeListener.hpp>
37 #include <com/sun/star/frame/XUntitledNumbers.hpp>
38 #include <com/sun/star/lang/DisposedException.hpp>
39 #include <com/sun/star/lang/EventObject.hpp>
40 #include <com/sun/star/lang/XEventListener.hpp>
41 #include <com/sun/star/lang/XComponent.hpp>
42 #include <com/sun/star/container/XIndexAccess.hpp>
43 #include <comphelper/interfacecontainer2.hxx>
44 #include <comphelper/multicontainer2.hxx>
45 #include <sfx2/viewsh.hxx>
46 #include <sfx2/docfac.hxx>
47 #include <sfx2/viewfrm.hxx>
48 #include <sfx2/objsh.hxx>
49 #include <sfx2/app.hxx>
50 #include <sfx2/msgpool.hxx>
51 #include <sfx2/dispatch.hxx>
52 #include <sfx2/userinputinterception.hxx>
54 #include <unoctitm.hxx>
55 #include <sfx2/childwin.hxx>
56 #include <sfx2/sfxsids.hrc>
57 #include <sfx2/sfxresid.hxx>
58 #include <workwin.hxx>
59 #include <sfx2/infobar.hxx>
61 #include <osl/mutex.hxx>
62 #include <tools/diagnose_ex.h>
63 #include <comphelper/namedvaluecollection.hxx>
64 #include <comphelper/sequence.hxx>
65 #include <toolkit/helper/convert.hxx>
66 #include <framework/titlehelper.hxx>
67 #include <comphelper/processfactory.hxx>
68 #include <vcl/svapp.hxx>
69 #include <tools/svborder.hxx>
71 #include <sfx2/event.hxx>
72 #include <sfx2/viewfac.hxx>
73 #include <sfx2/strings.hrc>
74 #include <sfxbasecontroller_internal.hxx>
76 #include <unordered_map>
78 #include <com/sun/star/ui/XSidebarProvider.hpp>
79 #include <sidebar/UnoSidebar.hxx>
81 #define TIMEOUT_START_RESCHEDULE 10L /* 10th s */
83 using namespace ::com::sun::star
;
84 using ::com::sun::star::uno::Reference
;
85 using ::com::sun::star::uno::RuntimeException
;
86 using ::com::sun::star::uno::UNO_QUERY_THROW
;
87 using ::com::sun::star::lang::DisposedException
;
88 using ::com::sun::star::awt::XWindow
;
89 using ::com::sun::star::frame::XController
;
90 using ::com::sun::star::frame::XDispatchProvider
;
91 using ::com::sun::star::document::XViewDataSupplier
;
92 using ::com::sun::star::container::XIndexAccess
;
93 using ::com::sun::star::beans::PropertyValue
;
94 using ::com::sun::star::beans::StringPair
;
95 using ::com::sun::star::uno::Sequence
;
96 using ::com::sun::star::uno::UNO_QUERY
;
97 using ::com::sun::star::uno::Exception
;
98 using ::com::sun::star::frame::XFrame
;
99 using ::com::sun::star::frame::XFrameActionListener
;
100 using ::com::sun::star::util::XCloseListener
;
101 using ::com::sun::star::task::XStatusIndicator
;
102 using ::com::sun::star::frame::XTitle
;
103 using ::com::sun::star::ui::XSidebarProvider
;
106 typedef std::unordered_map
< SfxGroupId
, sal_Int16
> GroupHashMap
;
108 sal_Int16
MapGroupIDToCommandGroup( SfxGroupId nGroupID
)
110 static GroupHashMap s_aHashMap
112 { SfxGroupId::Intern
, frame::CommandGroup::INTERNAL
},
113 { SfxGroupId::Application
, frame::CommandGroup::APPLICATION
},
114 { SfxGroupId::Document
, frame::CommandGroup::DOCUMENT
},
115 { SfxGroupId::View
, frame::CommandGroup::VIEW
},
116 { SfxGroupId::Edit
, frame::CommandGroup::EDIT
},
117 { SfxGroupId::Macro
, frame::CommandGroup::MACRO
},
118 { SfxGroupId::Options
, frame::CommandGroup::OPTIONS
},
119 { SfxGroupId::Math
, frame::CommandGroup::MATH
},
120 { SfxGroupId::Navigator
, frame::CommandGroup::NAVIGATOR
},
121 { SfxGroupId::Insert
, frame::CommandGroup::INSERT
},
122 { SfxGroupId::Format
, frame::CommandGroup::FORMAT
},
123 { SfxGroupId::Template
, frame::CommandGroup::TEMPLATE
},
124 { SfxGroupId::Text
, frame::CommandGroup::TEXT
},
125 { SfxGroupId::Frame
, frame::CommandGroup::FRAME
},
126 { SfxGroupId::Graphic
, frame::CommandGroup::GRAPHIC
},
127 { SfxGroupId::Table
, frame::CommandGroup::TABLE
},
128 { SfxGroupId::Enumeration
, frame::CommandGroup::ENUMERATION
},
129 { SfxGroupId::Data
, frame::CommandGroup::DATA
},
130 { SfxGroupId::Special
, frame::CommandGroup::SPECIAL
},
131 { SfxGroupId::Image
, frame::CommandGroup::IMAGE
},
132 { SfxGroupId::Chart
, frame::CommandGroup::CHART
},
133 { SfxGroupId::Explorer
, frame::CommandGroup::EXPLORER
},
134 { SfxGroupId::Connector
, frame::CommandGroup::CONNECTOR
},
135 { SfxGroupId::Modify
, frame::CommandGroup::MODIFY
},
136 { SfxGroupId::Drawing
, frame::CommandGroup::DRAWING
},
137 { SfxGroupId::Controls
, frame::CommandGroup::CONTROLS
},
141 GroupHashMap::const_iterator pIter
= s_aHashMap
.find( nGroupID
);
142 if ( pIter
!= s_aHashMap
.end() )
143 return pIter
->second
;
145 return frame::CommandGroup::INTERNAL
;
148 sal_uInt32
Get10ThSec()
150 sal_uInt32 n10Ticks
= 10 * static_cast<sal_uInt32
>(clock());
151 return n10Ticks
/ CLOCKS_PER_SEC
;
154 static sal_Int32 m_nInReschedule
= 0; /// static counter for rescheduling
156 static void reschedule()
158 if ( m_nInReschedule
== 0 )
161 Application::Reschedule();
168 class SfxStatusIndicator
: public ::cppu::WeakImplHelper
< task::XStatusIndicator
, lang::XEventListener
>
170 Reference
< XController
> xOwner
;
171 Reference
< task::XStatusIndicator
> xProgress
;
172 SfxWorkWindow
* pWorkWindow
;
173 tools::Long _nStartTime
;
175 SfxStatusIndicator(SfxBaseController
* pController
, SfxWorkWindow
* pWork
)
176 : xOwner( pController
)
177 , pWorkWindow( pWork
)
180 osl_atomic_increment(&m_refCount
);
181 Reference
< lang::XComponent
> xComponent
= pController
;
183 xComponent
->addEventListener(this);
184 osl_atomic_decrement(&m_refCount
);
187 virtual void SAL_CALL
start(const OUString
& aText
, sal_Int32 nRange
) override
;
188 virtual void SAL_CALL
end() override
;
189 virtual void SAL_CALL
setText(const OUString
& aText
) override
;
190 virtual void SAL_CALL
setValue(sal_Int32 nValue
) override
;
191 virtual void SAL_CALL
reset() override
;
193 virtual void SAL_CALL
disposing( const lang::EventObject
& Source
) override
;
198 void SAL_CALL
SfxStatusIndicator::start(const OUString
& aText
, sal_Int32 nRange
)
200 SolarMutexGuard aGuard
;
203 if ( !xProgress
.is() )
204 xProgress
= pWorkWindow
->GetStatusIndicator();
206 if ( xProgress
.is() )
207 xProgress
->start( aText
, nRange
);
209 _nStartTime
= Get10ThSec();
214 void SAL_CALL
SfxStatusIndicator::end()
216 SolarMutexGuard aGuard
;
219 if ( !xProgress
.is() )
220 xProgress
= pWorkWindow
->GetStatusIndicator();
222 if ( xProgress
.is() )
229 void SAL_CALL
SfxStatusIndicator::setText(const OUString
& aText
)
231 SolarMutexGuard aGuard
;
234 if ( !xProgress
.is() )
235 xProgress
= pWorkWindow
->GetStatusIndicator();
237 if ( xProgress
.is() )
238 xProgress
->setText( aText
);
244 void SAL_CALL
SfxStatusIndicator::setValue( sal_Int32 nValue
)
246 SolarMutexGuard aGuard
;
249 if ( !xProgress
.is() )
250 xProgress
= pWorkWindow
->GetStatusIndicator();
252 if ( xProgress
.is() )
253 xProgress
->setValue( nValue
);
255 bool bReschedule
= (( Get10ThSec() - _nStartTime
) > TIMEOUT_START_RESCHEDULE
);
261 void SAL_CALL
SfxStatusIndicator::reset()
263 SolarMutexGuard aGuard
;
266 if ( !xProgress
.is() )
267 xProgress
= pWorkWindow
->GetStatusIndicator();
269 if ( xProgress
.is() )
276 void SAL_CALL
SfxStatusIndicator::disposing( const lang::EventObject
& /*Source*/ )
278 SolarMutexGuard aGuard
;
284 // declaration IMPL_SfxBaseController_ListenerHelper
288 class IMPL_SfxBaseController_ListenerHelper
: public ::cppu::WeakImplHelper
< frame::XFrameActionListener
>
291 explicit IMPL_SfxBaseController_ListenerHelper( SfxBaseController
* pController
) ;
293 virtual void SAL_CALL
frameAction( const frame::FrameActionEvent
& aEvent
) override
;
294 virtual void SAL_CALL
disposing( const lang::EventObject
& aEvent
) override
;
298 SfxBaseController
* m_pController
;
300 } ; // class IMPL_SfxBaseController_ListenerContainer
302 class IMPL_SfxBaseController_CloseListenerHelper
: public ::cppu::WeakImplHelper
< util::XCloseListener
>
305 explicit IMPL_SfxBaseController_CloseListenerHelper( SfxBaseController
* pController
) ;
307 virtual void SAL_CALL
queryClosing( const lang::EventObject
& aEvent
, sal_Bool bDeliverOwnership
) override
;
308 virtual void SAL_CALL
notifyClosing( const lang::EventObject
& aEvent
) override
;
309 virtual void SAL_CALL
disposing( const lang::EventObject
& aEvent
) override
;
313 SfxBaseController
* m_pController
;
315 } ; // class IMPL_SfxBaseController_ListenerContainer
319 IMPL_SfxBaseController_CloseListenerHelper::IMPL_SfxBaseController_CloseListenerHelper( SfxBaseController
* pController
)
320 : m_pController ( pController
)
324 void SAL_CALL
IMPL_SfxBaseController_CloseListenerHelper::disposing( const lang::EventObject
& /*aEvent*/ )
328 void SAL_CALL
IMPL_SfxBaseController_CloseListenerHelper::queryClosing( const lang::EventObject
& /*aEvent*/, sal_Bool
/*bDeliverOwnership*/ )
330 SolarMutexGuard aGuard
;
331 SfxViewShell
* pShell
= m_pController
->GetViewShell_Impl();
334 bool bCanClose
= pShell
->PrepareClose( false );
337 throw util::CloseVetoException("Controller disagree ...",static_cast< ::cppu::OWeakObject
*>(this));
342 void SAL_CALL
IMPL_SfxBaseController_CloseListenerHelper::notifyClosing( const lang::EventObject
& /*aEvent*/ )
347 // declaration IMPL_SfxBaseController_DataContainer
350 struct IMPL_SfxBaseController_DataContainer
352 Reference
< XFrame
> m_xFrame
;
353 Reference
< XFrameActionListener
> m_xListener
;
354 Reference
< XCloseListener
> m_xCloseListener
;
355 ::sfx2::UserInputInterception m_aUserInputInterception
;
356 ::comphelper::OMultiTypeInterfaceContainerHelper2 m_aListenerContainer
;
357 ::comphelper::OInterfaceContainerHelper2 m_aInterceptorContainer
;
358 Reference
< XStatusIndicator
> m_xIndicator
;
359 SfxViewShell
* m_pViewShell
;
360 SfxBaseController
* m_pController
;
362 bool m_bSuspendState
;
363 Reference
< XTitle
> m_xTitleHelper
;
364 Sequence
< PropertyValue
> m_aCreationArgs
;
366 IMPL_SfxBaseController_DataContainer( ::osl::Mutex
& aMutex
,
367 SfxViewShell
* pViewShell
,
368 SfxBaseController
* pController
)
369 : m_xListener ( new IMPL_SfxBaseController_ListenerHelper( pController
) )
370 , m_xCloseListener ( new IMPL_SfxBaseController_CloseListenerHelper( pController
) )
371 , m_aUserInputInterception ( *pController
, aMutex
)
372 , m_aListenerContainer ( aMutex
)
373 , m_aInterceptorContainer ( aMutex
)
374 , m_pViewShell ( pViewShell
)
375 , m_pController ( pController
)
376 , m_bDisposing ( false )
377 , m_bSuspendState ( false )
381 } ; // struct IMPL_SfxBaseController_DataContainer
384 // IMPL_SfxBaseController_ListenerHelper constructor
387 IMPL_SfxBaseController_ListenerHelper::IMPL_SfxBaseController_ListenerHelper( SfxBaseController
* pController
)
388 : m_pController ( pController
)
392 void SAL_CALL
IMPL_SfxBaseController_ListenerHelper::frameAction( const frame::FrameActionEvent
& aEvent
)
394 SolarMutexGuard aGuard
;
396 ( m_pController
!= nullptr ) &&
397 ( aEvent
.Frame
== m_pController
->getFrame() ) &&
398 ( m_pController
->GetViewShell_Impl() && m_pController
->GetViewShell_Impl()->GetWindow() != nullptr )
401 if ( aEvent
.Action
== frame::FrameAction_FRAME_UI_ACTIVATED
)
403 if ( !m_pController
->GetViewShell_Impl()->GetUIActiveIPClient_Impl() )
404 m_pController
->GetViewShell_Impl()->GetViewFrame()->MakeActive_Impl( false );
406 else if ( aEvent
.Action
== frame::FrameAction_CONTEXT_CHANGED
)
408 m_pController
->GetViewShell_Impl()->GetViewFrame()->GetBindings().ContextChanged_Impl();
414 // IMPL_SfxBaseController_ListenerHelper -> XEventListener
417 void SAL_CALL
IMPL_SfxBaseController_ListenerHelper::disposing( const lang::EventObject
& /*aEvent*/ )
419 SolarMutexGuard aGuard
;
420 if ( m_pController
&& m_pController
->getFrame().is() )
421 m_pController
->getFrame()->removeFrameActionListener( this ) ;
424 SfxBaseController::SfxBaseController( SfxViewShell
* pViewShell
)
425 : m_pData ( new IMPL_SfxBaseController_DataContainer( m_aMutex
, pViewShell
, this ))
427 m_pData
->m_pViewShell
->SetController( this );
431 // SfxBaseController -> destructor
434 SfxBaseController::~SfxBaseController()
439 // SfxBaseController -> XController2
442 Reference
< XWindow
> SAL_CALL
SfxBaseController::getComponentWindow()
444 SolarMutexGuard aGuard
;
445 if ( !m_pData
->m_pViewShell
)
446 throw DisposedException();
448 return Reference
< XWindow
>( GetViewFrame_Impl().GetFrame().GetWindow().GetComponentInterface(), UNO_QUERY_THROW
);
451 OUString SAL_CALL
SfxBaseController::getViewControllerName()
453 SolarMutexGuard aGuard
;
454 if ( !m_pData
->m_pViewShell
|| !m_pData
->m_pViewShell
->GetObjectShell() )
455 throw DisposedException();
457 const SfxObjectFactory
& rDocFac( m_pData
->m_pViewShell
->GetObjectShell()->GetFactory() );
458 sal_uInt16 nViewNo
= rDocFac
.GetViewNo_Impl( GetViewFrame_Impl().GetCurViewId(), rDocFac
.GetViewFactoryCount() );
459 OSL_ENSURE( nViewNo
< rDocFac
.GetViewFactoryCount(), "SfxBaseController::getViewControllerName: view ID not found in view factories!" );
462 if ( nViewNo
< rDocFac
.GetViewFactoryCount() )
463 sViewName
= rDocFac
.GetViewFactory( nViewNo
).GetAPIViewName();
468 Sequence
< PropertyValue
> SAL_CALL
SfxBaseController::getCreationArguments()
470 SolarMutexGuard aGuard
;
471 if ( !m_pData
->m_pViewShell
|| !m_pData
->m_pViewShell
->GetObjectShell() )
472 throw DisposedException();
474 return m_pData
->m_aCreationArgs
;
477 void SfxBaseController::SetCreationArguments_Impl( const Sequence
< PropertyValue
>& i_rCreationArgs
)
479 OSL_ENSURE( !m_pData
->m_aCreationArgs
.hasElements(), "SfxBaseController::SetCreationArguments_Impl: not intended to be called twice!" );
480 m_pData
->m_aCreationArgs
= i_rCreationArgs
;
483 SfxViewFrame
& SfxBaseController::GetViewFrame_Impl() const
485 ENSURE_OR_THROW( m_pData
->m_pViewShell
, "not to be called without a view shell" );
486 SfxViewFrame
* pActFrame
= m_pData
->m_pViewShell
->GetFrame();
487 ENSURE_OR_THROW( pActFrame
, "a view shell without a view frame is pretty pathological" );
492 Reference
<XSidebarProvider
> SAL_CALL
SfxBaseController::getSidebar()
494 SfxViewFrame
& rViewFrame
= GetViewFrame_Impl();
495 SfxFrame
& rFrame
= rViewFrame
.GetFrame();
497 Reference
<XSidebarProvider
> rSidebar
= new SfxUnoSidebar(rFrame
.GetFrameInterface());
502 // SfxBaseController -> XController2 -> XController
505 void SAL_CALL
SfxBaseController::attachFrame( const Reference
< frame::XFrame
>& xFrame
)
507 Reference
< frame::XFrame
> xTemp( getFrame() ) ;
509 SolarMutexGuard aGuard
;
512 xTemp
->removeFrameActionListener( m_pData
->m_xListener
) ;
513 Reference
< util::XCloseBroadcaster
> xCloseable( xTemp
, uno::UNO_QUERY
);
514 if ( xCloseable
.is() )
515 xCloseable
->removeCloseListener( m_pData
->m_xCloseListener
);
518 m_pData
->m_xFrame
= xFrame
;
523 xFrame
->addFrameActionListener( m_pData
->m_xListener
) ;
524 Reference
< util::XCloseBroadcaster
> xCloseable( xFrame
, uno::UNO_QUERY
);
525 if ( xCloseable
.is() )
526 xCloseable
->addCloseListener( m_pData
->m_xCloseListener
);
528 if ( m_pData
->m_pViewShell
)
530 ConnectSfxFrame_Impl( E_CONNECT
);
533 // attaching the frame to the controller is the last step in the creation of a new view, so notify this
534 SfxViewEventHint
aHint( SfxEventHintId::ViewCreated
, GlobalEventConfig::GetEventName( GlobalEventId::VIEWCREATED
), m_pData
->m_pViewShell
->GetObjectShell(), Reference
< frame::XController2
>( this ) );
535 SfxGetpApp()->NotifyEvent( aHint
);
540 // SfxBaseController -> XController
543 sal_Bool SAL_CALL
SfxBaseController::attachModel( const Reference
< frame::XModel
>& xModel
)
545 if ( m_pData
->m_pViewShell
&& xModel
.is() && xModel
!= m_pData
->m_pViewShell
->GetObjectShell()->GetModel() )
547 // don't allow to reattach a model!
548 OSL_FAIL("Can't reattach model!");
552 Reference
< util::XCloseBroadcaster
> xCloseable( xModel
, uno::UNO_QUERY
);
553 if ( xCloseable
.is() )
554 xCloseable
->addCloseListener( m_pData
->m_xCloseListener
);
559 // SfxBaseController -> XController
562 sal_Bool SAL_CALL
SfxBaseController::suspend( sal_Bool bSuspend
)
564 SolarMutexGuard aGuard
;
566 // ignore duplicate calls, which doesn't change anything real
567 if (bool(bSuspend
) == m_pData
->m_bSuspendState
)
572 if ( !m_pData
->m_pViewShell
)
574 m_pData
->m_bSuspendState
= true;
578 if ( !m_pData
->m_pViewShell
->PrepareClose() )
581 if ( getFrame().is() )
582 getFrame()->removeFrameActionListener( m_pData
->m_xListener
) ;
583 SfxViewFrame
* pActFrame
= m_pData
->m_pViewShell
->GetFrame() ;
585 // More Views on the same document?
586 SfxObjectShell
* pDocShell
= m_pData
->m_pViewShell
->GetObjectShell() ;
587 bool bOther
= false ;
589 for ( const SfxViewFrame
* pFrame
= SfxViewFrame::GetFirst( pDocShell
); !bOther
&& pFrame
; pFrame
= SfxViewFrame::GetNext( *pFrame
, pDocShell
) )
590 bOther
= (pFrame
!= pActFrame
);
592 bool bRet
= bOther
|| pDocShell
->PrepareClose();
595 ConnectSfxFrame_Impl( E_DISCONNECT
);
596 m_pData
->m_bSuspendState
= true;
603 if ( getFrame().is() )
604 getFrame()->addFrameActionListener( m_pData
->m_xListener
) ;
606 if ( m_pData
->m_pViewShell
)
608 ConnectSfxFrame_Impl( E_RECONNECT
);
611 m_pData
->m_bSuspendState
= false;
617 // SfxBaseController -> XController
620 uno::Any
SfxBaseController::getViewData()
623 SolarMutexGuard aGuard
;
624 if ( m_pData
->m_pViewShell
)
627 m_pData
->m_pViewShell
->WriteUserData( sData
) ;
635 // SfxBaseController -> XController
638 void SAL_CALL
SfxBaseController::restoreViewData( const uno::Any
& aValue
)
640 SolarMutexGuard aGuard
;
641 if ( m_pData
->m_pViewShell
)
645 m_pData
->m_pViewShell
->ReadUserData( sData
) ;
650 // SfxBaseController -> XController
653 Reference
< frame::XFrame
> SAL_CALL
SfxBaseController::getFrame()
655 SolarMutexGuard aGuard
;
656 return m_pData
->m_xFrame
;
660 // SfxBaseController -> XController
663 Reference
< frame::XModel
> SAL_CALL
SfxBaseController::getModel()
665 SolarMutexGuard aGuard
;
666 return m_pData
->m_pViewShell
? m_pData
->m_pViewShell
->GetObjectShell()->GetModel() : Reference
< frame::XModel
> () ;
670 // SfxBaseController -> XDispatchProvider
673 Reference
< frame::XDispatch
> SAL_CALL
SfxBaseController::queryDispatch( const util::URL
& aURL
,
674 const OUString
& sTargetFrameName
,
675 sal_Int32 eSearchFlags
)
677 SolarMutexGuard aGuard
;
678 Reference
< frame::XDispatch
> xDisp
;
679 if ( m_pData
->m_pViewShell
)
681 SfxViewFrame
* pAct
= m_pData
->m_pViewShell
->GetViewFrame() ;
682 if ( !m_pData
->m_bDisposing
)
684 if ( sTargetFrameName
== "_beamer" )
686 SfxViewFrame
*pFrame
= m_pData
->m_pViewShell
->GetViewFrame();
687 if ( eSearchFlags
& frame::FrameSearchFlag::CREATE
)
688 pFrame
->SetChildWindow( SID_BROWSER
, true );
689 SfxChildWindow
* pChildWin
= pFrame
->GetChildWindow( SID_BROWSER
);
690 Reference
< frame::XFrame
> xFrame
;
692 xFrame
= pChildWin
->GetFrame();
694 xFrame
->setName( sTargetFrameName
);
696 Reference
< XDispatchProvider
> xProv( xFrame
, uno::UNO_QUERY
);
698 return xProv
->queryDispatch( aURL
, sTargetFrameName
, frame::FrameSearchFlag::SELF
);
701 if ( aURL
.Protocol
== ".uno:" )
703 OUString aMasterCommand
= SfxOfficeDispatch::GetMasterUnoCommand( aURL
);
704 bool bMasterCommand( !aMasterCommand
.isEmpty() );
706 pAct
= m_pData
->m_pViewShell
->GetViewFrame() ;
707 SfxSlotPool
& rSlotPool
= SfxSlotPool::GetSlotPool( pAct
);
709 const SfxSlot
* pSlot( nullptr );
710 if ( bMasterCommand
)
711 pSlot
= rSlotPool
.GetUnoSlot( aMasterCommand
);
713 pSlot
= rSlotPool
.GetUnoSlot( aURL
.Path
);
714 if ( pSlot
&& ( !pAct
->GetFrame().IsInPlace() || !pSlot
->IsMode( SfxSlotMode::CONTAINER
) ) )
715 return pAct
->GetBindings().GetDispatch( pSlot
, aURL
, bMasterCommand
);
718 // try to find parent SfxViewFrame
719 Reference
< frame::XFrame
> xParentFrame
;
720 Reference
< frame::XFrame
> xOwnFrame
= pAct
->GetFrame().GetFrameInterface();
721 if ( xOwnFrame
.is() )
722 xParentFrame
= xOwnFrame
->getCreator();
724 if ( xParentFrame
.is() )
726 // TODO/LATER: in future probably SfxViewFrame hierarchy should be the same as XFrame hierarchy
727 // SfxViewFrame* pParentFrame = pAct->GetParentViewFrame();
729 // search the related SfxViewFrame
730 SfxViewFrame
* pParentFrame
= nullptr;
731 for ( SfxViewFrame
* pFrame
= SfxViewFrame::GetFirst();
733 pFrame
= SfxViewFrame::GetNext( *pFrame
) )
735 if ( pFrame
->GetFrame().GetFrameInterface() == xParentFrame
)
737 pParentFrame
= pFrame
;
744 SfxSlotPool
& rFrameSlotPool
= SfxSlotPool::GetSlotPool( pParentFrame
);
745 const SfxSlot
* pSlot2( nullptr );
746 if ( bMasterCommand
)
747 pSlot2
= rFrameSlotPool
.GetUnoSlot( aMasterCommand
);
749 pSlot2
= rFrameSlotPool
.GetUnoSlot( aURL
.Path
);
752 return pParentFrame
->GetBindings().GetDispatch( pSlot2
, aURL
, bMasterCommand
);
757 else if ( aURL
.Protocol
== "slot:" )
759 sal_uInt16 nId
= static_cast<sal_uInt16
>(aURL
.Path
.toInt32());
761 pAct
= m_pData
->m_pViewShell
->GetViewFrame() ;
762 if (nId
>= SID_VERB_START
&& nId
<= SID_VERB_END
)
764 const SfxSlot
* pSlot
= m_pData
->m_pViewShell
->GetVerbSlot_Impl(nId
);
766 return pAct
->GetBindings().GetDispatch( pSlot
, aURL
, false );
769 SfxSlotPool
& rSlotPool
= SfxSlotPool::GetSlotPool( pAct
);
770 const SfxSlot
* pSlot
= rSlotPool
.GetSlot( nId
);
771 if ( pSlot
&& ( !pAct
->GetFrame().IsInPlace() || !pSlot
->IsMode( SfxSlotMode::CONTAINER
) ) )
772 return pAct
->GetBindings().GetDispatch( pSlot
, aURL
, false );
775 // try to find parent SfxViewFrame
776 Reference
< frame::XFrame
> xParentFrame
;
777 Reference
< frame::XFrame
> xOwnFrame
= pAct
->GetFrame().GetFrameInterface();
778 if ( xOwnFrame
.is() )
779 xParentFrame
= xOwnFrame
->getCreator();
781 if ( xParentFrame
.is() )
783 // TODO/LATER: in future probably SfxViewFrame hierarchy should be the same as XFrame hierarchy
784 // SfxViewFrame* pParentFrame = pAct->GetParentViewFrame();
786 // search the related SfxViewFrame
787 SfxViewFrame
* pParentFrame
= nullptr;
788 for ( SfxViewFrame
* pFrame
= SfxViewFrame::GetFirst();
790 pFrame
= SfxViewFrame::GetNext( *pFrame
) )
792 if ( pFrame
->GetFrame().GetFrameInterface() == xParentFrame
)
794 pParentFrame
= pFrame
;
801 SfxSlotPool
& rSlotPool2
= SfxSlotPool::GetSlotPool( pParentFrame
);
802 const SfxSlot
* pSlot2
= rSlotPool2
.GetUnoSlot( aURL
.Path
);
804 return pParentFrame
->GetBindings().GetDispatch( pSlot2
, aURL
, false );
809 else if( sTargetFrameName
== "_self" || sTargetFrameName
.isEmpty() )
811 // check for already loaded URL ... but with additional jumpmark!
812 Reference
< frame::XModel
> xModel
= getModel();
813 if( xModel
.is() && !aURL
.Mark
.isEmpty() )
815 SfxSlotPool
& rSlotPool
= SfxSlotPool::GetSlotPool( pAct
);
816 const SfxSlot
* pSlot
= rSlotPool
.GetSlot( SID_JUMPTOMARK
);
817 if( !aURL
.Main
.isEmpty() && aURL
.Main
== xModel
->getURL() && pSlot
)
818 return Reference
< frame::XDispatch
>( new SfxOfficeDispatch( pAct
->GetBindings(), pAct
->GetDispatcher(), pSlot
, aURL
) );
828 // SfxBaseController -> XDispatchProvider
831 uno::Sequence
< Reference
< frame::XDispatch
> > SAL_CALL
SfxBaseController::queryDispatches( const uno::Sequence
< frame::DispatchDescriptor
>& seqDescripts
)
833 // Create return list - which must have same size then the given descriptor
834 // It's not allowed to pack it!
835 sal_Int32 nCount
= seqDescripts
.getLength();
836 uno::Sequence
< Reference
< frame::XDispatch
> > lDispatcher( nCount
);
838 std::transform(seqDescripts
.begin(), seqDescripts
.end(), lDispatcher
.getArray(),
839 [this](const frame::DispatchDescriptor
& rDesc
) -> Reference
< frame::XDispatch
> {
840 return queryDispatch(rDesc
.FeatureURL
, rDesc
.FrameName
, rDesc
.SearchFlags
); });
846 // SfxBaseController -> XControllerBorder
849 frame::BorderWidths SAL_CALL
SfxBaseController::getBorder()
851 frame::BorderWidths aResult
;
853 SolarMutexGuard aGuard
;
854 if ( m_pData
->m_pViewShell
)
856 SvBorder aBorder
= m_pData
->m_pViewShell
->GetBorderPixel();
857 aResult
.Left
= aBorder
.Left();
858 aResult
.Top
= aBorder
.Top();
859 aResult
.Right
= aBorder
.Right();
860 aResult
.Bottom
= aBorder
.Bottom();
866 void SAL_CALL
SfxBaseController::addBorderResizeListener( const Reference
< frame::XBorderResizeListener
>& xListener
)
868 m_pData
->m_aListenerContainer
.addInterface( cppu::UnoType
<frame::XBorderResizeListener
>::get(),
872 void SAL_CALL
SfxBaseController::removeBorderResizeListener( const Reference
< frame::XBorderResizeListener
>& xListener
)
874 m_pData
->m_aListenerContainer
.removeInterface( cppu::UnoType
<frame::XBorderResizeListener
>::get(),
878 awt::Rectangle SAL_CALL
SfxBaseController::queryBorderedArea( const awt::Rectangle
& aPreliminaryRectangle
)
880 SolarMutexGuard aGuard
;
881 if ( m_pData
->m_pViewShell
)
883 tools::Rectangle aTmpRect
= VCLRectangle( aPreliminaryRectangle
);
884 m_pData
->m_pViewShell
->QueryObjAreaPixel( aTmpRect
);
885 return AWTRectangle( aTmpRect
);
888 return aPreliminaryRectangle
;
891 void SfxBaseController::BorderWidthsChanged_Impl()
893 ::comphelper::OInterfaceContainerHelper2
* pContainer
= m_pData
->m_aListenerContainer
.getContainer(
894 cppu::UnoType
<frame::XBorderResizeListener
>::get());
898 frame::BorderWidths aBWidths
= getBorder();
899 Reference
< uno::XInterface
> xThis( static_cast< ::cppu::OWeakObject
* >(this), uno::UNO_QUERY
);
901 ::comphelper::OInterfaceIteratorHelper2
pIterator(*pContainer
);
902 while (pIterator
.hasMoreElements())
906 static_cast<frame::XBorderResizeListener
*>(pIterator
.next())->borderWidthsChanged( xThis
, aBWidths
);
908 catch (const RuntimeException
&)
916 // SfxBaseController -> XComponent
919 void SAL_CALL
SfxBaseController::dispose()
921 SolarMutexGuard aGuard
;
922 Reference
< XController
> xKeepAlive( this );
923 m_pData
->m_bDisposing
= true ;
925 lang::EventObject aEventObject
;
926 aEventObject
.Source
= *this ;
927 m_pData
->m_aListenerContainer
.disposeAndClear( aEventObject
) ;
929 if ( m_pData
->m_pController
&& m_pData
->m_pController
->getFrame().is() )
930 m_pData
->m_pController
->getFrame()->removeFrameActionListener( m_pData
->m_xListener
) ;
932 if ( !m_pData
->m_pViewShell
)
935 SfxViewFrame
* pFrame
= m_pData
->m_pViewShell
->GetViewFrame() ;
936 if ( pFrame
&& pFrame
->GetViewShell() == m_pData
->m_pViewShell
)
937 pFrame
->GetFrame().SetIsClosing_Impl();
938 m_pData
->m_pViewShell
->DisconnectAllClients();
943 lang::EventObject aObject
;
944 aObject
.Source
= *this ;
946 SfxObjectShell
* pDoc
= pFrame
->GetObjectShell() ;
947 SfxViewFrame
*pView
= SfxViewFrame::GetFirst(pDoc
);
950 // if there is another ViewFrame or currently the ViewShell in my ViewFrame is switched (PagePreview)
951 if ( pView
!= pFrame
|| pView
->GetViewShell() != m_pData
->m_pViewShell
)
953 pView
= SfxViewFrame::GetNext( *pView
, pDoc
);
956 SfxGetpApp()->NotifyEvent( SfxViewEventHint(SfxEventHintId::CloseView
, GlobalEventConfig::GetEventName( GlobalEventId::CLOSEVIEW
), pDoc
, Reference
< frame::XController2
>( this ) ) );
958 SfxGetpApp()->NotifyEvent( SfxEventHint(SfxEventHintId::CloseDoc
, GlobalEventConfig::GetEventName( GlobalEventId::CLOSEDOC
), pDoc
) );
960 Reference
< frame::XModel
> xModel
= pDoc
->GetModel();
961 Reference
< util::XCloseable
> xCloseable( xModel
, uno::UNO_QUERY
);
964 xModel
->disconnectController( this );
965 if ( xCloseable
.is() )
966 xCloseable
->removeCloseListener( m_pData
->m_xCloseListener
);
969 Reference
< frame::XFrame
> aXFrame
;
970 attachFrame( aXFrame
);
972 m_pData
->m_xListener
->disposing( aObject
);
973 SfxViewShell
*pShell
= m_pData
->m_pViewShell
;
974 m_pData
->m_pViewShell
= nullptr;
975 if ( pFrame
->GetViewShell() == pShell
)
977 // Enter registrations only allowed if we are the owner!
978 if ( pFrame
->GetFrame().OwnsBindings_Impl() )
979 pFrame
->GetBindings().ENTERREGISTRATIONS();
980 pFrame
->GetFrame().SetFrameInterface_Impl( aXFrame
);
981 pFrame
->GetFrame().DoClose_Impl();
986 // SfxBaseController -> XComponent
989 void SAL_CALL
SfxBaseController::addEventListener( const Reference
< lang::XEventListener
>& aListener
)
991 m_pData
->m_aListenerContainer
.addInterface( cppu::UnoType
<lang::XEventListener
>::get(), aListener
);
995 // SfxBaseController -> XComponent
998 void SAL_CALL
SfxBaseController::removeEventListener( const Reference
< lang::XEventListener
>& aListener
)
1000 m_pData
->m_aListenerContainer
.removeInterface( cppu::UnoType
<lang::XEventListener
>::get(), aListener
);
1003 void SfxBaseController::ReleaseShell_Impl()
1005 SolarMutexGuard aGuard
;
1006 if ( !m_pData
->m_pViewShell
)
1009 SfxObjectShell
* pDoc
= m_pData
->m_pViewShell
->GetObjectShell() ;
1010 Reference
< frame::XModel
> xModel
= pDoc
->GetModel();
1011 Reference
< util::XCloseable
> xCloseable( xModel
, uno::UNO_QUERY
);
1014 xModel
->disconnectController( this );
1015 if ( xCloseable
.is() )
1016 xCloseable
->removeCloseListener( m_pData
->m_xCloseListener
);
1018 m_pData
->m_pViewShell
= nullptr;
1020 Reference
< frame::XFrame
> aXFrame
;
1021 attachFrame( aXFrame
);
1024 void SfxBaseController::CopyLokViewCallbackFromFrameCreator()
1026 if (!m_pData
->m_pViewShell
)
1028 SfxLokCallbackInterface
* pCallback
= nullptr;
1029 if (m_pData
->m_xFrame
)
1030 if (auto xCreator
= m_pData
->m_xFrame
->getCreator())
1031 if (auto parentVS
= SfxViewShell::Get(xCreator
->getController()))
1032 pCallback
= parentVS
->getLibreOfficeKitViewCallback();
1033 m_pData
->m_pViewShell
->setLibreOfficeKitViewCallback(pCallback
);
1036 SfxViewShell
* SfxBaseController::GetViewShell_Impl() const
1038 return m_pData
->m_pViewShell
;
1041 Reference
< task::XStatusIndicator
> SAL_CALL
SfxBaseController::getStatusIndicator( )
1043 SolarMutexGuard aGuard
;
1044 if ( m_pData
->m_pViewShell
&& !m_pData
->m_xIndicator
.is() )
1045 m_pData
->m_xIndicator
= new SfxStatusIndicator( this, m_pData
->m_pViewShell
->GetViewFrame()->GetFrame().GetWorkWindow_Impl() );
1046 return m_pData
->m_xIndicator
;
1049 void SAL_CALL
SfxBaseController::registerContextMenuInterceptor( const Reference
< ui::XContextMenuInterceptor
>& xInterceptor
)
1052 m_pData
->m_aInterceptorContainer
.addInterface( xInterceptor
);
1054 SolarMutexGuard aGuard
;
1055 if ( m_pData
->m_pViewShell
)
1056 m_pData
->m_pViewShell
->AddContextMenuInterceptor_Impl( xInterceptor
);
1059 void SAL_CALL
SfxBaseController::releaseContextMenuInterceptor( const Reference
< ui::XContextMenuInterceptor
>& xInterceptor
)
1062 m_pData
->m_aInterceptorContainer
.removeInterface( xInterceptor
);
1064 SolarMutexGuard aGuard
;
1065 if ( m_pData
->m_pViewShell
)
1066 m_pData
->m_pViewShell
->RemoveContextMenuInterceptor_Impl( xInterceptor
);
1069 void SAL_CALL
SfxBaseController::addKeyHandler( const Reference
< awt::XKeyHandler
>& xHandler
)
1071 SolarMutexGuard aGuard
;
1072 m_pData
->m_aUserInputInterception
.addKeyHandler( xHandler
);
1075 void SAL_CALL
SfxBaseController::removeKeyHandler( const Reference
< awt::XKeyHandler
>& xHandler
)
1077 SolarMutexGuard aGuard
;
1078 m_pData
->m_aUserInputInterception
.removeKeyHandler( xHandler
);
1081 void SAL_CALL
SfxBaseController::addMouseClickHandler( const Reference
< awt::XMouseClickHandler
>& xHandler
)
1083 SolarMutexGuard aGuard
;
1084 m_pData
->m_aUserInputInterception
.addMouseClickHandler( xHandler
);
1087 void SAL_CALL
SfxBaseController::removeMouseClickHandler( const Reference
< awt::XMouseClickHandler
>& xHandler
)
1089 SolarMutexGuard aGuard
;
1090 m_pData
->m_aUserInputInterception
.removeMouseClickHandler( xHandler
);
1093 uno::Sequence
< sal_Int16
> SAL_CALL
SfxBaseController::getSupportedCommandGroups()
1095 SolarMutexGuard aGuard
;
1097 std::vector
< sal_Int16
> aGroupList
;
1098 SfxViewFrame
* pViewFrame
= m_pData
->m_pViewShell
? m_pData
->m_pViewShell
->GetFrame() : nullptr;
1099 SfxSlotPool
* pSlotPool
= pViewFrame
? &SfxSlotPool::GetSlotPool(pViewFrame
) : &SFX_SLOTPOOL();
1100 const SfxSlotMode
nMode( SfxSlotMode::TOOLBOXCONFIG
|SfxSlotMode::ACCELCONFIG
|SfxSlotMode::MENUCONFIG
);
1102 // Select Group ( Group 0 is internal )
1103 for ( sal_uInt16 i
=0; i
<pSlotPool
->GetGroupCount(); i
++ )
1105 pSlotPool
->SeekGroup( i
);
1106 const SfxSlot
* pSfxSlot
= pSlotPool
->FirstSlot();
1109 if ( pSfxSlot
->GetMode() & nMode
)
1111 sal_Int16 nCommandGroup
= MapGroupIDToCommandGroup( pSfxSlot
->GetGroupId() );
1112 aGroupList
.push_back( nCommandGroup
);
1115 pSfxSlot
= pSlotPool
->NextSlot();
1119 return comphelper::containerToSequence( aGroupList
);
1122 uno::Sequence
< frame::DispatchInformation
> SAL_CALL
SfxBaseController::getConfigurableDispatchInformation( sal_Int16 nCmdGroup
)
1124 std::vector
< frame::DispatchInformation
> aCmdVector
;
1126 SolarMutexGuard aGuard
;
1127 if ( m_pData
->m_pViewShell
)
1129 const SfxSlotMode
nMode( SfxSlotMode::TOOLBOXCONFIG
|SfxSlotMode::ACCELCONFIG
|SfxSlotMode::MENUCONFIG
);
1131 SfxViewFrame
* pViewFrame( m_pData
->m_pViewShell
->GetFrame() );
1132 SfxSlotPool
* pSlotPool
1133 = pViewFrame
? &SfxSlotPool::GetSlotPool(pViewFrame
) : &SFX_SLOTPOOL();
1134 for ( sal_uInt16 i
=0; i
<pSlotPool
->GetGroupCount(); i
++ )
1136 pSlotPool
->SeekGroup( i
);
1137 const SfxSlot
* pSfxSlot
= pSlotPool
->FirstSlot();
1140 sal_Int16 nCommandGroup
= MapGroupIDToCommandGroup( pSfxSlot
->GetGroupId() );
1141 if ( nCommandGroup
== nCmdGroup
)
1145 if ( pSfxSlot
->GetMode() & nMode
)
1147 frame::DispatchInformation aCmdInfo
;
1148 aCmdInfo
.Command
= ".uno:" + OUString::createFromAscii( pSfxSlot
->GetUnoName() );
1149 aCmdInfo
.GroupId
= nCommandGroup
;
1150 aCmdVector
.push_back( aCmdInfo
);
1152 pSfxSlot
= pSlotPool
->NextSlot();
1159 return comphelper::containerToSequence( aCmdVector
);
1162 bool SfxBaseController::HandleEvent_Impl( NotifyEvent
const & rEvent
)
1164 return m_pData
->m_aUserInputInterception
.handleNotifyEvent( rEvent
);
1167 bool SfxBaseController::HasKeyListeners_Impl() const
1169 return m_pData
->m_aUserInputInterception
.hasKeyHandlers();
1172 bool SfxBaseController::HasMouseClickListeners_Impl() const
1174 return m_pData
->m_aUserInputInterception
.hasMouseClickListeners();
1177 void SfxBaseController::ConnectSfxFrame_Impl( const ConnectSfxFrame i_eConnect
)
1179 ENSURE_OR_THROW( m_pData
->m_pViewShell
, "not to be called without a view shell" );
1180 SfxViewFrame
* pViewFrame
= m_pData
->m_pViewShell
->GetFrame();
1181 ENSURE_OR_THROW( pViewFrame
, "a view shell without a view frame is pretty pathological" );
1183 const bool bConnect
= ( i_eConnect
!= E_DISCONNECT
);
1185 // disable window and dispatcher
1186 pViewFrame
->Enable( bConnect
);
1187 pViewFrame
->GetDispatcher()->Lock( !bConnect
);
1191 if ( i_eConnect
== E_CONNECT
)
1193 if ( ( m_pData
->m_pViewShell
->GetObjectShell() != nullptr )
1194 && ( m_pData
->m_pViewShell
->GetObjectShell()->GetCreateMode() == SfxObjectCreateMode::EMBEDDED
)
1197 SfxViewFrame
* pViewFrm
= m_pData
->m_pViewShell
->GetViewFrame();
1198 if ( !pViewFrm
->GetFrame().IsInPlace() )
1200 // for outplace embedded objects, we want the layout manager to keep the content window
1201 // size constant, if possible
1204 Reference
< beans::XPropertySet
> xFrameProps( m_pData
->m_xFrame
, uno::UNO_QUERY_THROW
);
1205 Reference
< beans::XPropertySet
> xLayouterProps(
1206 xFrameProps
->getPropertyValue("LayoutManager"), uno::UNO_QUERY_THROW
);
1207 xLayouterProps
->setPropertyValue("PreserveContentSize", uno::makeAny( true ) );
1209 catch (const uno::Exception
&)
1211 DBG_UNHANDLED_EXCEPTION("sfx.view");
1217 // upon DISCONNECT, we did *not* pop the shells from the stack (this is done elsewhere), so upon
1218 // RECONNECT, we're not allowed to push them
1219 if ( i_eConnect
!= E_RECONNECT
)
1221 pViewFrame
->GetDispatcher()->Push( *m_pData
->m_pViewShell
);
1222 m_pData
->m_pViewShell
->PushSubShells_Impl();
1223 pViewFrame
->GetDispatcher()->Flush();
1226 vcl::Window
* pEditWin
= m_pData
->m_pViewShell
->GetWindow();
1230 if ( SfxViewFrame::Current() == pViewFrame
)
1231 pViewFrame
->GetDispatcher()->Update_Impl( true );
1233 vcl::Window
* pFrameWin
= &pViewFrame
->GetWindow();
1234 if ( pFrameWin
!= &pViewFrame
->GetFrame().GetWindow() )
1237 if ( i_eConnect
== E_CONNECT
)
1239 css::uno::Reference
<css::frame::XModel3
> xModel(getModel(), css::uno::UNO_QUERY_THROW
);
1240 ::comphelper::NamedValueCollection
aDocumentArgs( xModel
->getArgs2( { "PluginMode" } ) );
1242 const sal_Int16 nPluginMode
= aDocumentArgs
.getOrDefault( "PluginMode", sal_Int16( 0 ) );
1243 const bool bHasPluginMode
= ( nPluginMode
!= 0 );
1245 SfxFrame
& rFrame
= pViewFrame
->GetFrame();
1246 SfxObjectShell
& rDoc
= *m_pData
->m_pViewShell
->GetObjectShell();
1247 if ( !rFrame
.IsMarkedHidden_Impl() )
1249 if ( rDoc
.IsHelpDocument() || ( nPluginMode
== 2 ) )
1250 pViewFrame
->GetDispatcher()->HideUI();
1252 pViewFrame
->GetDispatcher()->HideUI( false );
1254 if ( rFrame
.IsInPlace() )
1255 pViewFrame
->LockAdjustPosSizePixel();
1257 if ( nPluginMode
== 3 )
1258 rFrame
.GetWorkWindow_Impl()->SetInternalDockingAllowed( false );
1260 if ( !rFrame
.IsInPlace() )
1261 pViewFrame
->GetDispatcher()->Update_Impl();
1263 rFrame
.GetWindow().Show();
1264 if ( !rFrame
.IsInPlace() || ( nPluginMode
== 3 ) )
1265 pViewFrame
->MakeActive_Impl( rFrame
.GetFrameInterface()->isActive() );
1267 if ( rFrame
.IsInPlace() )
1269 pViewFrame
->UnlockAdjustPosSizePixel();
1270 // force resize for OLE server to fix layout problems of writer and math
1272 if ( nPluginMode
== 3 )
1273 pViewFrame
->Resize( true );
1278 DBG_ASSERT( !rFrame
.IsInPlace() && !bHasPluginMode
, "Special modes not compatible with hidden mode!" );
1279 rFrame
.GetWindow().Show();
1282 // UpdateTitle now, hidden TopFrames have otherwise no Name!
1283 pViewFrame
->UpdateTitle();
1285 if ( !rFrame
.IsInPlace() )
1286 pViewFrame
->Resize( true );
1288 ::comphelper::NamedValueCollection
aViewArgs(getCreationArguments());
1290 // sometimes we want to avoid adding to the recent documents
1291 bool bAllowPickListEntry
= aViewArgs
.getOrDefault("PickListEntry", true);
1292 m_pData
->m_pViewShell
->GetObjectShell()->AvoidRecentDocs(!bAllowPickListEntry
);
1294 // if there's a JumpMark given, then, well, jump to it
1295 const OUString sJumpMark
= aViewArgs
.getOrDefault( "JumpMark", OUString() );
1296 const bool bHasJumpMark
= !sJumpMark
.isEmpty();
1297 OSL_ENSURE( ( !m_pData
->m_pViewShell
->GetObjectShell()->IsLoading() )
1298 || ( sJumpMark
.isEmpty() ),
1299 "SfxBaseController::ConnectSfxFrame_Impl: so this code wasn't dead?" );
1300 // Before CWS autorecovery, there was code which postponed jumping to the Mark to a later time
1301 // (SfxObjectShell::PositionView_Impl), but it seems this branch was never used, since this method
1302 // here is never called before the load process finished. At least not with a non-empty jump mark
1303 if ( !sJumpMark
.isEmpty() )
1304 m_pData
->m_pViewShell
->JumpToMark( sJumpMark
);
1306 // if no plugin mode and no jump mark was supplied, check whether the document itself can provide view data, and
1307 // if so, forward it to the view/shell.
1308 if ( !bHasPluginMode
&& !bHasJumpMark
)
1310 // Note that this might not be the ideal place here. Restoring view data should, IMO, be the
1311 // responsibility of the loader, not an implementation detail buried here deep within the controller's
1313 // What I think should be done to replace the below code:
1314 // - change SfxBaseController::restoreViewData to also accept a PropertyValue[] (it currently accepts
1315 // a string only), and forward it to its ViewShell's ReadUserDataSequence
1316 // - change the frame loader so that when a new document is loaded (as opposed to an existing
1317 // document being loaded into a new frame), the model's view data is examine the very same
1318 // way as below, and the proper view data is set via XController::restoreViewData
1319 // - extend SfxViewFrame::SwitchToViewShell_Impl. Currently, it cares for the case where a non-PrintPreview
1320 // view is exchanged, and sets the old view's data at the model. It should also care for the other
1321 // way, were the PrintPreview view is left: in this case, the new view should also be initialized
1322 // with the model's view data
1325 Reference
< XViewDataSupplier
> xViewDataSupplier( getModel(), UNO_QUERY_THROW
);
1326 Reference
< XIndexAccess
> xViewData( xViewDataSupplier
->getViewData() );
1328 // find the view data item whose ViewId matches the ID of the view we're just connecting to
1329 const SfxObjectFactory
& rDocFactory( rDoc
.GetFactory() );
1330 const sal_Int32 nCount
= xViewData
.is() ? xViewData
->getCount() : 0;
1331 sal_Int32 nViewDataIndex
= 0;
1332 for ( sal_Int32 i
=0; i
<nCount
; ++i
)
1334 const ::comphelper::NamedValueCollection
aViewData( xViewData
->getByIndex(i
) );
1335 OUString
sViewId( aViewData
.getOrDefault( "ViewId", OUString() ) );
1336 if ( sViewId
.isEmpty() )
1339 const SfxViewFactory
* pViewFactory
= rDocFactory
.GetViewFactoryByViewName( sViewId
);
1340 if ( pViewFactory
== nullptr )
1343 if ( pViewFactory
->GetOrdinal() == pViewFrame
->GetCurViewId() )
1349 if (nViewDataIndex
< nCount
|| !xViewData
.is())
1351 Sequence
< PropertyValue
> aViewData
;
1354 OSL_VERIFY(xViewData
->getByIndex(nViewDataIndex
) >>= aViewData
);
1356 if (aViewData
.hasElements() || !xViewData
.is())
1358 // Tolerate empty xViewData, ReadUserDataSequence() has side effects.
1359 m_pData
->m_pViewShell
->ReadUserDataSequence( aViewData
);
1363 catch (const Exception
&)
1365 DBG_UNHANDLED_EXCEPTION("sfx.view");
1371 // invalidate slot corresponding to the view shell
1372 const sal_uInt16 nViewNo
= m_pData
->m_pViewShell
->GetObjectShell()->GetFactory().GetViewNo_Impl( pViewFrame
->GetCurViewId(), USHRT_MAX
);
1373 DBG_ASSERT( nViewNo
!= USHRT_MAX
, "view shell id not found" );
1374 if ( nViewNo
!= USHRT_MAX
)
1375 pViewFrame
->GetBindings().Invalidate( nViewNo
+ SID_VIEWSHELL0
);
1378 void SfxBaseController::ShowInfoBars( )
1380 if ( !m_pData
->m_pViewShell
)
1383 // CMIS verifications
1384 Reference
< document::XCmisDocument
> xCmisDoc( m_pData
->m_pViewShell
->GetObjectShell()->GetModel(), uno::UNO_QUERY
);
1385 if ( !xCmisDoc
.is( ) || !xCmisDoc
->canCheckOut( ) )
1388 const uno::Sequence
< document::CmisProperty
> aCmisProperties
= xCmisDoc
->getCmisProperties( );
1390 if ( !(xCmisDoc
->isVersionable( ) && aCmisProperties
.hasElements( )) )
1393 // Loop over the CMIS Properties to find cmis:isVersionSeriesCheckedOut
1394 // and find if it is a Google Drive file.
1395 bool bIsGoogleFile
= false;
1396 bool bCheckedOut
= false;
1397 for ( const auto& rCmisProp
: aCmisProperties
)
1399 if ( rCmisProp
.Id
== "cmis:isVersionSeriesCheckedOut" ) {
1400 uno::Sequence
< sal_Bool
> bTmp
;
1401 rCmisProp
.Value
>>= bTmp
;
1402 bCheckedOut
= bTmp
[0];
1404 // if it is a Google Drive file, we don't need the checkout bar,
1405 // still need the checkout feature for the version dialog.
1406 if ( rCmisProp
.Name
== "title" )
1407 bIsGoogleFile
= true;
1410 if ( bCheckedOut
|| bIsGoogleFile
)
1413 // Get the Frame and show the InfoBar if not checked out
1414 SfxViewFrame
* pViewFrame
= m_pData
->m_pViewShell
->GetFrame();
1415 auto pInfoBar
= pViewFrame
->AppendInfoBar("checkout", "", SfxResId(STR_NONCHECKEDOUT_DOCUMENT
),
1416 InfobarType::WARNING
);
1419 weld::Button
&rBtn
= pInfoBar
->addButton();
1420 rBtn
.set_label(SfxResId(STR_CHECKOUT
));
1421 rBtn
.connect_clicked(LINK(this, SfxBaseController
, CheckOutHandler
));
1425 IMPL_LINK_NOARG ( SfxBaseController
, CheckOutHandler
, weld::Button
&, void )
1427 if ( m_pData
->m_pViewShell
)
1428 m_pData
->m_pViewShell
->GetObjectShell()->CheckOut( );
1432 Reference
< frame::XTitle
> SfxBaseController::impl_getTitleHelper ()
1434 SolarMutexGuard aGuard
;
1436 if ( ! m_pData
->m_xTitleHelper
.is ())
1438 Reference
< frame::XModel
> xModel
= getModel ();
1439 Reference
< frame::XUntitledNumbers
> xUntitledProvider(xModel
, uno::UNO_QUERY
);
1441 m_pData
->m_xTitleHelper
= new ::framework::TitleHelper(::comphelper::getProcessComponentContext(),
1442 Reference
< frame::XController
>(this), xUntitledProvider
);
1445 return m_pData
->m_xTitleHelper
;
1450 OUString SAL_CALL
SfxBaseController::getTitle()
1452 return impl_getTitleHelper()->getTitle ();
1457 void SAL_CALL
SfxBaseController::setTitle(const OUString
& sTitle
)
1459 impl_getTitleHelper()->setTitle (sTitle
);
1463 // frame::XTitleChangeBroadcaster
1464 void SAL_CALL
SfxBaseController::addTitleChangeListener(const Reference
< frame::XTitleChangeListener
>& xListener
)
1466 Reference
< frame::XTitleChangeBroadcaster
> xBroadcaster(impl_getTitleHelper(), uno::UNO_QUERY
);
1467 if (xBroadcaster
.is ())
1468 xBroadcaster
->addTitleChangeListener (xListener
);
1472 // frame::XTitleChangeBroadcaster
1473 void SAL_CALL
SfxBaseController::removeTitleChangeListener(const Reference
< frame::XTitleChangeListener
>& xListener
)
1475 Reference
< frame::XTitleChangeBroadcaster
> xBroadcaster(impl_getTitleHelper(), uno::UNO_QUERY
);
1476 if (xBroadcaster
.is ())
1477 xBroadcaster
->removeTitleChangeListener (xListener
);
1480 void SfxBaseController::initialize( const css::uno::Sequence
< css::uno::Any
>& /*aArguments*/ )
1484 void SAL_CALL
SfxBaseController::appendInfobar(const OUString
& sId
, const OUString
& sPrimaryMessage
,
1485 const OUString
& sSecondaryMessage
,
1486 sal_Int32 aInfobarType
,
1487 const Sequence
<StringPair
>& actionButtons
,
1488 sal_Bool bShowCloseButton
)
1490 SolarMutexGuard aGuard
;
1492 if (aInfobarType
< static_cast<sal_Int32
>(InfobarType::INFO
)
1493 || aInfobarType
> static_cast<sal_Int32
>(InfobarType::DANGER
))
1494 throw lang::IllegalArgumentException("Undefined InfobarType: "
1495 + OUString::number(aInfobarType
),
1496 static_cast<::cppu::OWeakObject
*>(this), 0);
1497 SfxViewFrame
* pViewFrame
= m_pData
->m_pViewShell
->GetFrame();
1498 if (pViewFrame
->HasInfoBarWithID(sId
))
1499 throw lang::IllegalArgumentException("Infobar with ID '" + sId
+ "' already existing.",
1500 static_cast<::cppu::OWeakObject
*>(this), 0);
1503 = pViewFrame
->AppendInfoBar(sId
, sPrimaryMessage
, sSecondaryMessage
,
1504 static_cast<InfobarType
>(aInfobarType
), bShowCloseButton
);
1506 throw uno::RuntimeException("Could not create Infobar");
1508 auto vActionButtons
= comphelper::sequenceToContainer
<std::vector
<StringPair
>>(actionButtons
);
1509 for (auto& actionButton
: vActionButtons
)
1511 if (actionButton
.First
.isEmpty() || actionButton
.Second
.isEmpty())
1513 weld::Button
& rBtn
= pInfoBar
->addButton(&actionButton
.Second
);
1514 rBtn
.set_label(actionButton
.First
);
1518 void SAL_CALL
SfxBaseController::updateInfobar(const OUString
& sId
, const OUString
& sPrimaryMessage
,
1519 const OUString
& sSecondaryMessage
,
1520 sal_Int32 aInfobarType
)
1522 SolarMutexGuard aGuard
;
1524 if (aInfobarType
< static_cast<sal_Int32
>(InfobarType::INFO
)
1525 || aInfobarType
> static_cast<sal_Int32
>(InfobarType::DANGER
))
1526 throw lang::IllegalArgumentException("Undefined InfobarType: "
1527 + OUString::number(aInfobarType
),
1528 static_cast<::cppu::OWeakObject
*>(this), 0);
1529 SfxViewFrame
* pViewFrame
= m_pData
->m_pViewShell
->GetFrame();
1530 if (!pViewFrame
->HasInfoBarWithID(sId
))
1531 throw css::container::NoSuchElementException("Infobar with ID '" + sId
+ "' not found.");
1533 pViewFrame
->UpdateInfoBar(sId
, sPrimaryMessage
, sSecondaryMessage
,
1534 static_cast<InfobarType
>(aInfobarType
));
1537 void SAL_CALL
SfxBaseController::removeInfobar(const OUString
& sId
)
1539 SolarMutexGuard aGuard
;
1541 SfxViewFrame
* pViewFrame
= m_pData
->m_pViewShell
->GetFrame();
1542 if (!pViewFrame
->HasInfoBarWithID(sId
))
1543 throw css::container::NoSuchElementException("Infobar with ID '" + sId
+ "' not found.");
1544 pViewFrame
->RemoveInfoBar(sId
);
1547 sal_Bool SAL_CALL
SfxBaseController::hasInfobar(const OUString
& sId
)
1549 SolarMutexGuard aGuard
;
1550 SfxViewFrame
* pViewFrame
= m_pData
->m_pViewShell
->GetFrame();
1551 return pViewFrame
->HasInfoBarWithID(sId
);
1554 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */