Fix GNU C++ version check
[LibreOffice.git] / dbaccess / source / ui / misc / controllerframe.cxx
blobcfca8f73413ec992d14acc458e971b682395b9c7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
36 namespace dbaui
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;
67 namespace {
69 class FrameWindowActivationListener : public FrameWindowActivationListener_Base
71 public:
72 explicit FrameWindowActivationListener( ControllerFrame_Data& _rData );
74 void dispose();
76 protected:
77 virtual ~FrameWindowActivationListener() override;
79 // XTopWindowListener
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;
88 // XEventListener
89 virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
91 private:
92 void impl_checkDisposed_throw() const;
93 void impl_registerOnFrameContainerWindow_nothrow( bool _bRegister );
95 private:
96 ControllerFrame_Data* m_pData;
101 // ControllerFrame_Data
102 struct ControllerFrame_Data
104 explicit ControllerFrame_Data( IController& _rController )
105 :m_rController( _rController )
106 ,m_bActive( false )
107 ,m_bIsTopLevelDocumentWindow( false )
111 IController& m_rController;
112 Reference< XFrame > m_xFrame;
113 Reference< XDocumentEventBroadcaster > m_xDocEventBroadcaster;
114 ::rtl::Reference< FrameWindowActivationListener > m_pListener;
115 bool m_bActive;
116 bool m_bIsTopLevelDocumentWindow;
119 // helper
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() );
141 if ( xModel.is() )
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;
155 if ( _rxFrame.is() )
157 Reference< XWindow2 > xWindow( _rxFrame->getContainerWindow(), UNO_QUERY_THROW );
158 bIsActive = xWindow->isActive();
162 catch( const Exception& )
164 DBG_UNHANDLED_EXCEPTION("dbaccess");
166 return bIsActive;
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
174 model.
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() )
183 return;
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;
190 if ( xModel.is() )
191 xCurrentComponent = xModel;
192 else
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 )
225 return;
226 _rData.m_bActive = _bActive;
228 lcl_updateActiveComponents_nothrow( _rData );
229 lcl_notifyFocusChange_nothrow( _rData, _bActive );
232 FrameWindowActivationListener::FrameWindowActivationListener( ControllerFrame_Data& _rData )
233 :m_pData( &_rData )
235 impl_registerOnFrameContainerWindow_nothrow( true );
238 FrameWindowActivationListener::~FrameWindowActivationListener()
242 void FrameWindowActivationListener::dispose()
244 impl_registerOnFrameContainerWindow_nothrow( false );
245 m_pData = nullptr;
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() )
252 return;
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 );
260 if ( _bRegister )
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
280 if ( !m_pData )
281 throw DisposedException( OUString(), *const_cast< FrameWindowActivationListener* >( this ) );
284 void SAL_CALL FrameWindowActivationListener::windowOpened( const EventObject& /*_rEvent*/ )
286 // not interested in
289 void SAL_CALL FrameWindowActivationListener::windowClosing( const EventObject& /*_rEvent*/ )
291 // not interested in
294 void SAL_CALL FrameWindowActivationListener::windowClosed( const EventObject& /*_rEvent*/ )
296 // not interested in
299 void SAL_CALL FrameWindowActivationListener::windowMinimized( const EventObject& /*_rEvent*/ )
301 // not interested in
304 void SAL_CALL FrameWindowActivationListener::windowNormalized( const EventObject& /*_rEvent*/ )
306 // not interested in
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*/ )
323 dispose();
326 // ControllerFrame
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;
368 switch ( _eAction )
370 case FrameAction_FRAME_ACTIVATED:
371 case FrameAction_FRAME_UI_ACTIVATED:
372 bActive = true;
373 break;
375 case FrameAction_FRAME_DEACTIVATING:
376 case FrameAction_FRAME_UI_DEACTIVATING:
377 bActive = false;
378 break;
380 default:
381 break;
384 lcl_updateActive_nothrow( *m_pData, bActive );
387 } // namespace dbaui
389 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */