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 <tools/diagnose_ex.h>
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::RuntimeException
;
46 using ::com::sun::star::uno::Any
;
47 using ::com::sun::star::frame::XFrame
;
48 using ::com::sun::star::frame::FrameAction
;
49 using ::com::sun::star::frame::FrameAction_FRAME_ACTIVATED
;
50 using ::com::sun::star::frame::FrameAction_FRAME_UI_ACTIVATED
;
51 using ::com::sun::star::frame::FrameAction_FRAME_DEACTIVATING
;
52 using ::com::sun::star::frame::FrameAction_FRAME_UI_DEACTIVATING
;
53 using ::com::sun::star::frame::XModel
;
54 using ::com::sun::star::frame::XController
;
55 using ::com::sun::star::frame::XController2
;
56 using ::com::sun::star::awt::XTopWindow
;
57 using ::com::sun::star::awt::XTopWindowListener
;
58 using ::com::sun::star::awt::XWindow2
;
59 using ::com::sun::star::lang::DisposedException
;
60 using ::com::sun::star::lang::EventObject
;
61 using ::com::sun::star::document::XDocumentEventBroadcaster
;
62 using ::com::sun::star::awt::XWindow
;
64 // FrameWindowActivationListener
65 typedef ::cppu::WeakImplHelper
< XTopWindowListener
66 > FrameWindowActivationListener_Base
;
67 class FrameWindowActivationListener
: public FrameWindowActivationListener_Base
70 explicit FrameWindowActivationListener( ControllerFrame_Data
& _rData
);
75 virtual ~FrameWindowActivationListener();
78 virtual void SAL_CALL
windowOpened( const css::lang::EventObject
& e
) throw (css::uno::RuntimeException
, std::exception
) override
;
79 virtual void SAL_CALL
windowClosing( const css::lang::EventObject
& e
) throw (css::uno::RuntimeException
, std::exception
) override
;
80 virtual void SAL_CALL
windowClosed( const css::lang::EventObject
& e
) throw (css::uno::RuntimeException
, std::exception
) override
;
81 virtual void SAL_CALL
windowMinimized( const css::lang::EventObject
& e
) throw (css::uno::RuntimeException
, std::exception
) override
;
82 virtual void SAL_CALL
windowNormalized( const css::lang::EventObject
& e
) throw (css::uno::RuntimeException
, std::exception
) override
;
83 virtual void SAL_CALL
windowActivated( const css::lang::EventObject
& e
) throw (css::uno::RuntimeException
, std::exception
) override
;
84 virtual void SAL_CALL
windowDeactivated( const css::lang::EventObject
& e
) throw (css::uno::RuntimeException
, std::exception
) override
;
87 virtual void SAL_CALL
disposing( const css::lang::EventObject
& Source
) throw (css::uno::RuntimeException
, std::exception
) override
;
90 void impl_checkDisposed_throw() const;
91 void impl_registerOnFrameContainerWindow_nothrow( bool _bRegister
);
94 ControllerFrame_Data
* m_pData
;
97 // ControllerFrame_Data
98 struct ControllerFrame_Data
100 explicit ControllerFrame_Data( IController
& _rController
)
101 :m_rController( _rController
)
103 ,m_xDocEventBroadcaster()
106 ,m_bIsTopLevelDocumentWindow( false )
110 IController
& m_rController
;
111 Reference
< XFrame
> m_xFrame
;
112 Reference
< XDocumentEventBroadcaster
> m_xDocEventBroadcaster
;
113 ::rtl::Reference
< FrameWindowActivationListener
> m_pListener
;
115 bool m_bIsTopLevelDocumentWindow
;
119 static void lcl_setFrame_nothrow( ControllerFrame_Data
& _rData
, const Reference
< XFrame
>& _rxFrame
)
121 // release old listener
122 if ( _rData
.m_pListener
.get() )
124 _rData
.m_pListener
->dispose();
125 _rData
.m_pListener
= nullptr;
128 // remember new frame
129 _rData
.m_xFrame
= _rxFrame
;
131 // create new listener
132 if ( _rData
.m_xFrame
.is() )
133 _rData
.m_pListener
= new FrameWindowActivationListener( _rData
);
135 // at this point in time, we can assume the controller also has a model set, if it supports models
138 Reference
< XController
> xController( _rData
.m_rController
.getXController(), UNO_SET_THROW
);
139 Reference
< XModel
> xModel( xController
->getModel() );
141 _rData
.m_xDocEventBroadcaster
.set( xModel
, UNO_QUERY
);
143 catch( const Exception
& )
145 DBG_UNHANDLED_EXCEPTION();
149 static bool lcl_isActive_nothrow( const Reference
< XFrame
>& _rxFrame
)
151 bool bIsActive
= false;
156 Reference
< XWindow2
> xWindow( _rxFrame
->getContainerWindow(), UNO_QUERY_THROW
);
157 bIsActive
= xWindow
->isActive();
161 catch( const Exception
& )
163 DBG_UNHANDLED_EXCEPTION();
168 /** updates various global and local states with a new active component
170 In particular, the following are updated
171 * the global working document (aka Basic's ThisComponent in the application
172 Basic), with our controller's model, or the controller itself if there is no such
175 static void lcl_updateActiveComponents_nothrow( const ControllerFrame_Data
& _rData
)
179 Reference
< XController
> xCompController( _rData
.m_rController
.getXController() );
180 OSL_ENSURE( xCompController
.is(), "lcl_updateActiveComponents_nothrow: can't do anything without a controller!" );
181 if ( !xCompController
.is() )
184 if ( _rData
.m_bActive
&& _rData
.m_bIsTopLevelDocumentWindow
)
186 // set the "current component" at the SfxObjectShell
187 Reference
< XModel
> xModel( xCompController
->getModel() );
188 Reference
< XInterface
> xCurrentComponent
;
190 xCurrentComponent
= xModel
;
192 xCurrentComponent
= xCompController
;
193 SfxObjectShell::SetCurrentComponent( xCurrentComponent
);
196 catch( const Exception
& )
198 DBG_UNHANDLED_EXCEPTION();
202 /** broadcasts the OnFocus resp. OnUnfocus event
204 static void lcl_notifyFocusChange_nothrow( ControllerFrame_Data
& _rData
, bool _bActive
)
208 if ( _rData
.m_xDocEventBroadcaster
.is() )
210 OUString sEventName
= _bActive
? OUString("OnFocus") : OUString("OnUnfocus");
211 Reference
< XController2
> xController( _rData
.m_rController
.getXController(), UNO_QUERY_THROW
);
212 _rData
.m_xDocEventBroadcaster
->notifyDocumentEvent( sEventName
, xController
, Any() );
215 catch( const Exception
& )
217 DBG_UNHANDLED_EXCEPTION();
221 static void lcl_updateActive_nothrow( ControllerFrame_Data
& _rData
, bool _bActive
)
223 if ( _rData
.m_bActive
== _bActive
)
225 _rData
.m_bActive
= _bActive
;
227 lcl_updateActiveComponents_nothrow( _rData
);
228 lcl_notifyFocusChange_nothrow( _rData
, _bActive
);
231 FrameWindowActivationListener::FrameWindowActivationListener( ControllerFrame_Data
& _rData
)
234 impl_registerOnFrameContainerWindow_nothrow( true );
237 FrameWindowActivationListener::~FrameWindowActivationListener()
241 void FrameWindowActivationListener::dispose()
243 impl_registerOnFrameContainerWindow_nothrow( false );
247 void FrameWindowActivationListener::impl_registerOnFrameContainerWindow_nothrow( bool _bRegister
)
249 OSL_ENSURE( m_pData
&& m_pData
->m_xFrame
.is(), "FrameWindowActivationListener::impl_registerOnFrameContainerWindow_nothrow: no frame!" );
250 if ( !m_pData
|| !m_pData
->m_xFrame
.is() )
255 void ( SAL_CALL
XTopWindow::*pListenerAction
)( const Reference
< XTopWindowListener
>& ) =
256 _bRegister
? &XTopWindow::addTopWindowListener
: &XTopWindow::removeTopWindowListener
;
258 const Reference
< XWindow
> xContainerWindow( m_pData
->m_xFrame
->getContainerWindow(), UNO_SET_THROW
);
261 const vcl::Window
* pContainerWindow
= VCLUnoHelper::GetWindow( xContainerWindow
);
262 ENSURE_OR_THROW( pContainerWindow
, "no Window implementation for the frame's container window!" );
264 m_pData
->m_bIsTopLevelDocumentWindow
= ( pContainerWindow
->GetExtendedStyle() & WB_EXT_DOCUMENT
) != 0;
267 const Reference
< XTopWindow
> xFrameContainer( xContainerWindow
, UNO_QUERY
);
268 if ( xFrameContainer
.is() )
269 (xFrameContainer
.get()->*pListenerAction
)( this );
271 catch( const Exception
& )
273 DBG_UNHANDLED_EXCEPTION();
277 void FrameWindowActivationListener::impl_checkDisposed_throw() const
280 throw DisposedException( OUString(), *const_cast< FrameWindowActivationListener
* >( this ) );
283 void SAL_CALL
FrameWindowActivationListener::windowOpened( const EventObject
& /*_rEvent*/ ) throw (RuntimeException
, std::exception
)
288 void SAL_CALL
FrameWindowActivationListener::windowClosing( const EventObject
& /*_rEvent*/ ) throw (RuntimeException
, std::exception
)
293 void SAL_CALL
FrameWindowActivationListener::windowClosed( const EventObject
& /*_rEvent*/ ) throw (RuntimeException
, std::exception
)
298 void SAL_CALL
FrameWindowActivationListener::windowMinimized( const EventObject
& /*_rEvent*/ ) throw (RuntimeException
, std::exception
)
303 void SAL_CALL
FrameWindowActivationListener::windowNormalized( const EventObject
& /*_rEvent*/ ) throw (RuntimeException
, std::exception
)
308 void SAL_CALL
FrameWindowActivationListener::windowActivated( const EventObject
& /*_rEvent*/ ) throw (RuntimeException
, std::exception
)
310 impl_checkDisposed_throw();
311 lcl_updateActive_nothrow( *m_pData
, true );
314 void SAL_CALL
FrameWindowActivationListener::windowDeactivated( const EventObject
& /*_rEvent*/ ) throw (RuntimeException
, std::exception
)
316 impl_checkDisposed_throw();
317 lcl_updateActive_nothrow( *m_pData
, false );
320 void SAL_CALL
FrameWindowActivationListener::disposing( const EventObject
& /*_rEvent*/ ) throw (RuntimeException
, std::exception
)
326 ControllerFrame::ControllerFrame( IController
& _rController
)
327 :m_pData( new ControllerFrame_Data( _rController
) )
331 ControllerFrame::~ControllerFrame()
335 const Reference
< XFrame
>& ControllerFrame::attachFrame( const Reference
< XFrame
>& _rxFrame
)
337 // set new frame, including listener handling
338 lcl_setFrame_nothrow( *m_pData
, _rxFrame
);
340 // determine whether we're active
341 m_pData
->m_bActive
= lcl_isActive_nothrow( m_pData
->m_xFrame
);
343 // update active component
344 if ( m_pData
->m_bActive
)
346 lcl_updateActiveComponents_nothrow( *m_pData
);
347 lcl_notifyFocusChange_nothrow( *m_pData
, true );
350 return m_pData
->m_xFrame
;
353 const Reference
< XFrame
>& ControllerFrame::getFrame() const
355 return m_pData
->m_xFrame
;
358 bool ControllerFrame::isActive() const
360 return m_pData
->m_bActive
;
363 void ControllerFrame::frameAction( FrameAction _eAction
)
365 bool bActive
= m_pData
->m_bActive
;
369 case FrameAction_FRAME_ACTIVATED
:
370 case FrameAction_FRAME_UI_ACTIVATED
:
374 case FrameAction_FRAME_DEACTIVATING
:
375 case FrameAction_FRAME_UI_DEACTIVATING
:
383 lcl_updateActive_nothrow( *m_pData
, bActive
);
388 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */