1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "browserlistbox.hxx"
21 #include "pcrcommon.hxx"
22 #include "proplinelistener.hxx"
23 #include "propcontrolobserver.hxx"
24 #include "linedescriptor.hxx"
25 #include "inspectorhelpwindow.hxx"
27 #include <sal/log.hxx>
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 <comphelper/diagnose_ex.hxx>
33 #include <comphelper/asyncnotification.hxx>
34 #include <cppuhelper/implbase.hxx>
35 #include <vcl/svapp.hxx>
36 #include <osl/mutex.hxx>
41 using ::com::sun::star::uno::Any
;
42 using ::com::sun::star::uno::Exception
;
43 using ::com::sun::star::inspection::XPropertyControlContext
;
44 using ::com::sun::star::uno::Reference
;
45 using ::com::sun::star::inspection::XPropertyControl
;
46 using ::com::sun::star::lang::DisposedException
;
47 using ::com::sun::star::lang::XComponent
;
48 using ::com::sun::star::uno::UNO_QUERY
;
50 namespace PropertyControlType
= ::com::sun::star::inspection::PropertyControlType
;
61 struct ControlEvent
: public ::comphelper::AnyEvent
63 Reference
< XPropertyControl
> xControl
;
64 ControlEventType eType
;
66 ControlEvent( const Reference
< XPropertyControl
>& _rxControl
, ControlEventType _eType
)
67 :xControl( _rxControl
)
76 static ::osl::Mutex
& getMutex();
77 static ::rtl::Reference
< ::comphelper::AsyncEventNotifier
> s_pNotifier
;
80 SharedNotifier(const SharedNotifier
&) = delete;
81 SharedNotifier
& operator=(const SharedNotifier
&) = delete;
82 static const ::rtl::Reference
< ::comphelper::AsyncEventNotifier
>&
88 ::rtl::Reference
< ::comphelper::AsyncEventNotifier
> SharedNotifier::s_pNotifier
;
91 ::osl::Mutex
& SharedNotifier::getMutex()
93 static ::osl::Mutex s_aMutex
;
98 const ::rtl::Reference
< ::comphelper::AsyncEventNotifier
>& SharedNotifier::getNotifier()
100 ::osl::MutexGuard
aGuard( getMutex() );
101 if ( !s_pNotifier
.is() )
104 new ::comphelper::AsyncEventNotifier("browserlistbox"));
105 s_pNotifier
->launch();
106 //TODO: a protocol is missing how to join with the launched
107 // thread before exit(3), to ensure the thread is no longer
108 // relying on any infrastructure while that infrastructure is
109 // being shut down in atexit handlers
115 /** implementation for of <type scope="css::inspection">XPropertyControlContext</type>
116 which forwards all events to a non-UNO version of this interface
118 typedef ::cppu::WeakImplHelper
< XPropertyControlContext
> PropertyControlContext_Impl_Base
;
119 class PropertyControlContext_Impl
:public PropertyControlContext_Impl_Base
120 ,public ::comphelper::IEventProcessor
123 enum NotificationMode
130 OBrowserListBox
* m_pContext
;
131 NotificationMode m_eMode
;
134 /** creates an instance
136 the instance to delegate events to
138 explicit PropertyControlContext_Impl( OBrowserListBox
& _rContextImpl
);
140 /** disposes the context.
142 When you call this method, all subsequent callbacks to the
143 <type scope="css::inspection">XPropertyControlContext</type> methods
144 will throw a <type scope="css::lang">DisposedException</type>.
148 /** sets the notification mode, so that notifications received from the controls are
149 forwarded to our OBrowserListBox either synchronously or asynchronously
151 the new notification mode
153 void setNotificationMode( NotificationMode _eMode
);
155 virtual void SAL_CALL
acquire() noexcept override
;
156 virtual void SAL_CALL
release() noexcept override
;
159 virtual ~PropertyControlContext_Impl() override
;
161 // XPropertyControlObserver
162 virtual void SAL_CALL
focusGained( const Reference
< XPropertyControl
>& Control
) override
;
163 virtual void SAL_CALL
valueChanged( const Reference
< XPropertyControl
>& Control
) override
;
164 // XPropertyControlContext
165 virtual void SAL_CALL
activateNextControl( const Reference
< XPropertyControl
>& CurrentControl
) override
;
168 virtual void processEvent( const ::comphelper::AnyEvent
& _rEvent
) override
;
171 /** processes the given event, i.e. notifies it to our OBrowserListBox
175 our mutex (well, the SolarMutex) is locked
177 void impl_processEvent_throw( const ::comphelper::AnyEvent
& _rEvent
);
179 /** checks whether the instance is already disposed
181 bool impl_isDisposed_nothrow() const { return m_pContext
== nullptr; }
183 /** notifies the given event originating from the given control
184 @throws DisposedException
188 void impl_notify_throw( const Reference
< XPropertyControl
>& _rxControl
, ControlEventType _eType
);
191 PropertyControlContext_Impl::PropertyControlContext_Impl( OBrowserListBox
& _rContextImpl
)
192 : m_pContext( &_rContextImpl
)
193 , m_eMode( eAsynchronously
)
197 PropertyControlContext_Impl::~PropertyControlContext_Impl()
199 if ( !impl_isDisposed_nothrow() )
203 void PropertyControlContext_Impl::dispose()
205 SolarMutexGuard aGuard
;
206 if ( impl_isDisposed_nothrow() )
209 SharedNotifier::getNotifier()->removeEventsForProcessor( this );
210 m_pContext
= nullptr;
213 void PropertyControlContext_Impl::setNotificationMode( NotificationMode _eMode
)
215 SolarMutexGuard aGuard
;
219 void PropertyControlContext_Impl::impl_notify_throw( const Reference
< XPropertyControl
>& _rxControl
, ControlEventType _eType
)
221 ::comphelper::AnyEventRef pEvent
;
224 SolarMutexGuard aGuard
;
225 if ( impl_isDisposed_nothrow() )
226 throw DisposedException( OUString(), *this );
227 pEvent
= new ControlEvent( _rxControl
, _eType
);
229 if ( m_eMode
== eSynchronously
)
231 impl_processEvent_throw( *pEvent
);
236 SharedNotifier::getNotifier()->addEvent( pEvent
, this );
239 void SAL_CALL
PropertyControlContext_Impl::focusGained( const Reference
< XPropertyControl
>& Control
)
241 impl_notify_throw( Control
, FOCUS_GAINED
);
244 void SAL_CALL
PropertyControlContext_Impl::valueChanged( const Reference
< XPropertyControl
>& Control
)
246 impl_notify_throw( Control
, VALUE_CHANGED
);
249 void SAL_CALL
PropertyControlContext_Impl::activateNextControl( const Reference
< XPropertyControl
>& CurrentControl
)
251 impl_notify_throw( CurrentControl
, ACTIVATE_NEXT
);
254 void SAL_CALL
PropertyControlContext_Impl::acquire() noexcept
256 PropertyControlContext_Impl_Base::acquire();
259 void SAL_CALL
PropertyControlContext_Impl::release() noexcept
261 PropertyControlContext_Impl_Base::release();
264 void PropertyControlContext_Impl::processEvent( const ::comphelper::AnyEvent
& _rEvent
)
266 SolarMutexGuard aGuard
;
267 if ( impl_isDisposed_nothrow() )
272 impl_processEvent_throw( _rEvent
);
274 catch( const Exception
& )
276 // can't handle otherwise, since our caller (the notification thread) does not allow
277 // for exceptions (it could itself abort only)
278 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
282 void PropertyControlContext_Impl::impl_processEvent_throw( const ::comphelper::AnyEvent
& _rEvent
)
284 const ControlEvent
& rControlEvent
= static_cast< const ControlEvent
& >( _rEvent
);
285 switch ( rControlEvent
.eType
)
288 m_pContext
->focusGained( rControlEvent
.xControl
);
291 m_pContext
->valueChanged( rControlEvent
.xControl
);
294 m_pContext
->activateNextControl( rControlEvent
.xControl
);
299 OBrowserListBox::OBrowserListBox(weld::Builder
& rBuilder
, weld::Container
* pContainer
)
300 : m_xScrolledWindow(rBuilder
.weld_scrolled_window(u
"scrolledwindow"_ustr
))
301 , m_xLinesPlayground(rBuilder
.weld_container(u
"playground"_ustr
))
302 , m_xSizeGroup(rBuilder
.create_size_group())
303 , m_xHelpWindow(new InspectorHelpWindow(rBuilder
))
304 , m_pInitialControlParent(pContainer
)
305 , m_pLineListener(nullptr)
306 , m_pControlObserver( nullptr )
309 , m_pControlContextImpl( new PropertyControlContext_Impl( *this ) )
311 m_xScrolledWindow
->set_size_request(-1, m_xScrolledWindow
->get_text_height() * 20);
314 OBrowserListBox::~OBrowserListBox()
316 OSL_ENSURE( !IsModified(), "OBrowserListBox::~OBrowserListBox: still modified - should have been committed before!" );
318 // doing the commit here, while we, as well as our owner, as well as some other components,
319 // are already "half dead" (means within their dtor) is potentially dangerous.
320 // By definition, CommitModified has to be called (if necessary) before destruction
321 m_pControlContextImpl
->dispose();
322 m_pControlContextImpl
.clear();
327 bool OBrowserListBox::IsModified() const
329 bool bModified
= false;
331 if (m_xScrolledWindow
->get_visible() && m_xActiveControl
.is())
332 bModified
= m_xActiveControl
->isModified();
337 void OBrowserListBox::CommitModified( )
339 if ( !(IsModified() && m_xActiveControl
.is()) )
342 // for the time of this commit, notify all events synchronously
344 m_pControlContextImpl
->setNotificationMode( PropertyControlContext_Impl::eSynchronously
);
347 m_xActiveControl
->notifyModifiedValue();
349 catch( const Exception
& )
351 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
353 m_pControlContextImpl
->setNotificationMode( PropertyControlContext_Impl::eAsynchronously
);
356 void OBrowserListBox::SetListener( IPropertyLineListener
* _pListener
)
358 m_pLineListener
= _pListener
;
361 void OBrowserListBox::SetObserver( IPropertyControlObserver
* _pObserver
)
363 m_pControlObserver
= _pObserver
;
366 void OBrowserListBox::EnableHelpSection( bool _bEnable
)
368 m_xHelpWindow
->Show( _bEnable
);
371 bool OBrowserListBox::HasHelpSection() const
373 return m_xHelpWindow
->IsVisible();
376 void OBrowserListBox::SetHelpText( const OUString
& _rHelpText
)
378 OSL_ENSURE( HasHelpSection(), "OBrowserListBox::SetHelpText: help section not visible!" );
379 m_xHelpWindow
->SetText( _rHelpText
);
382 void OBrowserListBox::UpdatePlayGround()
384 for (auto& line
: m_aLines
)
385 line
.pLine
->SetTitleWidth(m_nTheNameSize
);
388 void OBrowserListBox::SetPropertyValue(const OUString
& _rEntryName
, const Any
& _rValue
, bool _bUnknownValue
)
390 ListBoxLines::iterator line
= std::find_if(m_aLines
.begin(), m_aLines
.end(),
391 [&_rEntryName
](const ListBoxLine
& rLine
) { return rLine
.aName
== _rEntryName
; });
393 if ( line
!= m_aLines
.end() )
395 if ( _bUnknownValue
)
397 Reference
< XPropertyControl
> xControl( line
->pLine
->getControl() );
398 OSL_ENSURE( xControl
.is(), "OBrowserListBox::SetPropertyValue: illegal control!" );
400 xControl
->setValue( Any() );
403 impl_setControlAsPropertyValue( *line
, _rValue
);
407 sal_uInt16
OBrowserListBox::GetPropertyPos( std::u16string_view _rEntryName
) const
410 for (auto const& line
: m_aLines
)
412 if ( line
.aName
== _rEntryName
)
419 return EDITOR_LIST_ENTRY_NOTFOUND
;
422 bool OBrowserListBox::impl_getBrowserLineForName( const OUString
& _rEntryName
, BrowserLinePointer
& _out_rpLine
) const
424 ListBoxLines::const_iterator line
= std::find_if(m_aLines
.begin(), m_aLines
.end(),
425 [&_rEntryName
](const ListBoxLine
& rLine
) { return rLine
.aName
== _rEntryName
; });
427 if ( line
!= m_aLines
.end() )
428 _out_rpLine
= line
->pLine
;
431 return bool(_out_rpLine
);
434 void OBrowserListBox::EnablePropertyControls( const OUString
& _rEntryName
, sal_Int16 _nControls
, bool _bEnable
)
436 BrowserLinePointer pLine
;
437 if ( impl_getBrowserLineForName( _rEntryName
, pLine
) )
438 pLine
->EnablePropertyControls( _nControls
, _bEnable
);
441 void OBrowserListBox::EnablePropertyLine( const OUString
& _rEntryName
, bool _bEnable
)
443 BrowserLinePointer pLine
;
444 if ( impl_getBrowserLineForName( _rEntryName
, pLine
) )
445 pLine
->EnablePropertyLine( _bEnable
);
448 Reference
< XPropertyControl
> OBrowserListBox::GetPropertyControl( const OUString
& _rEntryName
)
450 BrowserLinePointer pLine
;
451 if ( impl_getBrowserLineForName( _rEntryName
, pLine
) )
452 return pLine
->getControl();
456 void OBrowserListBox::InsertEntry(const OLineDescriptor
& rPropertyData
, sal_uInt16 _nPos
)
459 BrowserLinePointer pBrowserLine
= std::make_shared
<OBrowserLine
>(rPropertyData
.sName
, m_xLinesPlayground
.get(),
460 m_xSizeGroup
.get(), m_pInitialControlParent
);
462 // check that the name is unique
463 for (auto const& line
: m_aLines
)
465 if (line
.aName
== rPropertyData
.sName
)
467 // already have another line for this name!
472 ListBoxLine
aNewLine( rPropertyData
.sName
, pBrowserLine
, rPropertyData
.xPropertyHandler
);
473 ListBoxLines::size_type nInsertPos
= _nPos
;
474 if ( _nPos
>= m_aLines
.size() )
476 nInsertPos
= m_aLines
.size();
477 m_aLines
.push_back( aNewLine
);
480 m_aLines
.insert( m_aLines
.begin() + _nPos
, aNewLine
);
482 pBrowserLine
->SetTitleWidth(m_nTheNameSize
);
484 // initialize the entry
485 ChangeEntry(rPropertyData
, nInsertPos
);
487 m_nRowHeight
= std::max(m_nRowHeight
, pBrowserLine
->GetRowHeight() + 6); // 6 is spacing of the "playground" in browserpage.ui
488 m_xScrolledWindow
->vadjustment_set_step_increment(m_nRowHeight
);
491 void OBrowserListBox::ShowEntry(sal_uInt16 nPos
)
495 // special case the simple entry 0 situation
496 m_xScrolledWindow
->vadjustment_set_value(0);
500 if (nPos
>= m_aLines
.size())
503 unsigned const nWinHeight
= m_xScrolledWindow
->vadjustment_get_page_size();
505 auto nThumbPos
= m_xScrolledWindow
->vadjustment_get_value();
506 int const nWinTop
= nThumbPos
;
507 int const nWinBottom
= nWinTop
+ nWinHeight
;
509 auto nCtrlPosY
= nPos
* m_nRowHeight
;
511 int const nSelectedItemTop
= nCtrlPosY
;
512 int const nSelectedItemBottom
= nCtrlPosY
+ m_nRowHeight
;
513 bool const shouldScrollDown
= nSelectedItemBottom
>= nWinBottom
;
514 bool const shouldScrollUp
= nSelectedItemTop
<= nWinTop
;
515 bool const isNeedToScroll
= shouldScrollDown
|| shouldScrollUp
;
520 if (shouldScrollDown
)
522 int nOffset
= nSelectedItemBottom
- nWinBottom
;
523 nThumbPos
+= nOffset
;
527 int nOffset
= nWinTop
- nSelectedItemTop
;
528 nThumbPos
-= nOffset
;
532 m_xScrolledWindow
->vadjustment_set_value(nThumbPos
);
535 void OBrowserListBox::buttonClicked( OBrowserLine
* _pLine
, bool _bPrimary
)
537 DBG_ASSERT( _pLine
, "OBrowserListBox::buttonClicked: invalid browser line!" );
538 if ( _pLine
&& m_pLineListener
)
540 m_pLineListener
->Clicked( _pLine
->GetEntryName(), _bPrimary
);
544 void OBrowserListBox::impl_setControlAsPropertyValue( const ListBoxLine
& _rLine
, const Any
& _rPropertyValue
)
546 Reference
< XPropertyControl
> xControl( _rLine
.pLine
->getControl() );
549 if ( _rPropertyValue
.getValueType().equals( _rLine
.pLine
->getControl()->getValueType() ) )
551 xControl
->setValue( _rPropertyValue
);
555 SAL_WARN_IF( !_rLine
.xHandler
.is(), "extensions.propctrlr",
556 "OBrowserListBox::impl_setControlAsPropertyValue: no handler -> no conversion (property: '"
557 << _rLine
.pLine
->GetEntryName() << "')!" );
558 if ( _rLine
.xHandler
.is() )
560 Any aControlValue
= _rLine
.xHandler
->convertToControlValue(
561 _rLine
.pLine
->GetEntryName(), _rPropertyValue
, xControl
->getValueType() );
562 xControl
->setValue( aControlValue
);
566 catch( const Exception
& )
568 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
572 Any
OBrowserListBox::impl_getControlAsPropertyValue( const ListBoxLine
& _rLine
)
574 Reference
< XPropertyControl
> xControl( _rLine
.pLine
->getControl() );
578 SAL_WARN_IF( !_rLine
.xHandler
.is(), "extensions.propctrlr",
579 "OBrowserListBox::impl_getControlAsPropertyValue: no handler -> no conversion (property: '"
580 << _rLine
.pLine
->GetEntryName() << "')!" );
581 if ( _rLine
.xHandler
.is() )
582 aPropertyValue
= _rLine
.xHandler
->convertToPropertyValue( _rLine
.pLine
->GetEntryName(), xControl
->getValue() );
584 aPropertyValue
= xControl
->getValue();
586 catch( const Exception
& )
588 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
590 return aPropertyValue
;
593 sal_uInt16
OBrowserListBox::impl_getControlPos( const Reference
< XPropertyControl
>& _rxControl
) const
596 for (auto const& search
: m_aLines
)
598 if ( search
.pLine
->getControl().get() == _rxControl
.get() )
602 OSL_FAIL( "OBrowserListBox::impl_getControlPos: invalid control - not part of any of our lines!" );
603 return sal_uInt16(-1);
607 void OBrowserListBox::focusGained( const Reference
< XPropertyControl
>& _rxControl
)
609 DBG_TESTSOLARMUTEX();
611 DBG_ASSERT( _rxControl
.is(), "OBrowserListBox::focusGained: invalid event source!" );
612 if ( !_rxControl
.is() )
615 if ( m_pControlObserver
)
616 m_pControlObserver
->focusGained( _rxControl
);
618 m_xActiveControl
= _rxControl
;
619 ShowEntry( impl_getControlPos( m_xActiveControl
) );
623 void OBrowserListBox::valueChanged( const Reference
< XPropertyControl
>& _rxControl
)
625 DBG_TESTSOLARMUTEX();
627 DBG_ASSERT( _rxControl
.is(), "OBrowserListBox::valueChanged: invalid event source!" );
628 if ( !_rxControl
.is() )
631 if ( m_pControlObserver
)
632 m_pControlObserver
->valueChanged( _rxControl
);
634 if ( m_pLineListener
)
636 const ListBoxLine
& rLine
= m_aLines
[ impl_getControlPos( _rxControl
) ];
637 m_pLineListener
->Commit(
638 rLine
.pLine
->GetEntryName(),
639 impl_getControlAsPropertyValue( rLine
)
645 void OBrowserListBox::activateNextControl( const Reference
< XPropertyControl
>& _rxCurrentControl
)
647 DBG_TESTSOLARMUTEX();
649 sal_uInt16 nLine
= impl_getControlPos( _rxCurrentControl
);
651 // cycle forwards, 'til we've the next control which can grab the focus
653 while ( static_cast< size_t >( nLine
) < m_aLines
.size() )
655 if ( m_aLines
[nLine
].pLine
->GrabFocus() )
661 if ( ( static_cast< size_t >( nLine
) >= m_aLines
.size() ) && ( !m_aLines
.empty() ) )
662 m_aLines
[0].pLine
->GrabFocus();
669 void lcl_implDisposeControl_nothrow( const Reference
< XPropertyControl
>& _rxControl
)
671 if ( !_rxControl
.is() )
675 _rxControl
->setControlContext( nullptr );
676 Reference
< XComponent
> xControlComponent( _rxControl
, UNO_QUERY
);
677 if ( xControlComponent
.is() )
678 xControlComponent
->dispose();
680 catch( const Exception
& )
682 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
687 void OBrowserListBox::Clear()
689 for (auto const& line
: m_aLines
)
693 // reset the listener
694 lcl_implDisposeControl_nothrow( line
.pLine
->getControl() );
697 clearContainer( m_aLines
);
700 bool OBrowserListBox::RemoveEntry( const OUString
& _rName
)
702 ListBoxLines::iterator it
= std::find_if(m_aLines
.begin(), m_aLines
.end(),
703 [&_rName
](const ListBoxLine
& rLine
) { return rLine
.aName
== _rName
; });
705 if ( it
== m_aLines
.end() )
708 m_aLines
.erase( it
);
713 void OBrowserListBox::ChangeEntry( const OLineDescriptor
& rPropertyData
, ListBoxLines::size_type nPos
)
715 OSL_PRECOND( rPropertyData
.Control
.is(), "OBrowserListBox::ChangeEntry: invalid control!" );
716 if ( !rPropertyData
.Control
.is() )
719 if ( nPos
== EDITOR_LIST_REPLACE_EXISTING
)
720 nPos
= GetPropertyPos( rPropertyData
.sName
);
722 if ( nPos
>= m_aLines
.size() )
725 // the current line and control
726 ListBoxLine
& rLine
= m_aLines
[nPos
];
728 // the old control and some data about it
729 Reference
< XPropertyControl
> xControl
= rLine
.pLine
->getControl();
731 // clean up the old control
732 lcl_implDisposeControl_nothrow( xControl
);
734 // set the new control at the line
735 rLine
.pLine
->setControl( rPropertyData
.Control
);
736 xControl
= rLine
.pLine
->getControl();
739 xControl
->setControlContext( m_pControlContextImpl
);
741 // the initial property value
742 if ( rPropertyData
.bUnknownValue
)
743 xControl
->setValue( Any() );
745 impl_setControlAsPropertyValue( rLine
, rPropertyData
.aValue
);
747 rLine
.pLine
->SetTitle(rPropertyData
.DisplayName
);
748 rLine
.xHandler
= rPropertyData
.xPropertyHandler
;
750 if ( rPropertyData
.HasPrimaryButton
)
752 if ( !rPropertyData
.PrimaryButtonImageURL
.isEmpty() )
753 rLine
.pLine
->ShowBrowseButton( rPropertyData
.PrimaryButtonImageURL
, true );
754 else if ( rPropertyData
.PrimaryButtonImage
.is() )
755 rLine
.pLine
->ShowBrowseButton( rPropertyData
.PrimaryButtonImage
, true );
757 rLine
.pLine
->ShowBrowseButton( true );
759 if ( rPropertyData
.HasSecondaryButton
)
761 if ( !rPropertyData
.SecondaryButtonImageURL
.isEmpty() )
762 rLine
.pLine
->ShowBrowseButton( rPropertyData
.SecondaryButtonImageURL
, false );
763 else if ( rPropertyData
.SecondaryButtonImage
.is() )
764 rLine
.pLine
->ShowBrowseButton( rPropertyData
.SecondaryButtonImage
, false );
766 rLine
.pLine
->ShowBrowseButton( false );
769 rLine
.pLine
->HideBrowseButton( false );
771 rLine
.pLine
->SetClickListener( this );
775 rLine
.pLine
->HideBrowseButton( true );
776 rLine
.pLine
->HideBrowseButton( false );
779 DBG_ASSERT( ( rPropertyData
.IndentLevel
== 0 ) || ( rPropertyData
.IndentLevel
== 1 ),
780 "OBrowserListBox::ChangeEntry: unsupported indent level!" );
781 rLine
.pLine
->IndentTitle( rPropertyData
.IndentLevel
> 0 );
783 rLine
.pLine
->SetComponentHelpIds(
784 HelpIdUrl::getHelpId( rPropertyData
.HelpURL
)
787 if ( rPropertyData
.bReadOnly
)
789 rLine
.pLine
->SetReadOnly( true );
791 // user controls (i.e. the ones not provided by the usual
792 // XPropertyControlFactory) have no chance to know that they should be read-only,
793 // since XPropertyHandler::describePropertyLine does not transport this
795 // So, we manually switch this to read-only.
796 if ( xControl
.is() && ( xControl
->getControlType() == PropertyControlType::Unknown
) )
798 weld::Widget
* pWindow
= rLine
.pLine
->getControlWindow();
799 weld::Entry
* pControlWindowAsEdit
= dynamic_cast<weld::Entry
*>(pWindow
);
800 if (pControlWindowAsEdit
)
801 pControlWindowAsEdit
->set_editable(false);
803 pWindow
->set_sensitive(false);
807 sal_uInt16 nTextWidth
= m_xLinesPlayground
->get_pixel_size(rPropertyData
.DisplayName
).Width();
808 if (m_nTheNameSize
< nTextWidth
)
810 m_nTheNameSize
= nTextWidth
;
817 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */