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

Generated by: LCOV version 1.10