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