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/sdb/XOfficeDatabaseDocument.hpp>
24 #include <com/sun/star/awt/XTopWindow.hpp>
25 #include <com/sun/star/awt/XWindow2.hpp>
26 #include <com/sun/star/lang/DisposedException.hpp>
27 #include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
28 #include <com/sun/star/frame/XController2.hpp>
30 #include <cppuhelper/implbase1.hxx>
31 #include <rtl/ref.hxx>
32 #include <sfx2/objsh.hxx>
33 #include <tools/diagnose_ex.h>
34 #include <toolkit/helper/vclunohelper.hxx>
35 #include <vcl/window.hxx>
40 using ::com::sun::star::uno::Reference
;
41 using ::com::sun::star::uno::XInterface
;
42 using ::com::sun::star::uno::UNO_QUERY
;
43 using ::com::sun::star::uno::UNO_QUERY_THROW
;
44 using ::com::sun::star::uno::UNO_SET_THROW
;
45 using ::com::sun::star::uno::Exception
;
46 using ::com::sun::star::uno::RuntimeException
;
47 using ::com::sun::star::uno::Any
;
48 using ::com::sun::star::uno::makeAny
;
49 using ::com::sun::star::frame::XFrame
;
50 using ::com::sun::star::frame::FrameAction
;
51 using ::com::sun::star::frame::FrameAction_FRAME_ACTIVATED
;
52 using ::com::sun::star::frame::FrameAction_FRAME_UI_ACTIVATED
;
53 using ::com::sun::star::frame::FrameAction_FRAME_DEACTIVATING
;
54 using ::com::sun::star::frame::FrameAction_FRAME_UI_DEACTIVATING
;
55 using ::com::sun::star::frame::XModel
;
56 using ::com::sun::star::frame::XController
;
57 using ::com::sun::star::frame::XController2
;
58 using ::com::sun::star::frame::XFramesSupplier
;
59 using ::com::sun::star::sdb::XOfficeDatabaseDocument
;
60 using ::com::sun::star::awt::XTopWindow
;
61 using ::com::sun::star::awt::XTopWindowListener
;
62 using ::com::sun::star::awt::XWindow2
;
63 using ::com::sun::star::lang::DisposedException
;
64 using ::com::sun::star::lang::EventObject
;
65 using ::com::sun::star::document::XDocumentEventBroadcaster
;
66 using ::com::sun::star::awt::XWindow
;
68 // FrameWindowActivationListener
69 typedef ::cppu::WeakImplHelper1
< XTopWindowListener
70 > FrameWindowActivationListener_Base
;
71 class FrameWindowActivationListener
: public FrameWindowActivationListener_Base
74 FrameWindowActivationListener( ControllerFrame_Data
& _rData
);
79 virtual ~FrameWindowActivationListener();
82 virtual void SAL_CALL
windowOpened( const ::com::sun::star::lang::EventObject
& e
) throw (::com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
83 virtual void SAL_CALL
windowClosing( const ::com::sun::star::lang::EventObject
& e
) throw (::com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
84 virtual void SAL_CALL
windowClosed( const ::com::sun::star::lang::EventObject
& e
) throw (::com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
85 virtual void SAL_CALL
windowMinimized( const ::com::sun::star::lang::EventObject
& e
) throw (::com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
86 virtual void SAL_CALL
windowNormalized( const ::com::sun::star::lang::EventObject
& e
) throw (::com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
87 virtual void SAL_CALL
windowActivated( const ::com::sun::star::lang::EventObject
& e
) throw (::com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
88 virtual void SAL_CALL
windowDeactivated( const ::com::sun::star::lang::EventObject
& e
) throw (::com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
91 virtual void SAL_CALL
disposing( const ::com::sun::star::lang::EventObject
& Source
) throw (::com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
94 void impl_checkDisposed_throw() const;
95 void impl_registerOnFrameContainerWindow_nothrow( bool _bRegister
);
98 ControllerFrame_Data
* m_pData
;
101 // ControllerFrame_Data
102 struct ControllerFrame_Data
104 ControllerFrame_Data( IController
& _rController
)
105 :m_rController( _rController
)
107 ,m_xDocEventBroadcaster()
110 ,m_bIsTopLevelDocumentWindow( false )
114 IController
& m_rController
;
115 Reference
< XFrame
> m_xFrame
;
116 Reference
< XDocumentEventBroadcaster
> m_xDocEventBroadcaster
;
117 ::rtl::Reference
< FrameWindowActivationListener
> m_pListener
;
119 bool m_bIsTopLevelDocumentWindow
;
123 static void lcl_setFrame_nothrow( ControllerFrame_Data
& _rData
, const Reference
< XFrame
>& _rxFrame
)
125 // release old listener
126 if ( _rData
.m_pListener
.get() )
128 _rData
.m_pListener
->dispose();
129 _rData
.m_pListener
= NULL
;
132 // remember new frame
133 _rData
.m_xFrame
= _rxFrame
;
135 // create new listener
136 if ( _rData
.m_xFrame
.is() )
137 _rData
.m_pListener
= new FrameWindowActivationListener( _rData
);
139 // at this point in time, we can assume the controller also has a model set, if it supports models
142 Reference
< XController
> xController( _rData
.m_rController
.getXController(), UNO_SET_THROW
);
143 Reference
< XModel
> xModel( xController
->getModel() );
145 _rData
.m_xDocEventBroadcaster
.set( xModel
, UNO_QUERY
);
147 catch( const Exception
& )
149 DBG_UNHANDLED_EXCEPTION();
153 static bool lcl_isActive_nothrow( const Reference
< XFrame
>& _rxFrame
)
155 bool bIsActive
= false;
160 Reference
< XWindow2
> xWindow( _rxFrame
->getContainerWindow(), UNO_QUERY_THROW
);
161 bIsActive
= xWindow
->isActive();
165 catch( const Exception
& )
167 DBG_UNHANDLED_EXCEPTION();
172 /** updates various global and local states with a new active component
174 In particular, the following are updated
175 * the global working document (aka Basic's ThisComponent in the application
176 Basic), with our controller's model, or the controller itself if there is no such
179 static void lcl_updateActiveComponents_nothrow( const ControllerFrame_Data
& _rData
)
183 Reference
< XController
> xCompController( _rData
.m_rController
.getXController() );
184 OSL_ENSURE( xCompController
.is(), "lcl_updateActiveComponents_nothrow: can't do anything without a controller!" );
185 if ( !xCompController
.is() )
188 if ( _rData
.m_bActive
&& _rData
.m_bIsTopLevelDocumentWindow
)
190 // set the "current component" at the SfxObjectShell
191 Reference
< XModel
> xModel( xCompController
->getModel() );
192 Reference
< XInterface
> xCurrentComponent
;
194 xCurrentComponent
= xModel
;
196 xCurrentComponent
= xCompController
;
197 SfxObjectShell::SetCurrentComponent( xCurrentComponent
);
200 catch( const Exception
& )
202 DBG_UNHANDLED_EXCEPTION();
206 /** broadcasts the OnFocus resp. OnUnfocus event
208 static void lcl_notifyFocusChange_nothrow( ControllerFrame_Data
& _rData
, bool _bActive
)
212 if ( _rData
.m_xDocEventBroadcaster
.is() )
214 OUString sEventName
= _bActive
? OUString("OnFocus") : OUString("OnUnfocus");
215 Reference
< XController2
> xController( _rData
.m_rController
.getXController(), UNO_QUERY_THROW
);
216 _rData
.m_xDocEventBroadcaster
->notifyDocumentEvent( sEventName
, xController
, Any() );
219 catch( const Exception
& )
221 DBG_UNHANDLED_EXCEPTION();
225 static void lcl_updateActive_nothrow( ControllerFrame_Data
& _rData
, bool _bActive
)
227 if ( _rData
.m_bActive
== _bActive
)
229 _rData
.m_bActive
= _bActive
;
231 lcl_updateActiveComponents_nothrow( _rData
);
232 lcl_notifyFocusChange_nothrow( _rData
, _bActive
);
235 FrameWindowActivationListener::FrameWindowActivationListener( ControllerFrame_Data
& _rData
)
238 impl_registerOnFrameContainerWindow_nothrow( true );
241 FrameWindowActivationListener::~FrameWindowActivationListener()
245 void FrameWindowActivationListener::dispose()
247 impl_registerOnFrameContainerWindow_nothrow( false );
251 void FrameWindowActivationListener::impl_registerOnFrameContainerWindow_nothrow( bool _bRegister
)
253 OSL_ENSURE( m_pData
&& m_pData
->m_xFrame
.is(), "FrameWindowActivationListener::impl_registerOnFrameContainerWindow_nothrow: no frame!" );
254 if ( !m_pData
|| !m_pData
->m_xFrame
.is() )
259 void ( SAL_CALL
XTopWindow::*pListenerAction
)( const Reference
< XTopWindowListener
>& ) =
260 _bRegister
? &XTopWindow::addTopWindowListener
: &XTopWindow::removeTopWindowListener
;
262 const Reference
< XWindow
> xContainerWindow( m_pData
->m_xFrame
->getContainerWindow(), UNO_SET_THROW
);
265 const vcl::Window
* pContainerWindow
= VCLUnoHelper::GetWindow( xContainerWindow
);
266 ENSURE_OR_THROW( pContainerWindow
, "no Window implementation for the frame's container window!" );
268 m_pData
->m_bIsTopLevelDocumentWindow
= ( pContainerWindow
->GetExtendedStyle() & WB_EXT_DOCUMENT
) != 0;
271 const Reference
< XTopWindow
> xFrameContainer( xContainerWindow
, UNO_QUERY
);
272 if ( xFrameContainer
.is() )
273 (xFrameContainer
.get()->*pListenerAction
)( this );
275 catch( const Exception
& )
277 DBG_UNHANDLED_EXCEPTION();
281 void FrameWindowActivationListener::impl_checkDisposed_throw() const
284 throw DisposedException( OUString(), *const_cast< FrameWindowActivationListener
* >( this ) );
287 void SAL_CALL
FrameWindowActivationListener::windowOpened( const EventObject
& /*_rEvent*/ ) throw (RuntimeException
, std::exception
)
292 void SAL_CALL
FrameWindowActivationListener::windowClosing( const EventObject
& /*_rEvent*/ ) throw (RuntimeException
, std::exception
)
297 void SAL_CALL
FrameWindowActivationListener::windowClosed( const EventObject
& /*_rEvent*/ ) throw (RuntimeException
, std::exception
)
302 void SAL_CALL
FrameWindowActivationListener::windowMinimized( const EventObject
& /*_rEvent*/ ) throw (RuntimeException
, std::exception
)
307 void SAL_CALL
FrameWindowActivationListener::windowNormalized( const EventObject
& /*_rEvent*/ ) throw (RuntimeException
, std::exception
)
312 void SAL_CALL
FrameWindowActivationListener::windowActivated( const EventObject
& /*_rEvent*/ ) throw (RuntimeException
, std::exception
)
314 impl_checkDisposed_throw();
315 lcl_updateActive_nothrow( *m_pData
, true );
318 void SAL_CALL
FrameWindowActivationListener::windowDeactivated( const EventObject
& /*_rEvent*/ ) throw (RuntimeException
, std::exception
)
320 impl_checkDisposed_throw();
321 lcl_updateActive_nothrow( *m_pData
, false );
324 void SAL_CALL
FrameWindowActivationListener::disposing( const EventObject
& /*_rEvent*/ ) throw (RuntimeException
, std::exception
)
330 ControllerFrame::ControllerFrame( IController
& _rController
)
331 :m_pData( new ControllerFrame_Data( _rController
) )
335 ControllerFrame::~ControllerFrame()
339 const Reference
< XFrame
>& ControllerFrame::attachFrame( const Reference
< XFrame
>& _rxFrame
)
341 // set new frame, including listener handling
342 lcl_setFrame_nothrow( *m_pData
, _rxFrame
);
344 // determine whether we're active
345 m_pData
->m_bActive
= lcl_isActive_nothrow( m_pData
->m_xFrame
);
347 // update active component
348 if ( m_pData
->m_bActive
)
350 lcl_updateActiveComponents_nothrow( *m_pData
);
351 lcl_notifyFocusChange_nothrow( *m_pData
, true );
354 return m_pData
->m_xFrame
;
357 const Reference
< XFrame
>& ControllerFrame::getFrame() const
359 return m_pData
->m_xFrame
;
362 bool ControllerFrame::isActive() const
364 return m_pData
->m_bActive
;
367 void ControllerFrame::frameAction( FrameAction _eAction
)
369 bool bActive
= m_pData
->m_bActive
;
373 case FrameAction_FRAME_ACTIVATED
:
374 case FrameAction_FRAME_UI_ACTIVATED
:
378 case FrameAction_FRAME_DEACTIVATING
:
379 case FrameAction_FRAME_UI_DEACTIVATING
:
387 lcl_updateActive_nothrow( *m_pData
, bActive
);
392 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */