LCOV - code coverage report
Current view: top level - libreoffice/extensions/source/propctrlr - browserlistbox.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 523 0.0 %
Date: 2012-12-17 Functions: 0 70 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10