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 .
20 #include <dbaccess/controllerframe.hxx>
21 #include <dbaccess/IController.hxx>
23 #include <com/sun/star/awt/XTopWindow.hpp>
24 #include <com/sun/star/awt/XWindow2.hpp>
25 #include <com/sun/star/lang/DisposedException.hpp>
26 #include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
27 #include <com/sun/star/frame/XController2.hpp>
29 #include <cppuhelper/implbase.hxx>
30 #include <rtl/ref.hxx>
31 #include <sfx2/objsh.hxx>
32 #include <comphelper/diagnose_ex.hxx>
33 #include <toolkit/helper/vclunohelper.hxx>
34 #include <vcl/window.hxx>
39 using ::com::sun::star::uno::Reference
;
40 using ::com::sun::star::uno::XInterface
;
41 using ::com::sun::star::uno::UNO_QUERY
;
42 using ::com::sun::star::uno::UNO_QUERY_THROW
;
43 using ::com::sun::star::uno::UNO_SET_THROW
;
44 using ::com::sun::star::uno::Exception
;
45 using ::com::sun::star::uno::Any
;
46 using ::com::sun::star::frame::XFrame
;
47 using ::com::sun::star::frame::FrameAction
;
48 using ::com::sun::star::frame::FrameAction_FRAME_ACTIVATED
;
49 using ::com::sun::star::frame::FrameAction_FRAME_UI_ACTIVATED
;
50 using ::com::sun::star::frame::FrameAction_FRAME_DEACTIVATING
;
51 using ::com::sun::star::frame::FrameAction_FRAME_UI_DEACTIVATING
;
52 using ::com::sun::star::frame::XModel
;
53 using ::com::sun::star::frame::XController
;
54 using ::com::sun::star::frame::XController2
;
55 using ::com::sun::star::awt::XTopWindow
;
56 using ::com::sun::star::awt::XTopWindowListener
;
57 using ::com::sun::star::awt::XWindow2
;
58 using ::com::sun::star::lang::DisposedException
;
59 using ::com::sun::star::lang::EventObject
;
60 using ::com::sun::star::document::XDocumentEventBroadcaster
;
61 using ::com::sun::star::awt::XWindow
;
63 // FrameWindowActivationListener
64 typedef ::cppu::WeakImplHelper
< XTopWindowListener
65 > FrameWindowActivationListener_Base
;
69 class FrameWindowActivationListener
: public FrameWindowActivationListener_Base
72 explicit FrameWindowActivationListener( ControllerFrame_Data
& _rData
);
77 virtual ~FrameWindowActivationListener() override
;
80 virtual void SAL_CALL
windowOpened( const css::lang::EventObject
& e
) override
;
81 virtual void SAL_CALL
windowClosing( const css::lang::EventObject
& e
) override
;
82 virtual void SAL_CALL
windowClosed( const css::lang::EventObject
& e
) override
;
83 virtual void SAL_CALL
windowMinimized( const css::lang::EventObject
& e
) override
;
84 virtual void SAL_CALL
windowNormalized( const css::lang::EventObject
& e
) override
;
85 virtual void SAL_CALL
windowActivated( const css::lang::EventObject
& e
) override
;
86 virtual void SAL_CALL
windowDeactivated( const css::lang::EventObject
& e
) override
;
89 virtual void SAL_CALL
disposing( const css::lang::EventObject
& Source
) override
;
92 void impl_checkDisposed_throw() const;
93 void impl_registerOnFrameContainerWindow_nothrow( bool _bRegister
);
96 ControllerFrame_Data
* m_pData
;
101 // ControllerFrame_Data
102 struct ControllerFrame_Data
104 explicit ControllerFrame_Data( IController
& _rController
)
105 :m_rController( _rController
)
107 ,m_bIsTopLevelDocumentWindow( false )
111 IController
& m_rController
;
112 Reference
< XFrame
> m_xFrame
;
113 Reference
< XDocumentEventBroadcaster
> m_xDocEventBroadcaster
;
114 ::rtl::Reference
< FrameWindowActivationListener
> m_pListener
;
116 bool m_bIsTopLevelDocumentWindow
;
120 static void lcl_setFrame_nothrow( ControllerFrame_Data
& _rData
, const Reference
< XFrame
>& _rxFrame
)
122 // release old listener
123 if (_rData
.m_pListener
)
125 _rData
.m_pListener
->dispose();
126 _rData
.m_pListener
= nullptr;
129 // remember new frame
130 _rData
.m_xFrame
= _rxFrame
;
132 // create new listener
133 if ( _rData
.m_xFrame
.is() )
134 _rData
.m_pListener
= new FrameWindowActivationListener( _rData
);
136 // at this point in time, we can assume the controller also has a model set, if it supports models
139 Reference
< XController
> xController( _rData
.m_rController
.getXController(), UNO_SET_THROW
);
140 Reference
< XModel
> xModel( xController
->getModel() );
142 _rData
.m_xDocEventBroadcaster
.set( xModel
, UNO_QUERY
);
144 catch( const Exception
& )
146 DBG_UNHANDLED_EXCEPTION("dbaccess");
150 static bool lcl_isActive_nothrow( const Reference
< XFrame
>& _rxFrame
)
152 bool bIsActive
= false;
157 Reference
< XWindow2
> xWindow( _rxFrame
->getContainerWindow(), UNO_QUERY_THROW
);
158 bIsActive
= xWindow
->isActive();
162 catch( const Exception
& )
164 DBG_UNHANDLED_EXCEPTION("dbaccess");
169 /** updates various global and local states with a new active component
171 In particular, the following are updated
172 * the global working document (aka Basic's ThisComponent in the application
173 Basic), with our controller's model, or the controller itself if there is no such
176 static void lcl_updateActiveComponents_nothrow( const ControllerFrame_Data
& _rData
)
180 Reference
< XController
> xCompController( _rData
.m_rController
.getXController() );
181 OSL_ENSURE( xCompController
.is(), "lcl_updateActiveComponents_nothrow: can't do anything without a controller!" );
182 if ( !xCompController
.is() )
185 if ( _rData
.m_bActive
&& _rData
.m_bIsTopLevelDocumentWindow
)
187 // set the "current component" at the SfxObjectShell
188 Reference
< XModel
> xModel( xCompController
->getModel() );
189 Reference
< XInterface
> xCurrentComponent
;
191 xCurrentComponent
= xModel
;
193 xCurrentComponent
= xCompController
;
194 SfxObjectShell::SetCurrentComponent( xCurrentComponent
);
197 catch( const Exception
& )
199 DBG_UNHANDLED_EXCEPTION("dbaccess");
203 /** broadcasts the OnFocus resp. OnUnfocus event
205 static void lcl_notifyFocusChange_nothrow( ControllerFrame_Data
& _rData
, bool _bActive
)
209 if ( _rData
.m_xDocEventBroadcaster
.is() )
211 OUString sEventName
= _bActive
? u
"OnFocus"_ustr
: u
"OnUnfocus"_ustr
;
212 Reference
< XController2
> xController( _rData
.m_rController
.getXController(), UNO_QUERY_THROW
);
213 _rData
.m_xDocEventBroadcaster
->notifyDocumentEvent( sEventName
, xController
, Any() );
216 catch( const Exception
& )
218 DBG_UNHANDLED_EXCEPTION("dbaccess");
222 static void lcl_updateActive_nothrow( ControllerFrame_Data
& _rData
, bool _bActive
)
224 if ( _rData
.m_bActive
== _bActive
)
226 _rData
.m_bActive
= _bActive
;
228 lcl_updateActiveComponents_nothrow( _rData
);
229 lcl_notifyFocusChange_nothrow( _rData
, _bActive
);
232 FrameWindowActivationListener::FrameWindowActivationListener( ControllerFrame_Data
& _rData
)
235 impl_registerOnFrameContainerWindow_nothrow( true );
238 FrameWindowActivationListener::~FrameWindowActivationListener()
242 void FrameWindowActivationListener::dispose()
244 impl_registerOnFrameContainerWindow_nothrow( false );
248 void FrameWindowActivationListener::impl_registerOnFrameContainerWindow_nothrow( bool _bRegister
)
250 OSL_ENSURE( m_pData
&& m_pData
->m_xFrame
.is(), "FrameWindowActivationListener::impl_registerOnFrameContainerWindow_nothrow: no frame!" );
251 if ( !m_pData
|| !m_pData
->m_xFrame
.is() )
256 void ( SAL_CALL
XTopWindow::*pListenerAction
)( const Reference
< XTopWindowListener
>& ) =
257 _bRegister
? &XTopWindow::addTopWindowListener
: &XTopWindow::removeTopWindowListener
;
259 const Reference
< XWindow
> xContainerWindow( m_pData
->m_xFrame
->getContainerWindow(), UNO_SET_THROW
);
262 const vcl::Window
* pContainerWindow
= VCLUnoHelper::GetWindow( xContainerWindow
);
263 ENSURE_OR_THROW( pContainerWindow
, "no Window implementation for the frame's container window!" );
265 m_pData
->m_bIsTopLevelDocumentWindow
= bool( pContainerWindow
->GetExtendedStyle() & WindowExtendedStyle::Document
);
268 const Reference
< XTopWindow
> xFrameContainer( xContainerWindow
, UNO_QUERY
);
269 if ( xFrameContainer
.is() )
270 (xFrameContainer
.get()->*pListenerAction
)( this );
272 catch( const Exception
& )
274 DBG_UNHANDLED_EXCEPTION("dbaccess");
278 void FrameWindowActivationListener::impl_checkDisposed_throw() const
281 throw DisposedException( OUString(), *const_cast< FrameWindowActivationListener
* >( this ) );
284 void SAL_CALL
FrameWindowActivationListener::windowOpened( const EventObject
& /*_rEvent*/ )
289 void SAL_CALL
FrameWindowActivationListener::windowClosing( const EventObject
& /*_rEvent*/ )
294 void SAL_CALL
FrameWindowActivationListener::windowClosed( const EventObject
& /*_rEvent*/ )
299 void SAL_CALL
FrameWindowActivationListener::windowMinimized( const EventObject
& /*_rEvent*/ )
304 void SAL_CALL
FrameWindowActivationListener::windowNormalized( const EventObject
& /*_rEvent*/ )
309 void SAL_CALL
FrameWindowActivationListener::windowActivated( const EventObject
& /*_rEvent*/ )
311 impl_checkDisposed_throw();
312 lcl_updateActive_nothrow( *m_pData
, true );
315 void SAL_CALL
FrameWindowActivationListener::windowDeactivated( const EventObject
& /*_rEvent*/ )
317 impl_checkDisposed_throw();
318 lcl_updateActive_nothrow( *m_pData
, false );
321 void SAL_CALL
FrameWindowActivationListener::disposing( const EventObject
& /*_rEvent*/ )
327 ControllerFrame::ControllerFrame( IController
& _rController
)
328 :m_pData( new ControllerFrame_Data( _rController
) )
332 ControllerFrame::~ControllerFrame()
336 const Reference
< XFrame
>& ControllerFrame::attachFrame( const Reference
< XFrame
>& _rxFrame
)
338 // set new frame, including listener handling
339 lcl_setFrame_nothrow( *m_pData
, _rxFrame
);
341 // determine whether we're active
342 m_pData
->m_bActive
= lcl_isActive_nothrow( m_pData
->m_xFrame
);
344 // update active component
345 if ( m_pData
->m_bActive
)
347 lcl_updateActiveComponents_nothrow( *m_pData
);
348 lcl_notifyFocusChange_nothrow( *m_pData
, true );
351 return m_pData
->m_xFrame
;
354 const Reference
< XFrame
>& ControllerFrame::getFrame() const
356 return m_pData
->m_xFrame
;
359 bool ControllerFrame::isActive() const
361 return m_pData
->m_bActive
;
364 void ControllerFrame::frameAction( FrameAction _eAction
)
366 bool bActive
= m_pData
->m_bActive
;
370 case FrameAction_FRAME_ACTIVATED
:
371 case FrameAction_FRAME_UI_ACTIVATED
:
375 case FrameAction_FRAME_DEACTIVATING
:
376 case FrameAction_FRAME_UI_DEACTIVATING
:
384 lcl_updateActive_nothrow( *m_pData
, bActive
);
389 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */