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

Generated by: LCOV version 1.11