1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #ifndef _EXTENSIONS_PROPCTRLR_COMMONCONTROL_HXX_
29 #define _EXTENSIONS_PROPCTRLR_COMMONCONTROL_HXX_
30 
31 /** === begin UNO includes === **/
32 #include <com/sun/star/inspection/XPropertyControl.hpp>
33 #include <com/sun/star/lang/DisposedException.hpp>
34 /** === end UNO includes === **/
35 #include <cppuhelper/compbase1.hxx>
36 #include <comphelper/broadcasthelper.hxx>
37 #include <tools/link.hxx>
38 #include <vcl/window.hxx>
39 
40 class NotifyEvent;
41 //............................................................................
42 namespace pcr
43 {
44 //............................................................................
45 
46     class ControlHelper;
47     //========================================================================
48     //= ControlWindow
49     //========================================================================
50     template< class WINDOW >
51     class ControlWindow : public WINDOW
52     {
53     protected:
54         typedef WINDOW  WindowType;
55 
56     protected:
57         ControlHelper*  m_pHelper;
58 
59     public:
60         ControlWindow( Window* _pParent, WinBits _nStyle )
61             :WindowType( _pParent, _nStyle )
62             ,m_pHelper( NULL )
63         {
64         }
65 
66         /// sets a ControlHelper instance which some functionality is delegated to
67         inline virtual void setControlHelper( ControlHelper& _rControlHelper );
68 
69     protected:
70         // Window overridables
71         inline virtual long PreNotify( NotifyEvent& rNEvt );
72     };
73 
74     //========================================================================
75     //= IModifyListener
76     //========================================================================
77     class SAL_NO_VTABLE IModifyListener
78     {
79     public:
80         virtual void modified() = 0;
81     };
82 
83     //========================================================================
84     //= ControlHelper
85     //========================================================================
86     /** A helper class for implementing the <type scope="com::sun::star::inspection">XPropertyControl</type>
87         or one of its derived interfaces.
88 
89         This class is intended to be held as member of another class which implements the
90         <type scope="com::sun::star::inspection">XPropertyControl</type> interface. The pointer
91         to this interface is to be passed to the ctor.
92     */
93     class ControlHelper
94     {
95     private:
96         Window*                         m_pControlWindow;
97         sal_Int16                       m_nControlType;
98         ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControlContext >
99                                         m_xContext;
100         ::com::sun::star::inspection::XPropertyControl&
101                                         m_rAntiImpl;
102         IModifyListener*                m_pModifyListener;
103         sal_Bool                        m_bModified;
104 
105     public:
106         /** creates the instance
107             @param  _rControlWindow
108                 the window which is associated with the <type scope="com::sun::star::inspection">XPropertyControl</type>.
109                 Must not be <NULL/>.<br/>
110                 Ownership for this window is taken by the ControlHelper - it will be deleted in <member>disposing</member>.
111             @param  _nControlType
112                 the type of the control - one of the <type scope="com::sun::star::inspection">PropertyControlType</type>
113                 constants
114             @param _pAntiImpl
115                 Reference to the instance as whose "impl-class" we act. This reference is held during lifetime
116                 of the <type>ControlHelper</type> class, within acquiring it. Thus, the owner of the
117                 <type>ControlHelper</type> is responsible for assuring the lifetime of the instance
118                 pointed to by <arg>_pAntiImpl</arg>.
119             @param _pModifyListener
120                 a listener to be modfied when the user modified the control's value. the
121                 <member>IModifyListener::modified</member> of this listener is called from within our
122                 ModifiedHdl. A default implementation of <member>IModifyListener::modified</member>
123                 would just call our <member>setModified</member>.
124         */
125         ControlHelper(
126             Window* _pControlWindow,
127             sal_Int16 _nControlType,
128             ::com::sun::star::inspection::XPropertyControl& _rAntiImpl,
129             IModifyListener* _pModifyListener );
130 
131         virtual ~ControlHelper();
132 
133         /** sets our "modified" flag to <TRUE/>
134         */
135         inline void setModified() { m_bModified = sal_True; }
136         inline       Window* getVclControlWindow()       { return m_pControlWindow; }
137         inline const Window* getVclControlWindow() const { return m_pControlWindow; }
138 
139     public:
140         // XPropertyControl
141         ::sal_Int16 SAL_CALL getControlType() throw (::com::sun::star::uno::RuntimeException);
142         ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControlContext > SAL_CALL getControlContext() throw (::com::sun::star::uno::RuntimeException);
143         void SAL_CALL setControlContext( const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControlContext >& _controlcontext ) throw (::com::sun::star::uno::RuntimeException);
144         ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > SAL_CALL getControlWindow() throw (::com::sun::star::uno::RuntimeException);
145         ::sal_Bool SAL_CALL isModified(  ) throw (::com::sun::star::uno::RuntimeException);
146         void SAL_CALL notifyModifiedValue(  ) throw (::com::sun::star::uno::RuntimeException);
147 
148         // XComponent
149         virtual void SAL_CALL dispose();
150 
151         /** (fail-safe) wrapper around calling our context's activateNextControl
152         */
153         inline void activateNextControl() const { impl_activateNextControl_nothrow(); }
154 
155     public:
156         /// may be used to implement the default handling in PreNotify; returns sal_True if handled
157         bool handlePreNotify(NotifyEvent& _rNEvt);
158 
159         /// automatically size the window given in the ctor
160         void    autoSizeWindow();
161 
162         /// may be used by derived classes, they forward the event to the PropCtrListener
163         DECL_LINK( ModifiedHdl, Window* );
164         DECL_LINK( GetFocusHdl, Window* );
165         DECL_LINK( LoseFocusHdl, Window* );
166 
167     private:
168         /** fail-safe wrapper around calling our context's activateNextControl
169         */
170         void    impl_activateNextControl_nothrow() const;
171     };
172 
173     //========================================================================
174     //= CommonBehaviourControl
175     //========================================================================
176     /** implements a base class for <type scope="com::sun::star::inspection">XPropertyControl</type>
177         implementations, which delegates the generic functionality of this interface to a
178         <type>ControlHelper</type> member.
179 
180         @param CONTROL_INTERFACE
181             an interface class which is derived from (or identical to) <type scope="com::sun::star::inspection">XPropertyControl</type>
182         @param CONTROL_WINDOW
183             a class which is derived from ControlWindow
184     */
185     template < class CONTROL_INTERFACE, class CONTROL_WINDOW >
186     class CommonBehaviourControl    :public ::comphelper::OBaseMutex
187                                     ,public ::cppu::WeakComponentImplHelper1< CONTROL_INTERFACE >
188                                     ,public IModifyListener
189     {
190     protected:
191         typedef CONTROL_INTERFACE   InterfaceType;
192         typedef CONTROL_WINDOW      WindowType;
193 
194         typedef ::comphelper::OBaseMutex                                MutexBaseClass;
195         typedef ::cppu::WeakComponentImplHelper1< CONTROL_INTERFACE >   ComponentBaseClass;
196 
197     protected:
198         ControlHelper   m_aImplControl;
199 
200     protected:
201         inline CommonBehaviourControl( sal_Int16 _nControlType, Window* _pParentWindow, WinBits _nWindowStyle, bool _bDoSetHandlers = true );
202 
203         // XPropertyControl - delegated to ->m_aImplControl
204         inline ::sal_Int16 SAL_CALL getControlType() throw (::com::sun::star::uno::RuntimeException);
205         inline ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControlContext > SAL_CALL getControlContext() throw (::com::sun::star::uno::RuntimeException);
206         inline void SAL_CALL setControlContext( const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControlContext >& _controlcontext ) throw (::com::sun::star::uno::RuntimeException);
207         inline ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > SAL_CALL getControlWindow() throw (::com::sun::star::uno::RuntimeException);
208         inline ::sal_Bool SAL_CALL isModified(  ) throw (::com::sun::star::uno::RuntimeException);
209         inline void SAL_CALL notifyModifiedValue(  ) throw (::com::sun::star::uno::RuntimeException);
210 
211         // XComponent
212         inline virtual void SAL_CALL disposing();
213 
214         // IModifyListener
215         inline virtual void modified();
216 
217         /// returns a typed pointer to our control window
218               WindowType* getTypedControlWindow()       { return static_cast< WindowType* >      ( m_aImplControl.getVclControlWindow() ); }
219         const WindowType* getTypedControlWindow() const { return static_cast< const WindowType* >( m_aImplControl.getVclControlWindow() ); }
220 
221     protected:
222         /** checks whether the instance is already disposed
223             @throws DisposedException
224                 if the instance is already disposed
225         */
226         inline void impl_checkDisposed_throw();
227     };
228 
229     //========================================================================
230     //= ControlWindow - implementation
231     //========================================================================
232     //------------------------------------------------------------------------
233     template< class WINDOW >
234     inline void ControlWindow< WINDOW >::setControlHelper( ControlHelper& _rControlHelper )
235     {
236         m_pHelper = &_rControlHelper;
237     }
238 
239     //------------------------------------------------------------------------
240     template< class WINDOW >
241     inline long ControlWindow< WINDOW >::PreNotify( NotifyEvent& rNEvt )
242     {
243         if ( m_pHelper && m_pHelper->handlePreNotify( rNEvt ) )
244             return 1;
245         return WindowType::PreNotify( rNEvt );
246     }
247 
248     //========================================================================
249     //= CommonBehaviourControl - implementation
250     //========================================================================
251     //------------------------------------------------------------------------
252     template< class CONTROL_INTERFACE, class CONTROL_WINDOW >
253     inline CommonBehaviourControl< CONTROL_INTERFACE, CONTROL_WINDOW >::CommonBehaviourControl ( sal_Int16 _nControlType, Window* _pParentWindow, WinBits _nWindowStyle, bool _bDoSetHandlers )
254         :ComponentBaseClass( m_aMutex )
255         ,m_aImplControl( new WindowType( _pParentWindow, _nWindowStyle ), _nControlType, *this, this )
256     {
257         WindowType* pControlWindow( getTypedControlWindow() );
258         pControlWindow->setControlHelper( m_aImplControl );
259         if ( _bDoSetHandlers )
260         {
261             pControlWindow->SetModifyHdl( LINK( &m_aImplControl, ControlHelper, ModifiedHdl ) );
262 		    pControlWindow->SetGetFocusHdl( LINK( &m_aImplControl, ControlHelper, GetFocusHdl ) );
263 		    pControlWindow->SetLoseFocusHdl( LINK( &m_aImplControl, ControlHelper, LoseFocusHdl ) );
264         }
265 		m_aImplControl.autoSizeWindow();
266     }
267 
268     //--------------------------------------------------------------------
269     template< class CONTROL_INTERFACE, class CONTROL_WINDOW >
270     inline ::sal_Int16 SAL_CALL CommonBehaviourControl< CONTROL_INTERFACE, CONTROL_WINDOW >::getControlType() throw (::com::sun::star::uno::RuntimeException)
271     {
272         return m_aImplControl.getControlType();
273     }
274 
275     //--------------------------------------------------------------------
276     template< class CONTROL_INTERFACE, class CONTROL_WINDOW >
277     inline ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControlContext > SAL_CALL CommonBehaviourControl< CONTROL_INTERFACE, CONTROL_WINDOW >::getControlContext() throw (::com::sun::star::uno::RuntimeException)
278     {
279         return m_aImplControl.getControlContext();
280     }
281 
282     //--------------------------------------------------------------------
283     template< class CONTROL_INTERFACE, class CONTROL_WINDOW >
284     inline void SAL_CALL CommonBehaviourControl< CONTROL_INTERFACE, CONTROL_WINDOW >::setControlContext( const ::com::sun::star::uno::Reference< ::com::sun::star::inspection::XPropertyControlContext >& _controlcontext ) throw (::com::sun::star::uno::RuntimeException)
285     {
286         m_aImplControl.setControlContext( _controlcontext );
287     }
288 
289     //--------------------------------------------------------------------
290     template< class CONTROL_INTERFACE, class CONTROL_WINDOW >
291     inline ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > SAL_CALL CommonBehaviourControl< CONTROL_INTERFACE, CONTROL_WINDOW >::getControlWindow() throw (::com::sun::star::uno::RuntimeException)
292     {
293         return m_aImplControl.getControlWindow();
294     }
295 
296     //--------------------------------------------------------------------
297     template< class CONTROL_INTERFACE, class CONTROL_WINDOW >
298     inline ::sal_Bool SAL_CALL CommonBehaviourControl< CONTROL_INTERFACE, CONTROL_WINDOW >::isModified(  ) throw (::com::sun::star::uno::RuntimeException)
299     {
300         return m_aImplControl.isModified();
301     }
302 
303     //--------------------------------------------------------------------
304     template< class CONTROL_INTERFACE, class CONTROL_WINDOW >
305     inline void SAL_CALL CommonBehaviourControl< CONTROL_INTERFACE, CONTROL_WINDOW >::notifyModifiedValue(  ) throw (::com::sun::star::uno::RuntimeException)
306     {
307         m_aImplControl.notifyModifiedValue();
308     }
309 
310     //--------------------------------------------------------------------
311     template< class CONTROL_INTERFACE, class CONTROL_WINDOW >
312     inline void SAL_CALL CommonBehaviourControl< CONTROL_INTERFACE, CONTROL_WINDOW >::disposing()
313     {
314         m_aImplControl.dispose();
315     }
316 
317     //--------------------------------------------------------------------
318     template< class CONTROL_INTERFACE, class CONTROL_WINDOW >
319     inline void CommonBehaviourControl< CONTROL_INTERFACE, CONTROL_WINDOW >::modified()
320     {
321         m_aImplControl.setModified();
322     }
323 
324     //--------------------------------------------------------------------
325     template< class CONTROL_INTERFACE, class CONTROL_WINDOW >
326     inline void CommonBehaviourControl< CONTROL_INTERFACE, CONTROL_WINDOW >::impl_checkDisposed_throw()
327     {
328         if ( ComponentBaseClass::rBHelper.bDisposed )
329             throw ::com::sun::star::lang::DisposedException( ::rtl::OUString(), *this );
330     }
331 
332 //............................................................................
333 } // namespace pcr
334 //............................................................................
335 
336 #endif // _EXTENSIONS_PROPCTRLR_COMMONCONTROL_HXX_
337 
338