xref: /AOO41X/main/extensions/source/propctrlr/browserlistbox.cxx (revision 2a97ec55f1442d65917e8c8b82a55ab76c9ff676)
1*2a97ec55SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*2a97ec55SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*2a97ec55SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*2a97ec55SAndrew Rist  * distributed with this work for additional information
6*2a97ec55SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*2a97ec55SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*2a97ec55SAndrew Rist  * "License"); you may not use this file except in compliance
9*2a97ec55SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11*2a97ec55SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13*2a97ec55SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*2a97ec55SAndrew Rist  * software distributed under the License is distributed on an
15*2a97ec55SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*2a97ec55SAndrew Rist  * KIND, either express or implied.  See the License for the
17*2a97ec55SAndrew Rist  * specific language governing permissions and limitations
18*2a97ec55SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20*2a97ec55SAndrew Rist  *************************************************************/
21*2a97ec55SAndrew Rist 
22*2a97ec55SAndrew 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 
170cdf0e10cSrcweir         /** sets the notification mode, so that notifications recieved 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 //............................................................................
1307cdf0e10cSrcweir 
1308cdf0e10cSrcweir 
1309