xref: /trunk/main/extensions/source/propctrlr/browserlistbox.cxx (revision cf6516809c57e1bb0a940545cca99cdad54d4ce2)
12a97ec55SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
32a97ec55SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
42a97ec55SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
52a97ec55SAndrew Rist  * distributed with this work for additional information
62a97ec55SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
72a97ec55SAndrew Rist  * to you under the Apache License, Version 2.0 (the
82a97ec55SAndrew Rist  * "License"); you may not use this file except in compliance
92a97ec55SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
112a97ec55SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
132a97ec55SAndrew Rist  * Unless required by applicable law or agreed to in writing,
142a97ec55SAndrew Rist  * software distributed under the License is distributed on an
152a97ec55SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
162a97ec55SAndrew Rist  * KIND, either express or implied.  See the License for the
172a97ec55SAndrew Rist  * specific language governing permissions and limitations
182a97ec55SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
202a97ec55SAndrew Rist  *************************************************************/
212a97ec55SAndrew Rist 
222a97ec55SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_extensions.hxx"
26cdf0e10cSrcweir #include "browserlistbox.hxx"
27cdf0e10cSrcweir #ifndef EXTENSIONS_PROPRESID_HRC
28cdf0e10cSrcweir #include "propresid.hrc"
29cdf0e10cSrcweir #endif
30cdf0e10cSrcweir #include "proplinelistener.hxx"
31cdf0e10cSrcweir #include "propcontrolobserver.hxx"
32cdf0e10cSrcweir #include "linedescriptor.hxx"
33cdf0e10cSrcweir #include "inspectorhelpwindow.hxx"
34cdf0e10cSrcweir 
35cdf0e10cSrcweir /** === begin UNO includes === **/
36cdf0e10cSrcweir #include <com/sun/star/lang/DisposedException.hpp>
37cdf0e10cSrcweir #include <com/sun/star/lang/XComponent.hpp>
38cdf0e10cSrcweir #include <com/sun/star/inspection/PropertyControlType.hpp>
39cdf0e10cSrcweir /** === end UNO includes === **/
40cdf0e10cSrcweir #include <tools/debug.hxx>
41cdf0e10cSrcweir #include <tools/diagnose_ex.h>
42cdf0e10cSrcweir #include <comphelper/asyncnotification.hxx>
43cdf0e10cSrcweir #include <cppuhelper/implbase1.hxx>
44cdf0e10cSrcweir #include <vcl/svapp.hxx>
45cdf0e10cSrcweir #include <vos/mutex.hxx>
46cdf0e10cSrcweir 
47cdf0e10cSrcweir //............................................................................
48cdf0e10cSrcweir namespace pcr
49cdf0e10cSrcweir {
50cdf0e10cSrcweir //............................................................................
51cdf0e10cSrcweir 
52cdf0e10cSrcweir     #define FRAME_OFFSET 4
53cdf0e10cSrcweir         // TODO: find out what this is really for ... and check if it does make sense in the new
54cdf0e10cSrcweir         // browser environment
55cdf0e10cSrcweir     #define LAYOUT_HELP_WINDOW_DISTANCE_APPFONT 3
56cdf0e10cSrcweir 
57cdf0e10cSrcweir     /** === begin UNO using === **/
58cdf0e10cSrcweir     using ::com::sun::star::uno::Any;
59cdf0e10cSrcweir     using ::com::sun::star::uno::Exception;
60cdf0e10cSrcweir     using ::com::sun::star::inspection::XPropertyControlContext;
61cdf0e10cSrcweir     using ::com::sun::star::uno::Reference;
62cdf0e10cSrcweir     using ::com::sun::star::inspection::XPropertyControl;
63cdf0e10cSrcweir     using ::com::sun::star::uno::RuntimeException;
64cdf0e10cSrcweir     using ::com::sun::star::lang::DisposedException;
65cdf0e10cSrcweir     using ::com::sun::star::lang::XComponent;
66cdf0e10cSrcweir     using ::com::sun::star::uno::UNO_QUERY;
67cdf0e10cSrcweir     using ::com::sun::star::graphic::XGraphic;
68cdf0e10cSrcweir     /** === end UNO using === **/
69cdf0e10cSrcweir     namespace PropertyControlType = ::com::sun::star::inspection::PropertyControlType;
70cdf0e10cSrcweir 
71cdf0e10cSrcweir     //==================================================================
72cdf0e10cSrcweir     //= ControlEvent
73cdf0e10cSrcweir     //==================================================================
74cdf0e10cSrcweir     enum ControlEventType
75cdf0e10cSrcweir     {
76cdf0e10cSrcweir         FOCUS_GAINED,
77cdf0e10cSrcweir         VALUE_CHANGED,
78cdf0e10cSrcweir         ACTIVATE_NEXT
79cdf0e10cSrcweir     };
80cdf0e10cSrcweir 
81cdf0e10cSrcweir     struct ControlEvent : public ::comphelper::AnyEvent
82cdf0e10cSrcweir     {
83cdf0e10cSrcweir         Reference< XPropertyControl >   xControl;
84cdf0e10cSrcweir         ControlEventType                eType;
85cdf0e10cSrcweir 
ControlEventpcr::ControlEvent86cdf0e10cSrcweir         ControlEvent( const Reference< XPropertyControl >& _rxControl, ControlEventType _eType )
87cdf0e10cSrcweir             :xControl( _rxControl )
88cdf0e10cSrcweir             ,eType( _eType )
89cdf0e10cSrcweir         {
90cdf0e10cSrcweir         }
91cdf0e10cSrcweir     };
92cdf0e10cSrcweir 
93cdf0e10cSrcweir     //==================================================================
94cdf0e10cSrcweir     //= SharedNotifier
95cdf0e10cSrcweir     //==================================================================
96cdf0e10cSrcweir     class SharedNotifier
97cdf0e10cSrcweir     {
98cdf0e10cSrcweir     private:
99cdf0e10cSrcweir         static ::osl::Mutex&                                        getMutex();
100cdf0e10cSrcweir         static ::rtl::Reference< ::comphelper::AsyncEventNotifier > s_pNotifier;
101cdf0e10cSrcweir 
102cdf0e10cSrcweir     public:
103cdf0e10cSrcweir         static const ::rtl::Reference< ::comphelper::AsyncEventNotifier >&
104cdf0e10cSrcweir             getNotifier();
105cdf0e10cSrcweir 
106cdf0e10cSrcweir     private:
107cdf0e10cSrcweir         SharedNotifier();                                   // never implemented
108cdf0e10cSrcweir         SharedNotifier( const SharedNotifier& );            // never implemented
109cdf0e10cSrcweir         SharedNotifier& operator=( const SharedNotifier& ); // never implemented
110cdf0e10cSrcweir     };
111cdf0e10cSrcweir 
112cdf0e10cSrcweir     //------------------------------------------------------------------
113cdf0e10cSrcweir     ::rtl::Reference< ::comphelper::AsyncEventNotifier > SharedNotifier::s_pNotifier;
114cdf0e10cSrcweir 
115cdf0e10cSrcweir     //------------------------------------------------------------------
getMutex()116cdf0e10cSrcweir     ::osl::Mutex& SharedNotifier::getMutex()
117cdf0e10cSrcweir     {
118cdf0e10cSrcweir         static ::osl::Mutex s_aMutex;
119cdf0e10cSrcweir         return s_aMutex;
120cdf0e10cSrcweir     }
121cdf0e10cSrcweir 
122cdf0e10cSrcweir     //------------------------------------------------------------------
getNotifier()123cdf0e10cSrcweir     const ::rtl::Reference< ::comphelper::AsyncEventNotifier >& SharedNotifier::getNotifier()
124cdf0e10cSrcweir     {
125cdf0e10cSrcweir         ::osl::MutexGuard aGuard( getMutex() );
126cdf0e10cSrcweir         if ( !s_pNotifier.is() )
127cdf0e10cSrcweir         {
128cdf0e10cSrcweir             s_pNotifier.set( new ::comphelper::AsyncEventNotifier );
129cdf0e10cSrcweir             s_pNotifier->create();
130cdf0e10cSrcweir         }
131cdf0e10cSrcweir         return s_pNotifier;
132cdf0e10cSrcweir     }
133cdf0e10cSrcweir 
134cdf0e10cSrcweir     //==================================================================
135cdf0e10cSrcweir     //= PropertyControlContext_Impl
136cdf0e10cSrcweir     //==================================================================
137cdf0e10cSrcweir     /** implementation for of <type scope="com::sun::star::inspection">XPropertyControlContext</type>
138cdf0e10cSrcweir         which forwards all events to a non-UNO version of this interface
139cdf0e10cSrcweir     */
140cdf0e10cSrcweir     typedef ::cppu::WeakImplHelper1< XPropertyControlContext > PropertyControlContext_Impl_Base;
141cdf0e10cSrcweir     class PropertyControlContext_Impl   :public PropertyControlContext_Impl_Base
142cdf0e10cSrcweir                                         ,public ::comphelper::IEventProcessor
143cdf0e10cSrcweir     {
144cdf0e10cSrcweir     public:
145cdf0e10cSrcweir         enum NotifcationMode
146cdf0e10cSrcweir         {
147cdf0e10cSrcweir             eSynchronously,
148cdf0e10cSrcweir             eAsynchronously
149cdf0e10cSrcweir         };
150cdf0e10cSrcweir 
151cdf0e10cSrcweir     private:
152cdf0e10cSrcweir         IControlContext*    m_pContext;
153cdf0e10cSrcweir         NotifcationMode     m_eMode;
154cdf0e10cSrcweir 
155cdf0e10cSrcweir     public:
156cdf0e10cSrcweir         /** creates an instance
157cdf0e10cSrcweir             @param _rContextImpl
158cdf0e10cSrcweir                 the instance to delegate events to
159cdf0e10cSrcweir         */
160cdf0e10cSrcweir         PropertyControlContext_Impl( IControlContext& _rContextImpl );
161cdf0e10cSrcweir 
162cdf0e10cSrcweir         /** disposes the context.
163cdf0e10cSrcweir 
164cdf0e10cSrcweir             When you call this method, all subsequent callbacks to the
165cdf0e10cSrcweir             <type scope="com::sun::star::inspection">XPropertyControlContext</type> methods
166cdf0e10cSrcweir             will throw a <type scope="com::sun::star::lang">DisposedException</type>.
167cdf0e10cSrcweir         */
168cdf0e10cSrcweir         void SAL_CALL dispose();
169cdf0e10cSrcweir 
170*07a3d7f1SPedro Giffuni         /** sets the notification mode, so that notifications received from the controls are
171cdf0e10cSrcweir             forwarded to our IControlContext either synchronously or asynchronously
172cdf0e10cSrcweir             @param  _eMode
173cdf0e10cSrcweir                 the new notification mode
174cdf0e10cSrcweir         */
175cdf0e10cSrcweir         void setNotificationMode( NotifcationMode _eMode );
176cdf0e10cSrcweir 
177cdf0e10cSrcweir         virtual void SAL_CALL acquire() throw();
178cdf0e10cSrcweir         virtual void SAL_CALL release() throw();
179cdf0e10cSrcweir 
180cdf0e10cSrcweir     protected:
181cdf0e10cSrcweir         ~PropertyControlContext_Impl();
182cdf0e10cSrcweir 
183cdf0e10cSrcweir         // XPropertyControlObserver
184cdf0e10cSrcweir         virtual void SAL_CALL focusGained( const Reference< XPropertyControl >& Control ) throw (RuntimeException);
185cdf0e10cSrcweir         virtual void SAL_CALL valueChanged( const Reference< XPropertyControl >& Control ) throw (RuntimeException);
186cdf0e10cSrcweir         // XPropertyControlContext
187cdf0e10cSrcweir         virtual void SAL_CALL activateNextControl( const Reference< XPropertyControl >& CurrentControl ) throw (RuntimeException);
188cdf0e10cSrcweir 
189cdf0e10cSrcweir         // IEventProcessor
190cdf0e10cSrcweir         virtual void processEvent( const ::comphelper::AnyEvent& _rEvent );
191cdf0e10cSrcweir 
192cdf0e10cSrcweir     private:
193cdf0e10cSrcweir         /** processes the given event, i.e. notifies it to our IControlContext
194cdf0e10cSrcweir             @param  _rEvent
195cdf0e10cSrcweir                 the event no notify
196cdf0e10cSrcweir             @precond
197cdf0e10cSrcweir                 our mutex (well, the SolarMutex) is locked
198cdf0e10cSrcweir         */
199cdf0e10cSrcweir         void impl_processEvent_throw( const ::comphelper::AnyEvent& _rEvent );
200cdf0e10cSrcweir 
201cdf0e10cSrcweir         /** checks whether we're alive
202cdf0e10cSrcweir 
203cdf0e10cSrcweir             @throws DisposedException
204cdf0e10cSrcweir                 if the instance is already disposed
205cdf0e10cSrcweir         */
206cdf0e10cSrcweir         void impl_checkAlive_throw() const;
207cdf0e10cSrcweir 
208cdf0e10cSrcweir         /** checks whether the instance is already disposed
209cdf0e10cSrcweir         */
impl_isDisposed_nothrow() const210cdf0e10cSrcweir         bool impl_isDisposed_nothrow() const { return m_pContext == NULL; }
211cdf0e10cSrcweir 
212cdf0e10cSrcweir         /** notifies the given event originating from the given control
213cdf0e10cSrcweir         @throws DisposedException
214cdf0e10cSrcweir         @param  _rxControl
215cdf0e10cSrcweir         @param  _eType
216cdf0e10cSrcweir         */
217cdf0e10cSrcweir         void impl_notify_throw( const Reference< XPropertyControl >& _rxControl, ControlEventType _eType );
218cdf0e10cSrcweir     };
219cdf0e10cSrcweir 
220cdf0e10cSrcweir     //--------------------------------------------------------------------
PropertyControlContext_Impl(IControlContext & _rContextImpl)221cdf0e10cSrcweir     PropertyControlContext_Impl::PropertyControlContext_Impl( IControlContext& _rContextImpl )
222cdf0e10cSrcweir         :m_pContext( &_rContextImpl )
223cdf0e10cSrcweir         ,m_eMode( eAsynchronously )
224cdf0e10cSrcweir     {
225cdf0e10cSrcweir     }
226cdf0e10cSrcweir 
227cdf0e10cSrcweir     //--------------------------------------------------------------------
~PropertyControlContext_Impl()228cdf0e10cSrcweir     PropertyControlContext_Impl::~PropertyControlContext_Impl()
229cdf0e10cSrcweir     {
230cdf0e10cSrcweir         if ( !impl_isDisposed_nothrow() )
231cdf0e10cSrcweir             dispose();
232cdf0e10cSrcweir     }
233cdf0e10cSrcweir 
234cdf0e10cSrcweir     //--------------------------------------------------------------------
impl_checkAlive_throw() const235cdf0e10cSrcweir     void PropertyControlContext_Impl::impl_checkAlive_throw() const
236cdf0e10cSrcweir     {
237cdf0e10cSrcweir         if ( impl_isDisposed_nothrow() )
238cdf0e10cSrcweir             throw DisposedException( ::rtl::OUString(), *const_cast< PropertyControlContext_Impl* >( this ) );
239cdf0e10cSrcweir     }
240cdf0e10cSrcweir 
241cdf0e10cSrcweir     //--------------------------------------------------------------------
dispose()242cdf0e10cSrcweir     void SAL_CALL PropertyControlContext_Impl::dispose()
243cdf0e10cSrcweir     {
244cdf0e10cSrcweir         ::vos::OGuard aGuard( Application::GetSolarMutex() );
245cdf0e10cSrcweir         if ( impl_isDisposed_nothrow() )
246cdf0e10cSrcweir             return;
247cdf0e10cSrcweir 
248cdf0e10cSrcweir         SharedNotifier::getNotifier()->removeEventsForProcessor( this );
249cdf0e10cSrcweir         m_pContext = NULL;
250cdf0e10cSrcweir     }
251cdf0e10cSrcweir 
252cdf0e10cSrcweir     //--------------------------------------------------------------------
setNotificationMode(NotifcationMode _eMode)253cdf0e10cSrcweir     void PropertyControlContext_Impl::setNotificationMode( NotifcationMode _eMode )
254cdf0e10cSrcweir     {
255cdf0e10cSrcweir         ::vos::OGuard aGuard( Application::GetSolarMutex() );
256cdf0e10cSrcweir         m_eMode = _eMode;
257cdf0e10cSrcweir     }
258cdf0e10cSrcweir 
259cdf0e10cSrcweir     //--------------------------------------------------------------------
impl_notify_throw(const Reference<XPropertyControl> & _rxControl,ControlEventType _eType)260cdf0e10cSrcweir     void PropertyControlContext_Impl::impl_notify_throw( const Reference< XPropertyControl >& _rxControl, ControlEventType _eType )
261cdf0e10cSrcweir     {
262cdf0e10cSrcweir         ::comphelper::AnyEventRef pEvent;
263cdf0e10cSrcweir 
264cdf0e10cSrcweir         {
265cdf0e10cSrcweir             ::vos::OGuard aGuard( Application::GetSolarMutex() );
266cdf0e10cSrcweir             impl_checkAlive_throw();
267cdf0e10cSrcweir             pEvent = new ControlEvent( _rxControl, _eType );
268cdf0e10cSrcweir 
269cdf0e10cSrcweir             if ( m_eMode == eSynchronously )
270cdf0e10cSrcweir             {
271cdf0e10cSrcweir                 impl_processEvent_throw( *pEvent );
272cdf0e10cSrcweir                 return;
273cdf0e10cSrcweir             }
274cdf0e10cSrcweir         }
275cdf0e10cSrcweir 
276cdf0e10cSrcweir         SharedNotifier::getNotifier()->addEvent( pEvent, this );
277cdf0e10cSrcweir     }
278cdf0e10cSrcweir 
279cdf0e10cSrcweir     //--------------------------------------------------------------------
focusGained(const Reference<XPropertyControl> & Control)280cdf0e10cSrcweir     void SAL_CALL PropertyControlContext_Impl::focusGained( const Reference< XPropertyControl >& Control ) throw (RuntimeException)
281cdf0e10cSrcweir     {
282cdf0e10cSrcweir         DBG_TRACE( "PropertyControlContext_Impl: FOCUS_GAINED" );
283cdf0e10cSrcweir         impl_notify_throw( Control, FOCUS_GAINED );
284cdf0e10cSrcweir     }
285cdf0e10cSrcweir 
286cdf0e10cSrcweir     //--------------------------------------------------------------------
valueChanged(const Reference<XPropertyControl> & Control)287cdf0e10cSrcweir     void SAL_CALL PropertyControlContext_Impl::valueChanged( const Reference< XPropertyControl >& Control ) throw (RuntimeException)
288cdf0e10cSrcweir     {
289cdf0e10cSrcweir         DBG_TRACE( "PropertyControlContext_Impl: VALUE_CHANGED" );
290cdf0e10cSrcweir         impl_notify_throw( Control, VALUE_CHANGED );
291cdf0e10cSrcweir     }
292cdf0e10cSrcweir 
293cdf0e10cSrcweir     //--------------------------------------------------------------------
activateNextControl(const Reference<XPropertyControl> & CurrentControl)294cdf0e10cSrcweir     void SAL_CALL PropertyControlContext_Impl::activateNextControl( const Reference< XPropertyControl >& CurrentControl ) throw (RuntimeException)
295cdf0e10cSrcweir     {
296cdf0e10cSrcweir         DBG_TRACE( "PropertyControlContext_Impl: ACTIVATE_NEXT" );
297cdf0e10cSrcweir         impl_notify_throw( CurrentControl, ACTIVATE_NEXT );
298cdf0e10cSrcweir     }
299cdf0e10cSrcweir 
300cdf0e10cSrcweir     //--------------------------------------------------------------------
acquire()301cdf0e10cSrcweir     void SAL_CALL PropertyControlContext_Impl::acquire() throw()
302cdf0e10cSrcweir     {
303cdf0e10cSrcweir         PropertyControlContext_Impl_Base::acquire();
304cdf0e10cSrcweir     }
305cdf0e10cSrcweir 
306cdf0e10cSrcweir     //--------------------------------------------------------------------
release()307cdf0e10cSrcweir     void SAL_CALL PropertyControlContext_Impl::release() throw()
308cdf0e10cSrcweir     {
309cdf0e10cSrcweir         PropertyControlContext_Impl_Base::release();
310cdf0e10cSrcweir     }
311cdf0e10cSrcweir 
312cdf0e10cSrcweir     //--------------------------------------------------------------------
processEvent(const::comphelper::AnyEvent & _rEvent)313cdf0e10cSrcweir     void PropertyControlContext_Impl::processEvent( const ::comphelper::AnyEvent& _rEvent )
314cdf0e10cSrcweir     {
315cdf0e10cSrcweir         ::vos::OGuard aGuard( Application::GetSolarMutex() );
316cdf0e10cSrcweir         if ( impl_isDisposed_nothrow() )
317cdf0e10cSrcweir             return;
318cdf0e10cSrcweir 
319cdf0e10cSrcweir         try
320cdf0e10cSrcweir         {
321cdf0e10cSrcweir             impl_processEvent_throw( _rEvent );
322cdf0e10cSrcweir         }
323cdf0e10cSrcweir         catch( const Exception& )
324cdf0e10cSrcweir         {
325cdf0e10cSrcweir             // can't handle otherwise, since our caller (the notification thread) does not allow
326cdf0e10cSrcweir             // for exceptions (it could itself abort only)
327cdf0e10cSrcweir             DBG_UNHANDLED_EXCEPTION();
328cdf0e10cSrcweir         }
329cdf0e10cSrcweir     }
330cdf0e10cSrcweir 
331cdf0e10cSrcweir     //--------------------------------------------------------------------
impl_processEvent_throw(const::comphelper::AnyEvent & _rEvent)332cdf0e10cSrcweir     void PropertyControlContext_Impl::impl_processEvent_throw( const ::comphelper::AnyEvent& _rEvent )
333cdf0e10cSrcweir     {
334cdf0e10cSrcweir         const ControlEvent& rControlEvent = static_cast< const ControlEvent& >( _rEvent );
335cdf0e10cSrcweir         switch ( rControlEvent.eType )
336cdf0e10cSrcweir         {
337cdf0e10cSrcweir         case FOCUS_GAINED:
338cdf0e10cSrcweir             DBG_TRACE( "PropertyControlContext_Impl::processEvent: FOCUS_GAINED" );
339cdf0e10cSrcweir             m_pContext->focusGained( rControlEvent.xControl );
340cdf0e10cSrcweir             break;
341cdf0e10cSrcweir         case VALUE_CHANGED:
342cdf0e10cSrcweir             DBG_TRACE( "PropertyControlContext_Impl::processEvent: VALUE_CHANGED" );
343cdf0e10cSrcweir             m_pContext->valueChanged( rControlEvent.xControl );
344cdf0e10cSrcweir             break;
345cdf0e10cSrcweir         case ACTIVATE_NEXT:
346cdf0e10cSrcweir             DBG_TRACE( "PropertyControlContext_Impl::processEvent: ACTIVATE_NEXT" );
347cdf0e10cSrcweir             m_pContext->activateNextControl( rControlEvent.xControl );
348cdf0e10cSrcweir             break;
349cdf0e10cSrcweir         }
350cdf0e10cSrcweir     }
351cdf0e10cSrcweir 
352cdf0e10cSrcweir     //==================================================================
353cdf0e10cSrcweir     //= OBrowserListBox
354cdf0e10cSrcweir     //==================================================================
DBG_NAME(OBrowserListBox)355cdf0e10cSrcweir     DBG_NAME(OBrowserListBox)
356cdf0e10cSrcweir     //------------------------------------------------------------------
357cdf0e10cSrcweir     OBrowserListBox::OBrowserListBox( Window* pParent, WinBits nWinStyle)
358cdf0e10cSrcweir             :Control(pParent, nWinStyle| WB_CLIPCHILDREN)
359cdf0e10cSrcweir             ,m_aLinesPlayground(this,WB_DIALOGCONTROL | WB_CLIPCHILDREN)
360cdf0e10cSrcweir             ,m_aVScroll(this,WB_VSCROLL|WB_REPEAT|WB_DRAG)
361cdf0e10cSrcweir             ,m_pHelpWindow( new InspectorHelpWindow( this ) )
362cdf0e10cSrcweir             ,m_pLineListener(NULL)
363cdf0e10cSrcweir             ,m_pControlObserver( NULL )
364cdf0e10cSrcweir             ,m_nYOffset(0)
365cdf0e10cSrcweir             ,m_nCurrentPreferredHelpHeight(0)
366cdf0e10cSrcweir             ,m_nTheNameSize(0)
367cdf0e10cSrcweir             ,m_bIsActive(sal_False)
368cdf0e10cSrcweir             ,m_bUpdate(sal_True)
369cdf0e10cSrcweir             ,m_pControlContextImpl( new PropertyControlContext_Impl( *this ) )
370cdf0e10cSrcweir     {
371cdf0e10cSrcweir         DBG_CTOR(OBrowserListBox,NULL);
372cdf0e10cSrcweir 
373cdf0e10cSrcweir         ListBox aListBox(this,WB_DROPDOWN);
374cdf0e10cSrcweir         aListBox.SetPosSizePixel(Point(0,0),Size(100,100));
375cdf0e10cSrcweir         m_nRowHeight = (sal_uInt16)aListBox.GetSizePixel().Height()+2;
376cdf0e10cSrcweir         SetBackground( pParent->GetBackground() );
377cdf0e10cSrcweir         m_aLinesPlayground.SetBackground( GetBackground() );
378cdf0e10cSrcweir 
379cdf0e10cSrcweir         m_aLinesPlayground.SetPosPixel(Point(0,0));
380cdf0e10cSrcweir         m_aLinesPlayground.SetPaintTransparent(sal_True);
381cdf0e10cSrcweir         m_aLinesPlayground.Show();
382cdf0e10cSrcweir         m_aVScroll.Hide();
383cdf0e10cSrcweir         m_aVScroll.SetScrollHdl(LINK(this, OBrowserListBox, ScrollHdl));
384cdf0e10cSrcweir     }
385cdf0e10cSrcweir 
386cdf0e10cSrcweir     //------------------------------------------------------------------
~OBrowserListBox()387cdf0e10cSrcweir     OBrowserListBox::~OBrowserListBox()
388cdf0e10cSrcweir     {
389cdf0e10cSrcweir         OSL_ENSURE( !IsModified(), "OBrowserListBox::~OBrowserListBox: still modified - should have been committed before!" );
390cdf0e10cSrcweir             // doing the commit here, while we, as well as our owner, as well as some other components,
391cdf0e10cSrcweir             // are already "half dead" (means within their dtor) is potentially dangerous.
392cdf0e10cSrcweir             // By definition, CommitModified has to be called (if necessary) before destruction
393cdf0e10cSrcweir             // #105868# - 2002-12-13 - fs@openoffice.org
394cdf0e10cSrcweir 
395cdf0e10cSrcweir         m_pControlContextImpl->dispose();
396cdf0e10cSrcweir         m_pControlContextImpl.clear();
397cdf0e10cSrcweir 
398cdf0e10cSrcweir         Hide();
399cdf0e10cSrcweir         Clear();
400cdf0e10cSrcweir 
401cdf0e10cSrcweir         DBG_DTOR(OBrowserListBox,NULL);
402cdf0e10cSrcweir     }
403cdf0e10cSrcweir 
404cdf0e10cSrcweir     //------------------------------------------------------------------
IsModified() const405cdf0e10cSrcweir     sal_Bool OBrowserListBox::IsModified( ) const
406cdf0e10cSrcweir     {
407cdf0e10cSrcweir         sal_Bool bModified = sal_False;
408cdf0e10cSrcweir 
409cdf0e10cSrcweir         if ( m_bIsActive && m_xActiveControl.is() )
410cdf0e10cSrcweir             bModified = m_xActiveControl->isModified();
411cdf0e10cSrcweir 
412cdf0e10cSrcweir         return bModified;
413cdf0e10cSrcweir     }
414cdf0e10cSrcweir 
415cdf0e10cSrcweir     //------------------------------------------------------------------
CommitModified()416cdf0e10cSrcweir     void OBrowserListBox::CommitModified( )
417cdf0e10cSrcweir     {
418cdf0e10cSrcweir         if ( IsModified() && m_xActiveControl.is() )
419cdf0e10cSrcweir         {
420cdf0e10cSrcweir             // for the time of this commit, notify all events synchronously
421cdf0e10cSrcweir             // #i63814# / 2006-03-31 / frank.schoenheit@sun.com
422cdf0e10cSrcweir             m_pControlContextImpl->setNotificationMode( PropertyControlContext_Impl::eSynchronously );
423cdf0e10cSrcweir             try
424cdf0e10cSrcweir             {
425cdf0e10cSrcweir                 m_xActiveControl->notifyModifiedValue();
426cdf0e10cSrcweir             }
427cdf0e10cSrcweir             catch( const Exception& )
428cdf0e10cSrcweir             {
429cdf0e10cSrcweir                 DBG_UNHANDLED_EXCEPTION();
430cdf0e10cSrcweir             }
431cdf0e10cSrcweir             m_pControlContextImpl->setNotificationMode( PropertyControlContext_Impl::eAsynchronously );
432cdf0e10cSrcweir         }
433cdf0e10cSrcweir     }
434cdf0e10cSrcweir 
435cdf0e10cSrcweir     //------------------------------------------------------------------
ActivateListBox(sal_Bool _bActive)436cdf0e10cSrcweir     void OBrowserListBox::ActivateListBox(sal_Bool _bActive)
437cdf0e10cSrcweir     {
438cdf0e10cSrcweir         m_bIsActive = _bActive;
439cdf0e10cSrcweir         if (m_bIsActive)
440cdf0e10cSrcweir         {
441cdf0e10cSrcweir             // TODO: what's the sense of this?
442cdf0e10cSrcweir             m_aVScroll.SetThumbPos(100);
443cdf0e10cSrcweir             MoveThumbTo(0);
444cdf0e10cSrcweir             Resize();
445cdf0e10cSrcweir         }
446cdf0e10cSrcweir     }
447cdf0e10cSrcweir 
448cdf0e10cSrcweir     //------------------------------------------------------------------
impl_getPrefererredHelpHeight()449cdf0e10cSrcweir     long OBrowserListBox::impl_getPrefererredHelpHeight()
450cdf0e10cSrcweir     {
451cdf0e10cSrcweir         return HasHelpSection() ? m_pHelpWindow->GetOptimalHeightPixel() : 0;
452cdf0e10cSrcweir     }
453cdf0e10cSrcweir 
454cdf0e10cSrcweir     //------------------------------------------------------------------
Resize()455cdf0e10cSrcweir     void OBrowserListBox::Resize()
456cdf0e10cSrcweir     {
457cdf0e10cSrcweir         Rectangle aPlayground( Point( 0, 0 ), GetOutputSizePixel() );
458cdf0e10cSrcweir         Size aHelpWindowDistance( LogicToPixel( Size( 0, LAYOUT_HELP_WINDOW_DISTANCE_APPFONT ), MAP_APPFONT ) );
459cdf0e10cSrcweir 
460cdf0e10cSrcweir         long nHelpWindowHeight = m_nCurrentPreferredHelpHeight = impl_getPrefererredHelpHeight();
461cdf0e10cSrcweir         bool bPositionHelpWindow = ( nHelpWindowHeight != 0 );
462cdf0e10cSrcweir 
463cdf0e10cSrcweir         Rectangle aLinesArea( aPlayground );
464cdf0e10cSrcweir         if ( bPositionHelpWindow )
465cdf0e10cSrcweir         {
466cdf0e10cSrcweir             aLinesArea.Bottom() -= nHelpWindowHeight;
467cdf0e10cSrcweir             aLinesArea.Bottom() -= aHelpWindowDistance.Height();
468cdf0e10cSrcweir         }
469cdf0e10cSrcweir         m_aLinesPlayground.SetPosSizePixel( aLinesArea.TopLeft(), aLinesArea.GetSize() );
470cdf0e10cSrcweir 
471cdf0e10cSrcweir         UpdateVScroll();
472cdf0e10cSrcweir 
473cdf0e10cSrcweir         sal_Bool bNeedScrollbar = m_aOrderedLines.size() > (sal_uInt32)CalcVisibleLines();
474cdf0e10cSrcweir         if ( !bNeedScrollbar )
475cdf0e10cSrcweir         {
476cdf0e10cSrcweir             if ( m_aVScroll.IsVisible() )
477cdf0e10cSrcweir                 m_aVScroll.Hide();
478cdf0e10cSrcweir             // scroll to top
479cdf0e10cSrcweir             m_nYOffset = 0;
480cdf0e10cSrcweir             m_aVScroll.SetThumbPos( 0 );
481cdf0e10cSrcweir         }
482cdf0e10cSrcweir         else
483cdf0e10cSrcweir         {
484cdf0e10cSrcweir             Size aVScrollSize( m_aVScroll.GetSizePixel() );
485cdf0e10cSrcweir 
486cdf0e10cSrcweir             // adjust the playground's width
487cdf0e10cSrcweir             aLinesArea.Right() -= aVScrollSize.Width();
488cdf0e10cSrcweir             m_aLinesPlayground.SetPosSizePixel( aLinesArea.TopLeft(), aLinesArea.GetSize() );
489cdf0e10cSrcweir 
490cdf0e10cSrcweir             // position the scrollbar
491cdf0e10cSrcweir             aVScrollSize.Height() = aLinesArea.GetHeight();
492cdf0e10cSrcweir             Point aVScrollPos( aLinesArea.GetWidth(), 0 );
493cdf0e10cSrcweir             m_aVScroll.SetPosSizePixel( aVScrollPos, aVScrollSize );
494cdf0e10cSrcweir         }
495cdf0e10cSrcweir 
496cdf0e10cSrcweir         for ( sal_uInt16 i = 0; i < m_aOrderedLines.size(); ++i )
497cdf0e10cSrcweir             m_aOutOfDateLines.insert( i );
498cdf0e10cSrcweir 
499cdf0e10cSrcweir         // repaint
500cdf0e10cSrcweir         EnablePaint(sal_False);
501cdf0e10cSrcweir         UpdatePlayGround();
502cdf0e10cSrcweir         EnablePaint(sal_True);
503cdf0e10cSrcweir 
504cdf0e10cSrcweir         // show the scrollbar
505cdf0e10cSrcweir         if ( bNeedScrollbar )
506cdf0e10cSrcweir             m_aVScroll.Show();
507cdf0e10cSrcweir 
508cdf0e10cSrcweir         // position the help window
509cdf0e10cSrcweir         if ( bPositionHelpWindow )
510cdf0e10cSrcweir         {
511cdf0e10cSrcweir             Rectangle aHelpArea( aPlayground );
512cdf0e10cSrcweir             aHelpArea.Top() = aLinesArea.Bottom() + aHelpWindowDistance.Height();
513cdf0e10cSrcweir             m_pHelpWindow->SetPosSizePixel( aHelpArea.TopLeft(), aHelpArea.GetSize() );
514cdf0e10cSrcweir         }
515cdf0e10cSrcweir     }
516cdf0e10cSrcweir 
517cdf0e10cSrcweir     //------------------------------------------------------------------
SetListener(IPropertyLineListener * _pListener)518cdf0e10cSrcweir     void OBrowserListBox::SetListener( IPropertyLineListener* _pListener )
519cdf0e10cSrcweir     {
520cdf0e10cSrcweir         m_pLineListener = _pListener;
521cdf0e10cSrcweir     }
522cdf0e10cSrcweir 
523cdf0e10cSrcweir     //------------------------------------------------------------------
SetObserver(IPropertyControlObserver * _pObserver)524cdf0e10cSrcweir     void OBrowserListBox::SetObserver( IPropertyControlObserver* _pObserver )
525cdf0e10cSrcweir     {
526cdf0e10cSrcweir         m_pControlObserver = _pObserver;
527cdf0e10cSrcweir     }
528cdf0e10cSrcweir 
529cdf0e10cSrcweir     //------------------------------------------------------------------
EnableHelpSection(bool _bEnable)530cdf0e10cSrcweir     void OBrowserListBox::EnableHelpSection( bool _bEnable )
531cdf0e10cSrcweir     {
532cdf0e10cSrcweir         m_pHelpWindow->Show( _bEnable );
533cdf0e10cSrcweir         Resize();
534cdf0e10cSrcweir     }
535cdf0e10cSrcweir 
536cdf0e10cSrcweir     //------------------------------------------------------------------
HasHelpSection() const537cdf0e10cSrcweir     bool OBrowserListBox::HasHelpSection() const
538cdf0e10cSrcweir     {
539cdf0e10cSrcweir         return m_pHelpWindow->IsVisible();
540cdf0e10cSrcweir     }
541cdf0e10cSrcweir 
542cdf0e10cSrcweir     //------------------------------------------------------------------
SetHelpText(const::rtl::OUString & _rHelpText)543cdf0e10cSrcweir     void OBrowserListBox::SetHelpText( const ::rtl::OUString& _rHelpText )
544cdf0e10cSrcweir     {
545cdf0e10cSrcweir         OSL_ENSURE( HasHelpSection(), "OBrowserListBox::SetHelpText: help section not visible!" );
546cdf0e10cSrcweir         m_pHelpWindow->SetText( _rHelpText );
547cdf0e10cSrcweir         if ( m_nCurrentPreferredHelpHeight != impl_getPrefererredHelpHeight() )
548cdf0e10cSrcweir             Resize();
549cdf0e10cSrcweir     }
550cdf0e10cSrcweir 
551cdf0e10cSrcweir     //------------------------------------------------------------------
SetHelpLineLimites(sal_Int32 _nMinLines,sal_Int32 _nMaxLines)552cdf0e10cSrcweir     void OBrowserListBox::SetHelpLineLimites( sal_Int32 _nMinLines, sal_Int32 _nMaxLines )
553cdf0e10cSrcweir     {
554cdf0e10cSrcweir         m_pHelpWindow->SetLimits( _nMinLines, _nMaxLines );
555cdf0e10cSrcweir     }
556cdf0e10cSrcweir 
557cdf0e10cSrcweir     //------------------------------------------------------------------
CalcVisibleLines()558cdf0e10cSrcweir     sal_uInt16 OBrowserListBox::CalcVisibleLines()
559cdf0e10cSrcweir     {
560cdf0e10cSrcweir         Size aSize(m_aLinesPlayground.GetOutputSizePixel());
561cdf0e10cSrcweir         sal_uInt16 nResult = 0;
562cdf0e10cSrcweir         if (0 != m_nRowHeight)
563cdf0e10cSrcweir             nResult = (sal_uInt16) aSize.Height()/m_nRowHeight;
564cdf0e10cSrcweir 
565cdf0e10cSrcweir         return nResult;
566cdf0e10cSrcweir     }
567cdf0e10cSrcweir 
568cdf0e10cSrcweir     //------------------------------------------------------------------
UpdateVScroll()569cdf0e10cSrcweir     void OBrowserListBox::UpdateVScroll()
570cdf0e10cSrcweir     {
571cdf0e10cSrcweir         sal_uInt16 nLines = CalcVisibleLines();
572cdf0e10cSrcweir         m_aVScroll.SetPageSize(nLines-1);
573cdf0e10cSrcweir         m_aVScroll.SetVisibleSize(nLines-1);
574cdf0e10cSrcweir 
575cdf0e10cSrcweir         size_t nCount = m_aLines.size();
576cdf0e10cSrcweir         if (nCount>0)
577cdf0e10cSrcweir         {
578cdf0e10cSrcweir             m_aVScroll.SetRange(Range(0,nCount-1));
579cdf0e10cSrcweir             m_nYOffset = -m_aVScroll.GetThumbPos()*m_nRowHeight;
580cdf0e10cSrcweir         }
581cdf0e10cSrcweir         else
582cdf0e10cSrcweir         {
583cdf0e10cSrcweir             m_aVScroll.SetRange(Range(0,0));
584cdf0e10cSrcweir             m_nYOffset = 0;
585cdf0e10cSrcweir         }
586cdf0e10cSrcweir     }
587cdf0e10cSrcweir 
588cdf0e10cSrcweir     //------------------------------------------------------------------
PositionLine(sal_uInt16 _nIndex)589cdf0e10cSrcweir     void OBrowserListBox::PositionLine( sal_uInt16 _nIndex )
590cdf0e10cSrcweir     {
591cdf0e10cSrcweir         Size aSize(m_aLinesPlayground.GetOutputSizePixel());
592cdf0e10cSrcweir         Point aPos(0, m_nYOffset);
593cdf0e10cSrcweir 
594cdf0e10cSrcweir         aSize.Height() = m_nRowHeight;
595cdf0e10cSrcweir 
596cdf0e10cSrcweir         aPos.Y() += _nIndex * m_nRowHeight;
597cdf0e10cSrcweir 
598cdf0e10cSrcweir         if ( _nIndex < m_aOrderedLines.size() )
599cdf0e10cSrcweir         {
600cdf0e10cSrcweir             m_aOrderedLines[ _nIndex ]->second.pLine->SetPosSizePixel( aPos, aSize );
601cdf0e10cSrcweir 
602cdf0e10cSrcweir             m_aOrderedLines[ _nIndex ]->second.pLine->SetTitleWidth( m_nTheNameSize + 2 * FRAME_OFFSET );
603cdf0e10cSrcweir 
604cdf0e10cSrcweir             // show the line if necessary
605cdf0e10cSrcweir             if ( !m_aOrderedLines[ _nIndex ]->second.pLine->IsVisible() )
606cdf0e10cSrcweir                 m_aOrderedLines[ _nIndex ]->second.pLine->Show();
607cdf0e10cSrcweir         }
608cdf0e10cSrcweir     }
609cdf0e10cSrcweir 
610cdf0e10cSrcweir     //------------------------------------------------------------------
UpdatePosNSize()611cdf0e10cSrcweir     void OBrowserListBox::UpdatePosNSize()
612cdf0e10cSrcweir     {
613cdf0e10cSrcweir         for  (  ::std::set< sal_uInt16 >::const_iterator aLoop = m_aOutOfDateLines.begin();
614cdf0e10cSrcweir                 aLoop != m_aOutOfDateLines.end();
615cdf0e10cSrcweir                 ++aLoop
616cdf0e10cSrcweir              )
617cdf0e10cSrcweir         {
618cdf0e10cSrcweir             DBG_ASSERT( *aLoop < m_aOrderedLines.size(), "OBrowserListBox::UpdatePosNSize: invalid line index!" );
619cdf0e10cSrcweir             if ( *aLoop < m_aOrderedLines.size() )
620cdf0e10cSrcweir                 PositionLine( *aLoop );
621cdf0e10cSrcweir         }
622cdf0e10cSrcweir         m_aOutOfDateLines.clear();
623cdf0e10cSrcweir     }
624cdf0e10cSrcweir 
625cdf0e10cSrcweir     //------------------------------------------------------------------
UpdatePlayGround()626cdf0e10cSrcweir     void OBrowserListBox::UpdatePlayGround()
627cdf0e10cSrcweir     {
628cdf0e10cSrcweir         sal_Int32 nThumbPos = m_aVScroll.GetThumbPos();
629cdf0e10cSrcweir         sal_Int32 nLines = CalcVisibleLines();
630cdf0e10cSrcweir 
631cdf0e10cSrcweir         sal_uInt16 nEnd = (sal_uInt16)(nThumbPos + nLines);
632cdf0e10cSrcweir         if (nEnd >= m_aOrderedLines.size())
633cdf0e10cSrcweir             nEnd = (sal_uInt16)m_aOrderedLines.size()-1;
634cdf0e10cSrcweir 
635cdf0e10cSrcweir         if ( !m_aOrderedLines.empty() )
636cdf0e10cSrcweir         {
637cdf0e10cSrcweir             for ( sal_uInt16 i = (sal_uInt16)nThumbPos; i <= nEnd; ++i )
638cdf0e10cSrcweir                 m_aOutOfDateLines.insert( i );
639cdf0e10cSrcweir             UpdatePosNSize();
640cdf0e10cSrcweir         }
641cdf0e10cSrcweir     }
642cdf0e10cSrcweir 
643cdf0e10cSrcweir     //------------------------------------------------------------------
UpdateAll()644cdf0e10cSrcweir     void OBrowserListBox::UpdateAll()
645cdf0e10cSrcweir     {
646cdf0e10cSrcweir         Resize();
647cdf0e10cSrcweir     }
648cdf0e10cSrcweir 
649cdf0e10cSrcweir     //------------------------------------------------------------------
DisableUpdate()650cdf0e10cSrcweir     void OBrowserListBox::DisableUpdate()
651cdf0e10cSrcweir     {
652cdf0e10cSrcweir         m_bUpdate = sal_False;
653cdf0e10cSrcweir     }
654cdf0e10cSrcweir 
655cdf0e10cSrcweir     //------------------------------------------------------------------
EnableUpdate()656cdf0e10cSrcweir     void OBrowserListBox::EnableUpdate()
657cdf0e10cSrcweir     {
658cdf0e10cSrcweir         m_bUpdate = sal_True;
659cdf0e10cSrcweir         UpdateAll();
660cdf0e10cSrcweir     }
661cdf0e10cSrcweir 
662cdf0e10cSrcweir     //------------------------------------------------------------------
SetPropertyValue(const::rtl::OUString & _rEntryName,const Any & _rValue,bool _bUnknownValue)663cdf0e10cSrcweir     void OBrowserListBox::SetPropertyValue(const ::rtl::OUString& _rEntryName, const Any& _rValue, bool _bUnknownValue )
664cdf0e10cSrcweir     {
665cdf0e10cSrcweir         ListBoxLines::iterator line = m_aLines.find( _rEntryName );
666cdf0e10cSrcweir         if ( line != m_aLines.end() )
667cdf0e10cSrcweir         {
668cdf0e10cSrcweir             if ( _bUnknownValue )
669cdf0e10cSrcweir             {
670cdf0e10cSrcweir                 Reference< XPropertyControl > xControl( line->second.pLine->getControl() );
671cdf0e10cSrcweir                 OSL_ENSURE( xControl.is(), "OBrowserListBox::SetPropertyValue: illegal control!" );
672cdf0e10cSrcweir                 if ( xControl.is() )
673cdf0e10cSrcweir                     xControl->setValue( Any() );
674cdf0e10cSrcweir             }
675cdf0e10cSrcweir             else
676cdf0e10cSrcweir                 impl_setControlAsPropertyValue( line->second, _rValue );
677cdf0e10cSrcweir         }
678cdf0e10cSrcweir     }
679cdf0e10cSrcweir 
680cdf0e10cSrcweir     //------------------------------------------------------------------------
GetPropertyPos(const::rtl::OUString & _rEntryName) const681cdf0e10cSrcweir     sal_uInt16 OBrowserListBox::GetPropertyPos( const ::rtl::OUString& _rEntryName ) const
682cdf0e10cSrcweir     {
683cdf0e10cSrcweir         sal_uInt16 nRet = LISTBOX_ENTRY_NOTFOUND;
684cdf0e10cSrcweir         for ( OrderedListBoxLines::const_iterator linePos = m_aOrderedLines.begin();
685cdf0e10cSrcweir               linePos != m_aOrderedLines.end();
686cdf0e10cSrcweir               ++linePos
687cdf0e10cSrcweir             )
688cdf0e10cSrcweir         {
689cdf0e10cSrcweir             if ( (*linePos)->first == _rEntryName )
690cdf0e10cSrcweir             {
691cdf0e10cSrcweir                 nRet = (sal_uInt16)( linePos - m_aOrderedLines.begin() );
692cdf0e10cSrcweir                 break;
693cdf0e10cSrcweir             }
694cdf0e10cSrcweir         }
695cdf0e10cSrcweir 
696cdf0e10cSrcweir         return nRet;
697cdf0e10cSrcweir     }
698cdf0e10cSrcweir 
699cdf0e10cSrcweir     //------------------------------------------------------------------------
impl_getBrowserLineForName(const::rtl::OUString & _rEntryName,BrowserLinePointer & _out_rpLine) const700cdf0e10cSrcweir     bool OBrowserListBox::impl_getBrowserLineForName( const ::rtl::OUString& _rEntryName, BrowserLinePointer& _out_rpLine ) const
701cdf0e10cSrcweir     {
702cdf0e10cSrcweir         ListBoxLines::const_iterator line = m_aLines.find( _rEntryName );
703cdf0e10cSrcweir         if ( line != m_aLines.end() )
704cdf0e10cSrcweir             _out_rpLine = line->second.pLine;
705cdf0e10cSrcweir         else
706cdf0e10cSrcweir             _out_rpLine.reset();
707cdf0e10cSrcweir         return ( NULL != _out_rpLine.get() );
708cdf0e10cSrcweir     }
709cdf0e10cSrcweir 
710cdf0e10cSrcweir     //------------------------------------------------------------------------
EnablePropertyControls(const::rtl::OUString & _rEntryName,sal_Int16 _nControls,bool _bEnable)711cdf0e10cSrcweir     void OBrowserListBox::EnablePropertyControls( const ::rtl::OUString& _rEntryName, sal_Int16 _nControls, bool _bEnable )
712cdf0e10cSrcweir     {
713cdf0e10cSrcweir         BrowserLinePointer pLine;
714cdf0e10cSrcweir         if ( impl_getBrowserLineForName( _rEntryName, pLine ) )
715cdf0e10cSrcweir             pLine->EnablePropertyControls( _nControls, _bEnable );
716cdf0e10cSrcweir     }
717cdf0e10cSrcweir 
718cdf0e10cSrcweir     //------------------------------------------------------------------------
EnablePropertyLine(const::rtl::OUString & _rEntryName,bool _bEnable)719cdf0e10cSrcweir     void OBrowserListBox::EnablePropertyLine( const ::rtl::OUString& _rEntryName, bool _bEnable )
720cdf0e10cSrcweir     {
721cdf0e10cSrcweir         BrowserLinePointer pLine;
722cdf0e10cSrcweir         if ( impl_getBrowserLineForName( _rEntryName, pLine ) )
723cdf0e10cSrcweir             pLine->EnablePropertyLine( _bEnable );
724cdf0e10cSrcweir     }
725cdf0e10cSrcweir 
726cdf0e10cSrcweir     //------------------------------------------------------------------------
GetPropertyControl(const::rtl::OUString & _rEntryName)727cdf0e10cSrcweir     Reference< XPropertyControl > OBrowserListBox::GetPropertyControl( const ::rtl::OUString& _rEntryName )
728cdf0e10cSrcweir     {
729cdf0e10cSrcweir         BrowserLinePointer pLine;
730cdf0e10cSrcweir         if ( impl_getBrowserLineForName( _rEntryName, pLine ) )
731cdf0e10cSrcweir             return pLine->getControl();
732cdf0e10cSrcweir         return NULL;
733cdf0e10cSrcweir     }
734cdf0e10cSrcweir 
735cdf0e10cSrcweir     //------------------------------------------------------------------
InsertEntry(const OLineDescriptor & _rPropertyData,sal_uInt16 _nPos)736cdf0e10cSrcweir     sal_uInt16 OBrowserListBox::InsertEntry(const OLineDescriptor& _rPropertyData, sal_uInt16 _nPos)
737cdf0e10cSrcweir     {
738cdf0e10cSrcweir         // create a new line
739cdf0e10cSrcweir         BrowserLinePointer pBrowserLine( new OBrowserLine( _rPropertyData.sName, &m_aLinesPlayground ) );
740cdf0e10cSrcweir 
741cdf0e10cSrcweir         ListBoxLine aNewLine( pBrowserLine, _rPropertyData.xPropertyHandler );
742cdf0e10cSrcweir         ::std::pair< ListBoxLines::iterator, bool > insertPoint =
743cdf0e10cSrcweir             m_aLines.insert( ListBoxLines::value_type( _rPropertyData.sName, aNewLine ) );
744cdf0e10cSrcweir         OSL_ENSURE( insertPoint.second, "OBrowserListBox::InsertEntry: already have another line for this name!" );
745cdf0e10cSrcweir 
746cdf0e10cSrcweir         sal_uInt16 nInsertPos = _nPos;
747cdf0e10cSrcweir         if ( nInsertPos > m_aOrderedLines.size() )
748cdf0e10cSrcweir             nInsertPos = EDITOR_LIST_APPEND;
749cdf0e10cSrcweir         if ( EDITOR_LIST_APPEND == nInsertPos )
750cdf0e10cSrcweir         {
751cdf0e10cSrcweir             nInsertPos = (sal_uInt16)m_aOrderedLines.size();
752cdf0e10cSrcweir             m_aOrderedLines.push_back( insertPoint.first );
753cdf0e10cSrcweir         }
754cdf0e10cSrcweir         else
755cdf0e10cSrcweir             m_aOrderedLines.insert( m_aOrderedLines.begin() + nInsertPos, insertPoint.first );
756cdf0e10cSrcweir 
757cdf0e10cSrcweir         pBrowserLine->SetTitleWidth(m_nTheNameSize);
758cdf0e10cSrcweir         if (m_bUpdate)
759cdf0e10cSrcweir         {
760cdf0e10cSrcweir             UpdateVScroll();
761cdf0e10cSrcweir             Invalidate();
762cdf0e10cSrcweir         }
763cdf0e10cSrcweir 
764cdf0e10cSrcweir         // initialize the entry
765cdf0e10cSrcweir         ChangeEntry(_rPropertyData, nInsertPos);
766cdf0e10cSrcweir 
767cdf0e10cSrcweir         // update the positions of possibly affected lines
768cdf0e10cSrcweir         sal_uInt16 nUpdatePos = nInsertPos;
769cdf0e10cSrcweir         while ( nUpdatePos < m_aOrderedLines.size() )
770cdf0e10cSrcweir             m_aOutOfDateLines.insert( nUpdatePos++ );
771cdf0e10cSrcweir         UpdatePosNSize( );
772cdf0e10cSrcweir 
773cdf0e10cSrcweir         return nInsertPos;
774cdf0e10cSrcweir     }
775cdf0e10cSrcweir 
776cdf0e10cSrcweir     //------------------------------------------------------------------
GetMinimumWidth()777cdf0e10cSrcweir     sal_Int32 OBrowserListBox::GetMinimumWidth()
778cdf0e10cSrcweir     {
779cdf0e10cSrcweir         return m_nTheNameSize + 2 * FRAME_OFFSET + (m_nRowHeight - 4) * 8;
780cdf0e10cSrcweir     }
781cdf0e10cSrcweir 
782cdf0e10cSrcweir     //------------------------------------------------------------------
GetMinimumHeight()783cdf0e10cSrcweir     sal_Int32 OBrowserListBox::GetMinimumHeight()
784cdf0e10cSrcweir     {
785cdf0e10cSrcweir         // assume that we want to display 5 rows, at least
786cdf0e10cSrcweir         sal_Int32 nMinHeight = m_nRowHeight * 5;
787cdf0e10cSrcweir 
788cdf0e10cSrcweir         if ( HasHelpSection() )
789cdf0e10cSrcweir         {
790cdf0e10cSrcweir             Size aHelpWindowDistance( LogicToPixel( Size( 0, LAYOUT_HELP_WINDOW_DISTANCE_APPFONT ), MAP_APPFONT ) );
791cdf0e10cSrcweir             nMinHeight += aHelpWindowDistance.Height();
792cdf0e10cSrcweir 
793cdf0e10cSrcweir             nMinHeight += m_pHelpWindow->GetMinimalHeightPixel();
794cdf0e10cSrcweir         }
795cdf0e10cSrcweir 
796cdf0e10cSrcweir         return nMinHeight;
797cdf0e10cSrcweir     }
798cdf0e10cSrcweir 
799cdf0e10cSrcweir     //------------------------------------------------------------------
ShowEntry(sal_uInt16 _nPos)800cdf0e10cSrcweir     void OBrowserListBox::ShowEntry(sal_uInt16 _nPos)
801cdf0e10cSrcweir     {
802cdf0e10cSrcweir         if ( _nPos < m_aOrderedLines.size() )
803cdf0e10cSrcweir         {
804cdf0e10cSrcweir             sal_Int32 nThumbPos = m_aVScroll.GetThumbPos();
805cdf0e10cSrcweir 
806cdf0e10cSrcweir             if (_nPos < nThumbPos)
807cdf0e10cSrcweir                 MoveThumbTo(_nPos);
808cdf0e10cSrcweir             else
809cdf0e10cSrcweir             {
810cdf0e10cSrcweir                 sal_Int32 nLines = CalcVisibleLines();
811cdf0e10cSrcweir                 if (_nPos >= nThumbPos + nLines)
812cdf0e10cSrcweir                     MoveThumbTo(_nPos - nLines + 1);
813cdf0e10cSrcweir             }
814cdf0e10cSrcweir         }
815cdf0e10cSrcweir 
816cdf0e10cSrcweir     }
817cdf0e10cSrcweir 
818cdf0e10cSrcweir     //------------------------------------------------------------------
MoveThumbTo(sal_Int32 _nNewThumbPos)819cdf0e10cSrcweir     void OBrowserListBox::MoveThumbTo(sal_Int32 _nNewThumbPos)
820cdf0e10cSrcweir     {
821cdf0e10cSrcweir         // disable painting to prevent flicker
822cdf0e10cSrcweir         m_aLinesPlayground.EnablePaint(sal_False);
823cdf0e10cSrcweir 
824cdf0e10cSrcweir         sal_Int32 nDelta = _nNewThumbPos - m_aVScroll.GetThumbPos();
825cdf0e10cSrcweir         // adjust the scrollbar
826cdf0e10cSrcweir         m_aVScroll.SetThumbPos(_nNewThumbPos);
827cdf0e10cSrcweir         sal_Int32 nThumbPos = _nNewThumbPos;
828cdf0e10cSrcweir 
829cdf0e10cSrcweir         m_nYOffset = -m_aVScroll.GetThumbPos() * m_nRowHeight;
830cdf0e10cSrcweir 
831cdf0e10cSrcweir         sal_Int32 nLines = CalcVisibleLines();
832cdf0e10cSrcweir         sal_uInt16 nEnd = (sal_uInt16)(nThumbPos + nLines);
833cdf0e10cSrcweir 
834cdf0e10cSrcweir         m_aLinesPlayground.Scroll(0, -nDelta * m_nRowHeight, SCROLL_CHILDREN);
835cdf0e10cSrcweir 
836cdf0e10cSrcweir         if (1 == nDelta)
837cdf0e10cSrcweir         {
838cdf0e10cSrcweir             // TODO: what's the sense of this two PositionLines? Why not just one call?
839cdf0e10cSrcweir             PositionLine(nEnd-1);
840cdf0e10cSrcweir             PositionLine(nEnd);
841cdf0e10cSrcweir         }
842cdf0e10cSrcweir         else if (-1 == nDelta)
843cdf0e10cSrcweir         {
844cdf0e10cSrcweir             PositionLine((sal_uInt16)nThumbPos);
845cdf0e10cSrcweir         }
846cdf0e10cSrcweir         else if (0 != nDelta)
847cdf0e10cSrcweir         {
848cdf0e10cSrcweir             UpdatePlayGround();
849cdf0e10cSrcweir         }
850cdf0e10cSrcweir 
851cdf0e10cSrcweir         m_aLinesPlayground.EnablePaint(sal_True);
852cdf0e10cSrcweir         m_aLinesPlayground.Invalidate(INVALIDATE_CHILDREN);
853cdf0e10cSrcweir     }
854cdf0e10cSrcweir 
855cdf0e10cSrcweir     //------------------------------------------------------------------
IMPL_LINK(OBrowserListBox,ScrollHdl,ScrollBar *,_pScrollBar)856cdf0e10cSrcweir     IMPL_LINK(OBrowserListBox, ScrollHdl, ScrollBar*, _pScrollBar )
857cdf0e10cSrcweir     {
858cdf0e10cSrcweir         DBG_ASSERT(_pScrollBar == &m_aVScroll, "OBrowserListBox::ScrollHdl: where does this come from?");
859cdf0e10cSrcweir         (void)_pScrollBar;
860cdf0e10cSrcweir 
861cdf0e10cSrcweir         // disable painting to prevent flicker
862cdf0e10cSrcweir         m_aLinesPlayground.EnablePaint(sal_False);
863cdf0e10cSrcweir 
864cdf0e10cSrcweir         sal_Int32 nThumbPos = m_aVScroll.GetThumbPos();
865cdf0e10cSrcweir 
866cdf0e10cSrcweir         sal_Int32 nDelta = m_aVScroll.GetDelta();
867cdf0e10cSrcweir         m_nYOffset = -nThumbPos * m_nRowHeight;
868cdf0e10cSrcweir 
869cdf0e10cSrcweir         sal_uInt16 nEnd = (sal_uInt16)(nThumbPos + CalcVisibleLines());
870cdf0e10cSrcweir 
871cdf0e10cSrcweir         m_aLinesPlayground.Scroll(0, -nDelta * m_nRowHeight, SCROLL_CHILDREN);
872cdf0e10cSrcweir 
873cdf0e10cSrcweir         if (1 == nDelta)
874cdf0e10cSrcweir         {
875cdf0e10cSrcweir             PositionLine(nEnd-1);
876cdf0e10cSrcweir             PositionLine(nEnd);
877cdf0e10cSrcweir         }
878cdf0e10cSrcweir         else if (nDelta==-1)
879cdf0e10cSrcweir         {
880cdf0e10cSrcweir             PositionLine((sal_uInt16)nThumbPos);
881cdf0e10cSrcweir         }
882cdf0e10cSrcweir         else if (nDelta!=0 || m_aVScroll.GetType() == SCROLL_DONTKNOW)
883cdf0e10cSrcweir         {
884cdf0e10cSrcweir             UpdatePlayGround();
885cdf0e10cSrcweir         }
886cdf0e10cSrcweir 
887cdf0e10cSrcweir         m_aLinesPlayground.EnablePaint(sal_True);
888cdf0e10cSrcweir         return 0;
889cdf0e10cSrcweir     }
890cdf0e10cSrcweir 
891cdf0e10cSrcweir     //------------------------------------------------------------------
buttonClicked(OBrowserLine * _pLine,sal_Bool _bPrimary)892cdf0e10cSrcweir     void OBrowserListBox::buttonClicked( OBrowserLine* _pLine, sal_Bool _bPrimary )
893cdf0e10cSrcweir     {
894cdf0e10cSrcweir         DBG_ASSERT( _pLine, "OBrowserListBox::buttonClicked: invalid browser line!" );
895cdf0e10cSrcweir         if ( _pLine && m_pLineListener )
896cdf0e10cSrcweir         {
897cdf0e10cSrcweir             m_pLineListener->Clicked( _pLine->GetEntryName(), _bPrimary );
898cdf0e10cSrcweir         }
899cdf0e10cSrcweir     }
900cdf0e10cSrcweir 
901cdf0e10cSrcweir     //------------------------------------------------------------------
impl_setControlAsPropertyValue(const ListBoxLine & _rLine,const Any & _rPropertyValue)902cdf0e10cSrcweir     void OBrowserListBox::impl_setControlAsPropertyValue( const ListBoxLine& _rLine, const Any& _rPropertyValue )
903cdf0e10cSrcweir     {
904cdf0e10cSrcweir         Reference< XPropertyControl > xControl( _rLine.pLine->getControl() );
905cdf0e10cSrcweir         try
906cdf0e10cSrcweir         {
907cdf0e10cSrcweir             if ( _rPropertyValue.getValueType().equals( _rLine.pLine->getControl()->getValueType() ) )
908cdf0e10cSrcweir             {
909cdf0e10cSrcweir                 xControl->setValue( _rPropertyValue );
910cdf0e10cSrcweir             }
911cdf0e10cSrcweir             else
912cdf0e10cSrcweir             {
913cdf0e10cSrcweir     #ifdef DBG_UTIL
914cdf0e10cSrcweir                 if ( !_rLine.xHandler.is() )
915cdf0e10cSrcweir                 {
916cdf0e10cSrcweir                     ::rtl::OString sMessage( "OBrowserListBox::impl_setControlAsPropertyValue: no handler -> no conversion (property: '" );
917cdf0e10cSrcweir                     ::rtl::OUString sPropertyName( _rLine.pLine->GetEntryName() );
918cdf0e10cSrcweir                     sMessage += ::rtl::OString( sPropertyName.getStr(), sPropertyName.getLength(), RTL_TEXTENCODING_ASCII_US );
919cdf0e10cSrcweir                     sMessage += ::rtl::OString( "')!" );
920cdf0e10cSrcweir                     DBG_ERROR( sMessage );
921cdf0e10cSrcweir                 }
922cdf0e10cSrcweir     #endif
923cdf0e10cSrcweir                 if ( _rLine.xHandler.is() )
924cdf0e10cSrcweir                 {
925cdf0e10cSrcweir                     Any aControlValue = _rLine.xHandler->convertToControlValue(
926cdf0e10cSrcweir                         _rLine.pLine->GetEntryName(), _rPropertyValue, xControl->getValueType() );
927cdf0e10cSrcweir                     xControl->setValue( aControlValue );
928cdf0e10cSrcweir                 }
929cdf0e10cSrcweir             }
930cdf0e10cSrcweir         }
931cdf0e10cSrcweir         catch( const Exception& )
932cdf0e10cSrcweir         {
933cdf0e10cSrcweir             DBG_UNHANDLED_EXCEPTION();
934cdf0e10cSrcweir         }
935cdf0e10cSrcweir     }
936cdf0e10cSrcweir 
937cdf0e10cSrcweir     //------------------------------------------------------------------
impl_getControlAsPropertyValue(const ListBoxLine & _rLine) const938cdf0e10cSrcweir     Any OBrowserListBox::impl_getControlAsPropertyValue( const ListBoxLine& _rLine ) const
939cdf0e10cSrcweir     {
940cdf0e10cSrcweir         Reference< XPropertyControl > xControl( _rLine.pLine->getControl() );
941cdf0e10cSrcweir         Any aPropertyValue;
942cdf0e10cSrcweir         try
943cdf0e10cSrcweir         {
944cdf0e10cSrcweir         #ifdef DBG_UTIL
945cdf0e10cSrcweir             if ( !_rLine.xHandler.is() )
946cdf0e10cSrcweir             {
947cdf0e10cSrcweir                 ::rtl::OString sMessage( "OBrowserListBox::impl_getControlAsPropertyValue: no handler -> no conversion (property: '" );
948cdf0e10cSrcweir                 ::rtl::OUString sPropertyName( _rLine.pLine->GetEntryName() );
949cdf0e10cSrcweir                 sMessage += ::rtl::OString( sPropertyName.getStr(), sPropertyName.getLength(), RTL_TEXTENCODING_ASCII_US );
950cdf0e10cSrcweir                 sMessage += ::rtl::OString( "')!" );
951cdf0e10cSrcweir                 DBG_ERROR( sMessage );
952cdf0e10cSrcweir             }
953cdf0e10cSrcweir         #endif
954cdf0e10cSrcweir             if ( _rLine.xHandler.is() )
955cdf0e10cSrcweir                 aPropertyValue = _rLine.xHandler->convertToPropertyValue( _rLine.pLine->GetEntryName(), xControl->getValue() );
956cdf0e10cSrcweir             else
957cdf0e10cSrcweir                 aPropertyValue = xControl->getValue();
958cdf0e10cSrcweir         }
959cdf0e10cSrcweir         catch( const Exception& )
960cdf0e10cSrcweir         {
961cdf0e10cSrcweir             DBG_UNHANDLED_EXCEPTION();
962cdf0e10cSrcweir         }
963cdf0e10cSrcweir         return aPropertyValue;
964cdf0e10cSrcweir     }
965cdf0e10cSrcweir 
966cdf0e10cSrcweir     //------------------------------------------------------------------
impl_getControlPos(const Reference<XPropertyControl> & _rxControl) const967cdf0e10cSrcweir     sal_uInt16 OBrowserListBox::impl_getControlPos( const Reference< XPropertyControl >& _rxControl ) const
968cdf0e10cSrcweir     {
969cdf0e10cSrcweir         for (   OrderedListBoxLines::const_iterator search = m_aOrderedLines.begin();
970cdf0e10cSrcweir                 search != m_aOrderedLines.end();
971cdf0e10cSrcweir                 ++search
972cdf0e10cSrcweir             )
973cdf0e10cSrcweir             if ( (*search)->second.pLine->getControl().get() == _rxControl.get() )
974cdf0e10cSrcweir                 return sal_uInt16( search - m_aOrderedLines.begin() );
975cdf0e10cSrcweir         DBG_ERROR( "OBrowserListBox::impl_getControlPos: invalid control - not part of any of our lines!" );
976cdf0e10cSrcweir         return (sal_uInt16)-1;
977cdf0e10cSrcweir     }
978cdf0e10cSrcweir 
979cdf0e10cSrcweir     //--------------------------------------------------------------------
focusGained(const Reference<XPropertyControl> & _rxControl)980cdf0e10cSrcweir     void SAL_CALL OBrowserListBox::focusGained( const Reference< XPropertyControl >& _rxControl ) throw (RuntimeException)
981cdf0e10cSrcweir     {
982cdf0e10cSrcweir         DBG_TESTSOLARMUTEX();
983cdf0e10cSrcweir 
984cdf0e10cSrcweir         DBG_ASSERT( _rxControl.is(), "OBrowserListBox::focusGained: invalid event source!" );
985cdf0e10cSrcweir         if ( !_rxControl.is() )
986cdf0e10cSrcweir             return;
987cdf0e10cSrcweir 
988cdf0e10cSrcweir         if ( m_pControlObserver )
989cdf0e10cSrcweir             m_pControlObserver->focusGained( _rxControl );
990cdf0e10cSrcweir 
991cdf0e10cSrcweir         m_xActiveControl = _rxControl;
992cdf0e10cSrcweir         ShowEntry( impl_getControlPos( m_xActiveControl ) );
993cdf0e10cSrcweir     }
994cdf0e10cSrcweir 
995cdf0e10cSrcweir     //--------------------------------------------------------------------
valueChanged(const Reference<XPropertyControl> & _rxControl)996cdf0e10cSrcweir     void SAL_CALL OBrowserListBox::valueChanged( const Reference< XPropertyControl >& _rxControl ) throw (RuntimeException)
997cdf0e10cSrcweir     {
998cdf0e10cSrcweir         DBG_TESTSOLARMUTEX();
999cdf0e10cSrcweir 
1000cdf0e10cSrcweir         DBG_ASSERT( _rxControl.is(), "OBrowserListBox::valueChanged: invalid event source!" );
1001cdf0e10cSrcweir         if ( !_rxControl.is() )
1002cdf0e10cSrcweir             return;
1003cdf0e10cSrcweir 
1004cdf0e10cSrcweir         if ( m_pControlObserver )
1005cdf0e10cSrcweir             m_pControlObserver->valueChanged( _rxControl );
1006cdf0e10cSrcweir 
1007cdf0e10cSrcweir         if ( m_pLineListener )
1008cdf0e10cSrcweir         {
1009cdf0e10cSrcweir             const ListBoxLine& rLine = impl_getControlLine( _rxControl );
1010cdf0e10cSrcweir             m_pLineListener->Commit(
1011cdf0e10cSrcweir                 rLine.pLine->GetEntryName(),
1012cdf0e10cSrcweir                 impl_getControlAsPropertyValue( rLine )
1013cdf0e10cSrcweir             );
1014cdf0e10cSrcweir         }
1015cdf0e10cSrcweir     }
1016cdf0e10cSrcweir 
1017cdf0e10cSrcweir     //--------------------------------------------------------------------
activateNextControl(const Reference<XPropertyControl> & _rxCurrentControl)1018cdf0e10cSrcweir     void SAL_CALL OBrowserListBox::activateNextControl( const Reference< XPropertyControl >& _rxCurrentControl ) throw (RuntimeException)
1019cdf0e10cSrcweir     {
1020cdf0e10cSrcweir         DBG_TESTSOLARMUTEX();
1021cdf0e10cSrcweir 
1022cdf0e10cSrcweir         sal_uInt16 nLine = impl_getControlPos( _rxCurrentControl );
1023cdf0e10cSrcweir 
1024cdf0e10cSrcweir         // cycle forwards, 'til we've the next control which can grab the focus
1025cdf0e10cSrcweir         ++nLine;
1026cdf0e10cSrcweir         while ( (size_t)nLine < m_aOrderedLines.size() )
1027cdf0e10cSrcweir         {
1028cdf0e10cSrcweir             if ( m_aOrderedLines[nLine]->second.pLine->GrabFocus() )
1029cdf0e10cSrcweir                 break;
1030cdf0e10cSrcweir             ++nLine;
1031cdf0e10cSrcweir         }
1032cdf0e10cSrcweir 
1033cdf0e10cSrcweir         if  (   ( (size_t)nLine >= m_aOrderedLines.size() )
1034cdf0e10cSrcweir             &&  ( m_aOrderedLines.size() > 0 )
1035cdf0e10cSrcweir             )
1036cdf0e10cSrcweir             // wrap around
1037cdf0e10cSrcweir             m_aOrderedLines[0]->second.pLine->GrabFocus();
1038cdf0e10cSrcweir     }
1039cdf0e10cSrcweir 
1040cdf0e10cSrcweir     //------------------------------------------------------------------
1041cdf0e10cSrcweir     namespace
1042cdf0e10cSrcweir     {
1043cdf0e10cSrcweir         //..............................................................
lcl_implDisposeControl_nothrow(const Reference<XPropertyControl> & _rxControl)1044cdf0e10cSrcweir         void lcl_implDisposeControl_nothrow( const Reference< XPropertyControl >& _rxControl )
1045cdf0e10cSrcweir         {
1046cdf0e10cSrcweir             if ( !_rxControl.is() )
1047cdf0e10cSrcweir                 return;
1048cdf0e10cSrcweir             try
1049cdf0e10cSrcweir             {
1050cdf0e10cSrcweir                 _rxControl->setControlContext( NULL );
1051cdf0e10cSrcweir                 Reference< XComponent > xControlComponent( _rxControl, UNO_QUERY );
1052cdf0e10cSrcweir                 if ( xControlComponent.is() )
1053cdf0e10cSrcweir                     xControlComponent->dispose();
1054cdf0e10cSrcweir             }
1055cdf0e10cSrcweir             catch( const Exception& )
1056cdf0e10cSrcweir             {
1057cdf0e10cSrcweir                 DBG_UNHANDLED_EXCEPTION();
1058cdf0e10cSrcweir             }
1059cdf0e10cSrcweir         }
1060cdf0e10cSrcweir     }
1061cdf0e10cSrcweir 
1062cdf0e10cSrcweir     //------------------------------------------------------------------
Clear()1063cdf0e10cSrcweir     void OBrowserListBox::Clear()
1064cdf0e10cSrcweir     {
1065cdf0e10cSrcweir         for (   ListBoxLines::iterator loop = m_aLines.begin();
1066cdf0e10cSrcweir                 loop != m_aLines.end();
1067cdf0e10cSrcweir                 ++loop
1068cdf0e10cSrcweir             )
1069cdf0e10cSrcweir         {
1070cdf0e10cSrcweir             // hide the line
1071cdf0e10cSrcweir             loop->second.pLine->Hide();
1072cdf0e10cSrcweir             // reset the listener
1073cdf0e10cSrcweir             lcl_implDisposeControl_nothrow( loop->second.pLine->getControl() );
1074cdf0e10cSrcweir         }
1075cdf0e10cSrcweir 
1076cdf0e10cSrcweir         clearContainer( m_aLines );
1077cdf0e10cSrcweir         clearContainer( m_aOrderedLines );
1078cdf0e10cSrcweir     }
1079cdf0e10cSrcweir 
1080cdf0e10cSrcweir     //------------------------------------------------------------------
RemoveEntry(const::rtl::OUString & _rName)1081cdf0e10cSrcweir     sal_Bool OBrowserListBox::RemoveEntry( const ::rtl::OUString& _rName )
1082cdf0e10cSrcweir     {
1083cdf0e10cSrcweir         sal_uInt16 nPos = GetPropertyPos( _rName );
1084cdf0e10cSrcweir         if ( nPos == LISTBOX_ENTRY_NOTFOUND )
1085cdf0e10cSrcweir             return sal_False;
1086cdf0e10cSrcweir 
1087cdf0e10cSrcweir         OrderedListBoxLines::iterator orderedPos = m_aOrderedLines.begin() + nPos;
1088cdf0e10cSrcweir         BrowserLinePointer pLine = (*orderedPos)->second.pLine;
1089cdf0e10cSrcweir         pLine->Hide();
1090cdf0e10cSrcweir         lcl_implDisposeControl_nothrow( pLine->getControl() );
1091cdf0e10cSrcweir 
1092cdf0e10cSrcweir         m_aLines.erase( *orderedPos );
1093cdf0e10cSrcweir         m_aOrderedLines.erase( orderedPos );
1094cdf0e10cSrcweir         m_aOutOfDateLines.erase( (sal_uInt16)m_aOrderedLines.size() );
1095cdf0e10cSrcweir             // this index *may* have been out of date, which is obsoleted now by m_aOrderedLines shrinking
1096cdf0e10cSrcweir 
1097cdf0e10cSrcweir         // update the positions of possibly affected lines
1098cdf0e10cSrcweir         while ( nPos < m_aOrderedLines.size() )
1099cdf0e10cSrcweir             m_aOutOfDateLines.insert( nPos++ );
1100cdf0e10cSrcweir         UpdatePosNSize( );
1101cdf0e10cSrcweir 
1102cdf0e10cSrcweir         return sal_True;
1103cdf0e10cSrcweir     }
1104cdf0e10cSrcweir 
1105cdf0e10cSrcweir     //------------------------------------------------------------------
ChangeEntry(const OLineDescriptor & _rPropertyData,sal_uInt16 nPos)1106cdf0e10cSrcweir     void OBrowserListBox::ChangeEntry( const OLineDescriptor& _rPropertyData, sal_uInt16 nPos )
1107cdf0e10cSrcweir     {
1108cdf0e10cSrcweir         OSL_PRECOND( _rPropertyData.Control.is(), "OBrowserListBox::ChangeEntry: invalid control!" );
1109cdf0e10cSrcweir         if ( !_rPropertyData.Control.is() )
1110cdf0e10cSrcweir             return;
1111cdf0e10cSrcweir 
1112cdf0e10cSrcweir         if ( nPos == EDITOR_LIST_REPLACE_EXISTING )
1113cdf0e10cSrcweir             nPos = GetPropertyPos( _rPropertyData.sName );
1114cdf0e10cSrcweir 
1115cdf0e10cSrcweir         if ( nPos < m_aOrderedLines.size() )
1116cdf0e10cSrcweir         {
1117cdf0e10cSrcweir             Window* pRefWindow = NULL;
1118cdf0e10cSrcweir             if ( nPos > 0 )
1119cdf0e10cSrcweir                 pRefWindow = m_aOrderedLines[nPos-1]->second.pLine->GetRefWindow();
1120cdf0e10cSrcweir 
1121cdf0e10cSrcweir             // the current line and control
1122cdf0e10cSrcweir             ListBoxLine& rLine = m_aOrderedLines[nPos]->second;
1123cdf0e10cSrcweir 
1124cdf0e10cSrcweir             // the old control and some data about it
1125cdf0e10cSrcweir             Reference< XPropertyControl > xControl = rLine.pLine->getControl();
1126cdf0e10cSrcweir             Window* pControlWindow = rLine.pLine->getControlWindow();
1127cdf0e10cSrcweir             Point aControlPos;
1128cdf0e10cSrcweir             if ( pControlWindow )
1129cdf0e10cSrcweir                 aControlPos = pControlWindow->GetPosPixel();
1130cdf0e10cSrcweir 
1131cdf0e10cSrcweir             // clean up the old control
1132cdf0e10cSrcweir             lcl_implDisposeControl_nothrow( xControl );
1133cdf0e10cSrcweir 
1134cdf0e10cSrcweir             // set the new control at the line
1135cdf0e10cSrcweir             rLine.pLine->setControl( _rPropertyData.Control );
1136cdf0e10cSrcweir             xControl = rLine.pLine->getControl();
1137cdf0e10cSrcweir 
1138cdf0e10cSrcweir             if ( xControl.is() )
1139cdf0e10cSrcweir                 xControl->setControlContext( m_pControlContextImpl.get() );
1140cdf0e10cSrcweir 
1141cdf0e10cSrcweir             // the initial property value
1142cdf0e10cSrcweir             if ( _rPropertyData.bUnknownValue )
1143cdf0e10cSrcweir                 xControl->setValue( Any() );
1144cdf0e10cSrcweir             else
1145cdf0e10cSrcweir                 impl_setControlAsPropertyValue( rLine, _rPropertyData.aValue );
1146cdf0e10cSrcweir 
1147cdf0e10cSrcweir             rLine.pLine->SetTitle(_rPropertyData.DisplayName);
1148cdf0e10cSrcweir             rLine.xHandler = _rPropertyData.xPropertyHandler;
1149cdf0e10cSrcweir 
1150cdf0e10cSrcweir             sal_uInt16 nTextWidth = (sal_uInt16)m_aLinesPlayground.GetTextWidth(_rPropertyData.DisplayName);
1151cdf0e10cSrcweir             if (m_nTheNameSize< nTextWidth)
1152cdf0e10cSrcweir                 m_nTheNameSize = nTextWidth;
1153cdf0e10cSrcweir 
1154cdf0e10cSrcweir             if ( _rPropertyData.HasPrimaryButton )
1155cdf0e10cSrcweir             {
1156cdf0e10cSrcweir                 if ( _rPropertyData.PrimaryButtonImageURL.getLength() )
1157cdf0e10cSrcweir                     rLine.pLine->ShowBrowseButton( _rPropertyData.PrimaryButtonImageURL, true );
1158cdf0e10cSrcweir                 else if ( _rPropertyData.PrimaryButtonImage.is() )
1159cdf0e10cSrcweir                     rLine.pLine->ShowBrowseButton( Image( _rPropertyData.PrimaryButtonImage ), true );
1160cdf0e10cSrcweir                 else
1161cdf0e10cSrcweir                     rLine.pLine->ShowBrowseButton( true );
1162cdf0e10cSrcweir 
1163cdf0e10cSrcweir                 if ( _rPropertyData.HasSecondaryButton )
1164cdf0e10cSrcweir                 {
1165cdf0e10cSrcweir                     if ( _rPropertyData.SecondaryButtonImageURL.getLength() )
1166cdf0e10cSrcweir                         rLine.pLine->ShowBrowseButton( _rPropertyData.SecondaryButtonImageURL, false );
1167cdf0e10cSrcweir                     else if ( _rPropertyData.SecondaryButtonImage.is() )
1168cdf0e10cSrcweir                         rLine.pLine->ShowBrowseButton( Image( _rPropertyData.SecondaryButtonImage ), false );
1169cdf0e10cSrcweir                     else
1170cdf0e10cSrcweir                         rLine.pLine->ShowBrowseButton( false );
1171cdf0e10cSrcweir                 }
1172cdf0e10cSrcweir                 else
1173cdf0e10cSrcweir                     rLine.pLine->HideBrowseButton( false );
1174cdf0e10cSrcweir 
1175cdf0e10cSrcweir                 rLine.pLine->SetClickListener( this );
1176cdf0e10cSrcweir             }
1177cdf0e10cSrcweir             else
1178cdf0e10cSrcweir             {
1179cdf0e10cSrcweir                 rLine.pLine->HideBrowseButton( true );
1180cdf0e10cSrcweir                 rLine.pLine->HideBrowseButton( false );
1181cdf0e10cSrcweir             }
1182cdf0e10cSrcweir 
1183cdf0e10cSrcweir             DBG_ASSERT( ( _rPropertyData.IndentLevel == 0 ) || ( _rPropertyData.IndentLevel == 1 ),
1184cdf0e10cSrcweir                 "OBrowserListBox::ChangeEntry: unsupported indent level!" );
1185cdf0e10cSrcweir             rLine.pLine->IndentTitle( _rPropertyData.IndentLevel > 0 );
1186cdf0e10cSrcweir 
1187cdf0e10cSrcweir             if ( nPos > 0 )
1188cdf0e10cSrcweir                 rLine.pLine->SetTabOrder( pRefWindow, WINDOW_ZORDER_BEHIND );
1189cdf0e10cSrcweir             else
1190cdf0e10cSrcweir                 rLine.pLine->SetTabOrder( pRefWindow, WINDOW_ZORDER_FIRST );
1191cdf0e10cSrcweir 
1192cdf0e10cSrcweir             m_aOutOfDateLines.insert( nPos );
1193cdf0e10cSrcweir             rLine.pLine->SetComponentHelpIds(
1194cdf0e10cSrcweir                 HelpIdUrl::getHelpId( _rPropertyData.HelpURL ),
1195cdf0e10cSrcweir                 rtl::OUStringToOString( _rPropertyData.PrimaryButtonId, RTL_TEXTENCODING_UTF8 ),
1196cdf0e10cSrcweir                 rtl::OUStringToOString( _rPropertyData.SecondaryButtonId, RTL_TEXTENCODING_UTF8 )
1197cdf0e10cSrcweir             );
1198cdf0e10cSrcweir 
1199cdf0e10cSrcweir             if ( _rPropertyData.bReadOnly )
1200cdf0e10cSrcweir             {
1201cdf0e10cSrcweir                 rLine.pLine->SetReadOnly( true );
1202cdf0e10cSrcweir 
1203cdf0e10cSrcweir                 // user controls (i.e. the ones not provided by the usual
1204cdf0e10cSrcweir                 // XPropertyControlFactory) have no chance to know that they should be read-only,
1205cdf0e10cSrcweir                 // since XPropertyHandler::describePropertyLine does not transport this
1206cdf0e10cSrcweir                 // information.
1207cdf0e10cSrcweir                 // So, we manually switch this to read-only.
1208cdf0e10cSrcweir                 if ( xControl.is() && ( xControl->getControlType() == PropertyControlType::Unknown ) )
1209cdf0e10cSrcweir                 {
1210cdf0e10cSrcweir                     Edit* pControlWindowAsEdit = dynamic_cast< Edit* >( rLine.pLine->getControlWindow() );
1211cdf0e10cSrcweir                     if ( pControlWindowAsEdit )
1212cdf0e10cSrcweir                         pControlWindowAsEdit->SetReadOnly( sal_True );
1213cdf0e10cSrcweir                     else
1214cdf0e10cSrcweir                         pControlWindowAsEdit->Enable( sal_False );
1215cdf0e10cSrcweir                 }
1216cdf0e10cSrcweir             }
1217cdf0e10cSrcweir         }
1218cdf0e10cSrcweir     }
1219cdf0e10cSrcweir 
1220cdf0e10cSrcweir     //------------------------------------------------------------------
PreNotify(NotifyEvent & _rNEvt)1221cdf0e10cSrcweir     long OBrowserListBox::PreNotify( NotifyEvent& _rNEvt )
1222cdf0e10cSrcweir     {
1223cdf0e10cSrcweir         switch ( _rNEvt.GetType() )
1224cdf0e10cSrcweir         {
1225cdf0e10cSrcweir         case EVENT_KEYINPUT:
1226cdf0e10cSrcweir         {
1227cdf0e10cSrcweir             const KeyEvent* pKeyEvent = _rNEvt.GetKeyEvent();
1228cdf0e10cSrcweir             if  (   ( pKeyEvent->GetKeyCode().GetModifier() != 0 )
1229cdf0e10cSrcweir                 ||  (   ( pKeyEvent->GetKeyCode().GetCode() != KEY_PAGEUP )
1230cdf0e10cSrcweir                     &&  ( pKeyEvent->GetKeyCode().GetCode() != KEY_PAGEDOWN )
1231cdf0e10cSrcweir                     )
1232cdf0e10cSrcweir                 )
1233cdf0e10cSrcweir                 break;
1234cdf0e10cSrcweir 
1235cdf0e10cSrcweir             long nScrollOffset = 0;
1236cdf0e10cSrcweir             if ( m_aVScroll.IsVisible() )
1237cdf0e10cSrcweir             {
1238cdf0e10cSrcweir                 if ( pKeyEvent->GetKeyCode().GetCode() == KEY_PAGEUP )
1239cdf0e10cSrcweir                     nScrollOffset = -m_aVScroll.GetPageSize();
1240cdf0e10cSrcweir                 else if ( pKeyEvent->GetKeyCode().GetCode() == KEY_PAGEDOWN )
1241cdf0e10cSrcweir                     nScrollOffset = m_aVScroll.GetPageSize();
1242cdf0e10cSrcweir             }
1243cdf0e10cSrcweir 
1244cdf0e10cSrcweir             if ( nScrollOffset )
1245cdf0e10cSrcweir             {
1246cdf0e10cSrcweir                 long nNewThumbPos = m_aVScroll.GetThumbPos() + nScrollOffset;
1247cdf0e10cSrcweir                 nNewThumbPos = ::std::max( nNewThumbPos, m_aVScroll.GetRangeMin() );
1248cdf0e10cSrcweir                 nNewThumbPos = ::std::min( nNewThumbPos, m_aVScroll.GetRangeMax() );
1249cdf0e10cSrcweir                 m_aVScroll.DoScroll( nNewThumbPos );
1250cdf0e10cSrcweir                 nNewThumbPos = m_aVScroll.GetThumbPos();
1251cdf0e10cSrcweir 
1252cdf0e10cSrcweir                 sal_uInt16 nFocusControlPos = 0;
1253cdf0e10cSrcweir                 sal_uInt16 nActiveControlPos = impl_getControlPos( m_xActiveControl );
1254cdf0e10cSrcweir                 if ( nActiveControlPos < nNewThumbPos )
1255cdf0e10cSrcweir                     nFocusControlPos = (sal_uInt16)nNewThumbPos;
1256cdf0e10cSrcweir                 else if ( nActiveControlPos >= nNewThumbPos + CalcVisibleLines() )
1257cdf0e10cSrcweir                     nFocusControlPos = (sal_uInt16)nNewThumbPos + CalcVisibleLines() - 1;
1258cdf0e10cSrcweir                 if ( nFocusControlPos )
1259cdf0e10cSrcweir                 {
1260cdf0e10cSrcweir                     if ( nFocusControlPos < m_aOrderedLines.size() )
1261cdf0e10cSrcweir                     {
1262cdf0e10cSrcweir                         m_aOrderedLines[ nFocusControlPos ]->second.pLine->GrabFocus();
1263cdf0e10cSrcweir                     }
1264cdf0e10cSrcweir                     else
1265cdf0e10cSrcweir                         OSL_ENSURE( false, "OBrowserListBox::PreNotify: internal error, invalid focus control position!" );
1266cdf0e10cSrcweir                 }
1267cdf0e10cSrcweir             }
1268cdf0e10cSrcweir 
1269cdf0e10cSrcweir             return 1L;
1270cdf0e10cSrcweir             // handled this. In particular, we also consume PageUp/Down events if we do not use them for scrolling,
1271cdf0e10cSrcweir             // otherwise they would be used to scroll the document view, which does not sound like it is desired by
1272cdf0e10cSrcweir             // the user.
1273cdf0e10cSrcweir         }
1274cdf0e10cSrcweir         }
1275cdf0e10cSrcweir         return Control::PreNotify( _rNEvt );
1276cdf0e10cSrcweir     }
1277cdf0e10cSrcweir 
1278cdf0e10cSrcweir     //------------------------------------------------------------------
Notify(NotifyEvent & _rNEvt)1279cdf0e10cSrcweir     long OBrowserListBox::Notify( NotifyEvent& _rNEvt )
1280cdf0e10cSrcweir     {
1281cdf0e10cSrcweir         switch ( _rNEvt.GetType() )
1282cdf0e10cSrcweir         {
1283cdf0e10cSrcweir         case EVENT_COMMAND:
1284cdf0e10cSrcweir         {
1285cdf0e10cSrcweir             const CommandEvent* pCommand = _rNEvt.GetCommandEvent();
1286cdf0e10cSrcweir             if  (   ( COMMAND_WHEEL == pCommand->GetCommand() )
1287cdf0e10cSrcweir                 ||  ( COMMAND_STARTAUTOSCROLL == pCommand->GetCommand() )
1288cdf0e10cSrcweir                 ||  ( COMMAND_AUTOSCROLL == pCommand->GetCommand() )
1289cdf0e10cSrcweir                 )
1290cdf0e10cSrcweir             {
1291cdf0e10cSrcweir                 // interested in scroll events if we have a scrollbar
1292cdf0e10cSrcweir                 if ( m_aVScroll.IsVisible() )
1293cdf0e10cSrcweir                 {
1294cdf0e10cSrcweir                     HandleScrollCommand( *pCommand, NULL, &m_aVScroll );
1295cdf0e10cSrcweir                 }
1296cdf0e10cSrcweir             }
1297cdf0e10cSrcweir         }
1298cdf0e10cSrcweir         break;
1299cdf0e10cSrcweir         }
1300cdf0e10cSrcweir 
1301cdf0e10cSrcweir         return Control::Notify( _rNEvt );
1302cdf0e10cSrcweir     }
1303cdf0e10cSrcweir 
1304cdf0e10cSrcweir //............................................................................
1305cdf0e10cSrcweir } // namespace pcr
1306cdf0e10cSrcweir //............................................................................
1307