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