bump product version to 5.0.4.1
[LibreOffice.git] / forms / source / component / ListBox.cxx
blobc6243902ccc5d872b4c3eda629b5ea11876b4450
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <config_features.h>
22 #include "ListBox.hxx"
23 #include "property.hxx"
24 #include "property.hrc"
25 #include "services.hxx"
26 #include "frm_resource.hxx"
27 #include "frm_resource.hrc"
28 #include "BaseListBox.hxx"
29 #include "listenercontainers.hxx"
30 #include "componenttools.hxx"
32 #include <com/sun/star/util/XNumberFormatTypes.hpp>
33 #include <com/sun/star/sdbc/XRowSet.hpp>
34 #include <com/sun/star/container/XIndexAccess.hpp>
35 #include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp>
36 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
37 #include <com/sun/star/util/NumberFormat.hpp>
38 #include <com/sun/star/awt/XWindow.hpp>
39 #include <com/sun/star/sdbc/XConnection.hpp>
40 #include <com/sun/star/sdb/CommandType.hpp>
42 #include <comphelper/basicio.hxx>
43 #include <comphelper/container.hxx>
44 #include <comphelper/numbers.hxx>
45 #include <comphelper/processfactory.hxx>
46 #include <comphelper/listenernotification.hxx>
47 #include <connectivity/dbtools.hxx>
48 #include <connectivity/formattedcolumnvalue.hxx>
49 #include <connectivity/dbconversion.hxx>
50 #include <cppuhelper/queryinterface.hxx>
51 #include <tools/debug.hxx>
52 #include <tools/diagnose_ex.h>
53 #include <unotools/sharedunocomponent.hxx>
54 #include <vcl/svapp.hxx>
56 #include <boost/optional.hpp>
58 #include <algorithm>
59 #include <functional>
60 #include <iterator>
62 namespace frm
64 using namespace ::com::sun::star::uno;
65 using namespace ::com::sun::star::sdb;
66 using namespace ::com::sun::star::sdbc;
67 using namespace ::com::sun::star::sdbcx;
68 using namespace ::com::sun::star::beans;
69 using namespace ::com::sun::star::container;
70 using namespace ::com::sun::star::form;
71 using namespace ::com::sun::star::awt;
72 using namespace ::com::sun::star::io;
73 using namespace ::com::sun::star::lang;
74 using namespace ::com::sun::star::util;
75 using namespace ::com::sun::star::form::binding;
76 using namespace ::dbtools;
78 using ::connectivity::ORowSetValue;
80 const ::connectivity::ORowSetValue OListBoxModel::s_aEmptyValue;
81 const ::connectivity::ORowSetValue OListBoxModel::s_aEmptyStringValue = OUString();
83 //= helper
85 namespace
88 struct RowSetValueToString : public ::std::unary_function< ORowSetValue, OUString >
90 OUString operator()( const ORowSetValue& _value ) const
92 return _value.getString();
97 struct AppendRowSetValueString : public ::std::unary_function< OUString, void >
99 AppendRowSetValueString( OUString& _string )
100 :m_string( _string )
104 void operator()( const OUString& _append )
106 m_string += _append;
109 private:
110 OUString& m_string;
114 Sequence< OUString > lcl_convertToStringSequence( const ValueList& _values )
116 Sequence< OUString > aStrings( _values.size() );
117 ::std::transform(
118 _values.begin(),
119 _values.end(),
120 aStrings.getArray(),
121 RowSetValueToString()
123 return aStrings;
128 //= ItemEventDescription
130 typedef ::comphelper::EventHolder< ItemEvent > ItemEventDescription;
133 //= OListBoxModel
135 Sequence< Type> OListBoxModel::_getTypes()
137 return TypeBag(
138 OBoundControlModel::_getTypes(),
139 OEntryListHelper::getTypes(),
140 OErrorBroadcaster::getTypes()
141 ).getTypes();
144 // stuff common to all constructors
145 void OListBoxModel::init()
147 startAggregatePropertyListening( PROPERTY_STRINGITEMLIST );
151 OListBoxModel::OListBoxModel(const Reference<XComponentContext>& _rxFactory)
152 :OBoundControlModel( _rxFactory, VCL_CONTROLMODEL_LISTBOX, FRM_SUN_CONTROL_LISTBOX, true, true, true )
153 // use the old control name for compatibility reasons
154 ,OEntryListHelper( (OControlModel&)*this )
155 ,OErrorBroadcaster( OComponentHelper::rBHelper )
156 ,m_aListRowSet()
157 ,m_nConvertedBoundValuesType(0)
158 ,m_nNULLPos(-1)
159 ,m_nBoundColumnType( DataType::SQLNULL )
162 m_nClassId = FormComponentType::LISTBOX;
163 m_eListSourceType = ListSourceType_VALUELIST;
164 m_aBoundColumn <<= (sal_Int16)1;
165 initValueProperty( PROPERTY_SELECT_SEQ, PROPERTY_ID_SELECT_SEQ);
167 init();
171 OListBoxModel::OListBoxModel( const OListBoxModel* _pOriginal, const Reference<XComponentContext>& _rxFactory )
172 :OBoundControlModel( _pOriginal, _rxFactory )
173 ,OEntryListHelper( *_pOriginal, (OControlModel&)*this )
174 ,OErrorBroadcaster( OComponentHelper::rBHelper )
175 ,m_aListRowSet()
176 ,m_eListSourceType( _pOriginal->m_eListSourceType )
177 ,m_aBoundColumn( _pOriginal->m_aBoundColumn )
178 ,m_aListSourceValues( _pOriginal->m_aListSourceValues )
179 ,m_aBoundValues( _pOriginal->m_aBoundValues )
180 ,m_nConvertedBoundValuesType(0)
181 ,m_aDefaultSelectSeq( _pOriginal->m_aDefaultSelectSeq )
182 ,m_nNULLPos(-1)
183 ,m_nBoundColumnType( DataType::SQLNULL )
186 init();
190 OListBoxModel::~OListBoxModel()
192 if (!OComponentHelper::rBHelper.bDisposed)
194 acquire();
195 dispose();
200 // XCloneable
202 IMPLEMENT_DEFAULT_CLONING( OListBoxModel )
204 // XServiceInfo
206 StringSequence SAL_CALL OListBoxModel::getSupportedServiceNames() throw(RuntimeException, std::exception)
208 StringSequence aSupported = OBoundControlModel::getSupportedServiceNames();
210 sal_Int32 nOldLen = aSupported.getLength();
211 aSupported.realloc( nOldLen + 9 );
212 OUString* pStoreTo = aSupported.getArray() + nOldLen;
214 *pStoreTo++ = BINDABLE_CONTROL_MODEL;
215 *pStoreTo++ = DATA_AWARE_CONTROL_MODEL;
216 *pStoreTo++ = VALIDATABLE_CONTROL_MODEL;
218 *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL;
219 *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL;
221 *pStoreTo++ = FRM_SUN_COMPONENT_LISTBOX;
222 *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_LISTBOX;
223 *pStoreTo++ = BINDABLE_DATABASE_LIST_BOX;
225 *pStoreTo++ = FRM_COMPONENT_LISTBOX;
227 return aSupported;
231 Any SAL_CALL OListBoxModel::queryAggregation(const Type& _rType) throw (RuntimeException, std::exception)
233 Any aReturn = OBoundControlModel::queryAggregation( _rType );
234 if ( !aReturn.hasValue() )
235 aReturn = OEntryListHelper::queryInterface( _rType );
236 if ( !aReturn.hasValue() )
237 aReturn = OErrorBroadcaster::queryInterface( _rType );
238 return aReturn;
241 // OComponentHelper
243 void OListBoxModel::disposing()
245 OBoundControlModel::disposing();
246 OEntryListHelper::disposing();
247 OErrorBroadcaster::disposing();
251 void OListBoxModel::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const
253 switch (_nHandle)
255 case PROPERTY_ID_BOUNDCOLUMN:
256 _rValue <<= m_aBoundColumn;
257 break;
259 case PROPERTY_ID_LISTSOURCETYPE:
260 _rValue <<= m_eListSourceType;
261 break;
263 case PROPERTY_ID_LISTSOURCE:
264 _rValue <<= lcl_convertToStringSequence( m_aListSourceValues );
265 break;
267 case PROPERTY_ID_VALUE_SEQ:
268 _rValue <<= lcl_convertToStringSequence( m_aBoundValues );
269 break;
271 case PROPERTY_ID_SELECT_VALUE_SEQ:
272 _rValue = getCurrentMultiValue();
273 break;
275 case PROPERTY_ID_SELECT_VALUE:
276 _rValue = getCurrentSingleValue();
277 break;
279 case PROPERTY_ID_DEFAULT_SELECT_SEQ:
280 _rValue <<= m_aDefaultSelectSeq;
281 break;
283 case PROPERTY_ID_STRINGITEMLIST:
284 _rValue <<= getStringItemList();
285 break;
287 default:
288 OBoundControlModel::getFastPropertyValue(_rValue, _nHandle);
293 void OListBoxModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue) throw (com::sun::star::uno::Exception, std::exception)
295 switch (_nHandle)
297 case PROPERTY_ID_BOUNDCOLUMN :
298 DBG_ASSERT((_rValue.getValueType().getTypeClass() == TypeClass_SHORT) || (_rValue.getValueType().getTypeClass() == TypeClass_VOID),
299 "OListBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" );
300 m_aBoundColumn = _rValue;
301 break;
303 case PROPERTY_ID_LISTSOURCETYPE :
304 DBG_ASSERT(_rValue.getValueType().equals(::cppu::UnoType<ListSourceType>::get()),
305 "OComboBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" );
306 _rValue >>= m_eListSourceType;
307 break;
309 case PROPERTY_ID_LISTSOURCE:
311 // extract
312 Sequence< OUString > aListSource;
313 OSL_VERIFY( _rValue >>= aListSource );
315 // copy to member
316 ValueList().swap(m_aListSourceValues);
317 ::std::copy(
318 aListSource.getConstArray(),
319 aListSource.getConstArray() + aListSource.getLength(),
320 ::std::insert_iterator< ValueList >( m_aListSourceValues, m_aListSourceValues.end() )
323 // propagate
324 if ( m_eListSourceType == ListSourceType_VALUELIST )
326 setBoundValues(m_aListSourceValues);
328 else
330 if ( m_xCursor.is() && !hasField() && !hasExternalListSource() )
331 // listbox is already connected to a database, and no external list source
332 // data source changed -> refresh
333 loadData( false );
336 break;
338 case PROPERTY_ID_VALUE_SEQ :
339 SAL_WARN( "forms.component", "ValueItemList is read-only!" );
340 throw PropertyVetoException();
342 case PROPERTY_ID_SELECT_VALUE_SEQ :
344 Sequence< const Any > v;
345 _rValue >>= v;
346 Any newSelectSeq(translateBindingValuesToControlValue(v));
347 setControlValue( newSelectSeq, eOther );
349 break;
351 #if HAVE_FEATURE_DBCONNECTIVITY
352 case PROPERTY_ID_SELECT_VALUE :
354 ORowSetValue v;
355 v.fill(_rValue);
356 Any newSelectSeq(translateDbValueToControlValue(v));
357 setControlValue( newSelectSeq, eOther );
359 break;
360 #endif
361 case PROPERTY_ID_DEFAULT_SELECT_SEQ :
362 DBG_ASSERT(_rValue.getValueType().equals(cppu::UnoType<Sequence<sal_Int16>>::get()),
363 "OListBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" );
364 _rValue >>= m_aDefaultSelectSeq;
366 DBG_ASSERT(m_xAggregateFastSet.is(), "OListBoxModel::setFastPropertyValue_NoBroadcast(DEFAULT_SELECT_SEQ) : invalid aggregate !");
367 if ( m_xAggregateFastSet.is() )
368 setControlValue( _rValue, eOther );
369 break;
371 case PROPERTY_ID_STRINGITEMLIST:
373 ControlModelLock aLock( *this );
374 setNewStringItemList( _rValue, aLock );
375 // TODO: this is bogus. setNewStringItemList expects a guard which has the *only*
376 // lock to the mutex, but setFastPropertyValue_NoBroadcast is already called with
377 // a lock - so we effectively has two locks here, of which setNewStringItemList can
378 // only control one.
380 resetNoBroadcast();
381 break;
383 default:
384 OBoundControlModel::setFastPropertyValue_NoBroadcast(_nHandle, _rValue);
389 sal_Bool OListBoxModel::convertFastPropertyValue(
390 Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue)
391 throw (IllegalArgumentException)
393 bool bModified(false);
394 switch (_nHandle)
396 case PROPERTY_ID_BOUNDCOLUMN :
397 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aBoundColumn, ::cppu::UnoType<sal_Int16>::get());
398 break;
400 case PROPERTY_ID_LISTSOURCETYPE:
401 bModified = tryPropertyValueEnum(_rConvertedValue, _rOldValue, _rValue, m_eListSourceType);
402 break;
404 case PROPERTY_ID_LISTSOURCE:
405 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, lcl_convertToStringSequence( m_aListSourceValues ) );
406 break;
408 case PROPERTY_ID_VALUE_SEQ :
409 SAL_WARN( "forms.component", "ValueItemList is read-only!" );
410 throw IllegalArgumentException();
412 case PROPERTY_ID_SELECT_VALUE_SEQ :
413 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, getCurrentMultiValue());
414 break;
416 case PROPERTY_ID_SELECT_VALUE :
417 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, getCurrentSingleValue());
418 break;
420 case PROPERTY_ID_DEFAULT_SELECT_SEQ :
421 bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aDefaultSelectSeq);
422 break;
424 case PROPERTY_ID_STRINGITEMLIST:
425 bModified = convertNewListSourceProperty( _rConvertedValue, _rOldValue, _rValue );
426 break;
428 default:
429 return OBoundControlModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue);
431 return bModified;
435 void SAL_CALL OListBoxModel::setPropertyValues( const Sequence< OUString >& _rPropertyNames, const Sequence< Any >& _rValues ) throw(PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException, std::exception)
437 // if both SelectedItems and StringItemList are set, care for this
438 // #i27024#
439 const Any* pSelectSequenceValue = NULL;
441 const OUString* pStartPos = _rPropertyNames.getConstArray();
442 const OUString* pEndPos = _rPropertyNames.getConstArray() + _rPropertyNames.getLength();
443 const OUString* pSelectedItemsPos = ::std::find_if(
444 pStartPos, pEndPos,
445 ::std::bind2nd( ::std::equal_to< OUString >(), PROPERTY_SELECT_SEQ )
447 const OUString* pStringItemListPos = ::std::find_if(
448 pStartPos, pEndPos,
449 ::std::bind2nd( ::std::equal_to< OUString >(), PROPERTY_STRINGITEMLIST )
451 if ( ( pSelectedItemsPos != pEndPos ) && ( pStringItemListPos != pEndPos ) )
453 // both properties are present
454 // -> remember the value for the select sequence
455 pSelectSequenceValue = _rValues.getConstArray() + ( pSelectedItemsPos - pStartPos );
458 OBoundControlModel::setPropertyValues( _rPropertyNames, _rValues );
460 if ( pSelectSequenceValue )
462 setPropertyValue( PROPERTY_SELECT_SEQ, *pSelectSequenceValue );
463 // Note that this is the only reliable way, since one of the properties is implemented
464 // by ourself, and one is implemented by the aggregate, we cannot rely on any particular
465 // results when setting them both - too many undocumented behavior in all the involved
471 void OListBoxModel::describeFixedProperties( Sequence< Property >& _rProps ) const
473 BEGIN_DESCRIBE_PROPERTIES( 9, OBoundControlModel )
474 DECL_PROP1(TABINDEX, sal_Int16, BOUND);
475 DECL_PROP2(BOUNDCOLUMN, sal_Int16, BOUND, MAYBEVOID);
476 DECL_PROP1(LISTSOURCETYPE, ListSourceType, BOUND);
477 DECL_PROP1(LISTSOURCE, StringSequence, BOUND);
478 DECL_PROP3(VALUE_SEQ, StringSequence, BOUND, READONLY, TRANSIENT);
479 DECL_PROP2(SELECT_VALUE_SEQ, Sequence< Any >, BOUND, TRANSIENT);
480 DECL_PROP2(SELECT_VALUE, Any, BOUND, TRANSIENT);
481 DECL_PROP1(DEFAULT_SELECT_SEQ, Sequence<sal_Int16>, BOUND);
482 DECL_PROP1(STRINGITEMLIST, Sequence< OUString >, BOUND);
483 END_DESCRIBE_PROPERTIES();
487 void OListBoxModel::_propertyChanged( const PropertyChangeEvent& i_rEvent ) throw ( RuntimeException )
489 if ( i_rEvent.PropertyName == PROPERTY_STRINGITEMLIST )
491 ControlModelLock aLock( *this );
492 // SYNCHRONIZED ----->
493 // our aggregate internally changed its StringItemList property - reflect this in our "overridden"
494 // version of the property
495 setNewStringItemList( i_rEvent.NewValue, aLock );
496 // <----- SYNCHRONIZED
497 return;
499 OBoundControlModel::_propertyChanged( i_rEvent );
503 void OListBoxModel::describeAggregateProperties( Sequence< Property >& _rAggregateProps ) const
505 OBoundControlModel::describeAggregateProperties( _rAggregateProps );
507 // superseded properties:
508 RemoveProperty( _rAggregateProps, PROPERTY_STRINGITEMLIST );
512 OUString SAL_CALL OListBoxModel::getServiceName() throw(RuntimeException, std::exception)
514 return OUString(FRM_COMPONENT_LISTBOX); // old (non-sun) name for compatibility !
518 void SAL_CALL OListBoxModel::write(const Reference<XObjectOutputStream>& _rxOutStream)
519 throw(IOException, RuntimeException, std::exception)
521 OBoundControlModel::write(_rxOutStream);
523 // Dummy sequence, to stay compatible if SelectSeq is not saved anymore
524 Sequence<sal_Int16> aDummySeq;
526 // Version
527 // Version 0x0002: ListSource becomes StringSeq
528 _rxOutStream->writeShort(0x0004);
530 // Masking for any
531 sal_uInt16 nAnyMask = 0;
532 if (m_aBoundColumn.getValueType().getTypeClass() != TypeClass_VOID)
533 nAnyMask |= BOUNDCOLUMN;
535 _rxOutStream << nAnyMask;
537 _rxOutStream << lcl_convertToStringSequence( m_aListSourceValues );
538 _rxOutStream << (sal_Int16)m_eListSourceType;
539 _rxOutStream << aDummySeq;
540 _rxOutStream << m_aDefaultSelectSeq;
542 if ((nAnyMask & BOUNDCOLUMN) == BOUNDCOLUMN)
544 sal_Int16 nBoundColumn = 0;
545 m_aBoundColumn >>= nBoundColumn;
546 _rxOutStream << nBoundColumn;
548 writeHelpTextCompatibly(_rxOutStream);
550 // from version 0x0004 : common properties
551 writeCommonProperties(_rxOutStream);
555 void SAL_CALL OListBoxModel::read(const Reference<XObjectInputStream>& _rxInStream) throw(IOException, RuntimeException, std::exception)
557 // We need to respect dependencies for certain variables.
558 // Therefore, we need to set them explicitly via setPropertyValue().
560 OBoundControlModel::read(_rxInStream);
561 ControlModelLock aLock( *this );
563 // since we are "overwriting" the StringItemList of our aggregate (means we have
564 // an own place to store the value, instead of relying on our aggregate storing it),
565 // we need to respect what the aggregate just read for the StringItemList property.
568 if ( m_xAggregateSet.is() )
569 setNewStringItemList( m_xAggregateSet->getPropertyValue( PROPERTY_STRINGITEMLIST ), aLock );
571 catch( const Exception& )
573 SAL_WARN( "forms.component", "OComboBoxModel::read: caught an exception while examining the aggregate's string item list!" );
576 // Version
577 sal_uInt16 nVersion = _rxInStream->readShort();
578 DBG_ASSERT(nVersion > 0, "OListBoxModel::read : version 0 ? this should never have been written !");
580 if (nVersion > 0x0004)
582 SAL_WARN( "forms.component", "OListBoxModel::read : invalid (means unknown) version !");
583 ValueList().swap(m_aListSourceValues);
584 m_aBoundColumn <<= (sal_Int16)0;
585 clearBoundValues();
586 m_eListSourceType = ListSourceType_VALUELIST;
587 m_aDefaultSelectSeq.realloc(0);
588 defaultCommonProperties();
589 return;
592 // Masking for any
593 sal_uInt16 nAnyMask;
594 _rxInStream >> nAnyMask;
596 // ListSourceSeq
597 StringSequence aListSourceSeq;
598 if (nVersion == 0x0001)
600 // Create ListSourceSeq from String
601 OUString sListSource;
602 _rxInStream >> sListSource;
604 sal_Int32 nTokens = 1;
605 const sal_Unicode* pStr = sListSource.getStr();
606 while ( *pStr )
608 if ( *pStr == ';' )
609 nTokens++;
610 pStr++;
612 aListSourceSeq.realloc( nTokens );
613 for (sal_uInt16 i=0; i<nTokens; ++i)
615 sal_Int32 nTmp = 0;
616 aListSourceSeq.getArray()[i] = sListSource.getToken(i,';',nTmp);
619 else
620 _rxInStream >> aListSourceSeq;
622 sal_Int16 nListSourceType;
623 _rxInStream >> nListSourceType;
624 m_eListSourceType = (ListSourceType)nListSourceType;
625 Any aListSourceSeqAny;
626 aListSourceSeqAny <<= aListSourceSeq;
628 setFastPropertyValue(PROPERTY_ID_LISTSOURCE, aListSourceSeqAny );
630 // Dummy sequence, to stay compatible if SelectSeq is not saved anymore
631 Sequence<sal_Int16> aDummySeq;
632 _rxInStream >> aDummySeq;
634 // DefaultSelectSeq
635 Sequence<sal_Int16> aDefaultSelectSeq;
636 _rxInStream >> aDefaultSelectSeq;
637 Any aDefaultSelectSeqAny;
638 aDefaultSelectSeqAny <<= aDefaultSelectSeq;
639 setFastPropertyValue(PROPERTY_ID_DEFAULT_SELECT_SEQ, aDefaultSelectSeqAny);
641 // BoundColumn
642 if ((nAnyMask & BOUNDCOLUMN) == BOUNDCOLUMN)
644 sal_Int16 nValue;
645 _rxInStream >> nValue;
646 m_aBoundColumn <<= nValue;
648 else // the constructor initialises to 1, so if it is empty,
649 // we must explicitly set to empty
651 m_aBoundColumn = Any();
654 if (nVersion > 2)
655 readHelpTextCompatibly(_rxInStream);
657 // if our string list is not filled from the value list, we must empty it
658 // this can be the case when somebody saves in alive mode
659 if ( ( m_eListSourceType != ListSourceType_VALUELIST )
660 && !hasExternalListSource()
663 setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( StringSequence() ) );
666 if (nVersion > 3)
667 readCommonProperties(_rxInStream);
669 // Display the default values after reading
670 if ( !getControlSource().isEmpty() )
671 // (not if we don't have a control source - the "State" property acts like it is persistent, then
672 resetNoBroadcast();
676 void OListBoxModel::loadData( bool _bForce )
678 SAL_INFO( "forms.component", "OListBoxModel::loadData" );
679 DBG_ASSERT( m_eListSourceType != ListSourceType_VALUELIST, "OListBoxModel::loadData: cannot load value list from DB!" );
680 DBG_ASSERT( !hasExternalListSource(), "OListBoxModel::loadData: cannot load from DB when I have an external list source!" );
682 const sal_Int16 nNULLPosBackup( m_nNULLPos );
683 const sal_Int32 nBoundColumnTypeBackup( m_nBoundColumnType );
684 m_nNULLPos = -1;
685 m_nBoundColumnType = DataType::SQLNULL;
687 // pre-requisites:
688 // PRE1: connection
689 Reference< XConnection > xConnection;
690 // is the active connection of our form
691 Reference< XPropertySet > xFormProps( m_xCursor, UNO_QUERY );
692 if ( xFormProps.is() )
693 xFormProps->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xConnection;
695 // PRE2: list source
696 OUString sListSource;
697 // if our list source type is no value list, we need to concatenate
698 // the single list source elements
699 ::std::for_each(
700 m_aListSourceValues.begin(),
701 m_aListSourceValues.end(),
702 AppendRowSetValueString( sListSource )
705 // outta here if we don't have all pre-requisites
706 if ( !xConnection.is() || sListSource.isEmpty() )
708 clearBoundValues();
709 return;
712 ::boost::optional< sal_Int16 > aBoundColumn(boost::none);
713 if ( m_aBoundColumn.getValueType().getTypeClass() == TypeClass_SHORT )
715 sal_Int16 nBoundColumn( 0 );
716 m_aBoundColumn >>= nBoundColumn;
717 aBoundColumn.reset( nBoundColumn );
720 ::utl::SharedUNOComponent< XResultSet > xListCursor;
723 m_aListRowSet.setConnection( xConnection );
725 bool bExecute = false;
726 switch (m_eListSourceType)
728 case ListSourceType_TABLEFIELDS:
729 // don't work with a statement here, the fields will be collected below
730 break;
732 case ListSourceType_TABLE:
734 Reference<XNameAccess> xFieldsByName = getTableFields(xConnection, sListSource);
735 Reference<XIndexAccess> xFieldsByIndex(xFieldsByName, UNO_QUERY);
737 // do we have a bound column if yes we have to select it
738 // and the displayed column is the first column othwhise we act as a combobox
739 OUString aFieldName;
740 OUString aBoundFieldName;
742 if ( !!aBoundColumn && ( *aBoundColumn >= 0 ) && xFieldsByIndex.is() )
744 if ( *aBoundColumn >= xFieldsByIndex->getCount() )
745 break;
747 Reference<XPropertySet> xFieldAsSet(xFieldsByIndex->getByIndex( *aBoundColumn ),UNO_QUERY);
748 assert(xFieldAsSet.is());
749 xFieldAsSet->getPropertyValue(PROPERTY_NAME) >>= aBoundFieldName;
750 aBoundColumn.reset( 1 );
752 xFieldAsSet.set(xFieldsByIndex->getByIndex(0),UNO_QUERY);
753 xFieldAsSet->getPropertyValue(PROPERTY_NAME) >>= aFieldName;
755 else if (xFieldsByName.is())
757 if ( xFieldsByName->hasByName( getControlSource() ) )
758 aFieldName = getControlSource();
759 else
761 // otherwise look for the alias
762 Reference< XColumnsSupplier > xSupplyFields;
763 xFormProps->getPropertyValue("SingleSelectQueryComposer") >>= xSupplyFields;
765 // search the field
766 DBG_ASSERT(xSupplyFields.is(), "OListBoxModel::loadData : invalid query composer !");
768 Reference<XNameAccess> xFieldNames = xSupplyFields->getColumns();
769 if ( xFieldNames->hasByName( getControlSource() ) )
771 Reference<XPropertySet> xComposerFieldAsSet;
772 xFieldNames->getByName( getControlSource() ) >>= xComposerFieldAsSet;
773 if (hasProperty(PROPERTY_FIELDSOURCE, xComposerFieldAsSet))
774 xComposerFieldAsSet->getPropertyValue(PROPERTY_FIELDSOURCE) >>= aFieldName;
778 if (aFieldName.isEmpty())
779 break;
781 Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
782 OUString aQuote = xMeta->getIdentifierQuoteString();
783 OUString aStatement("SELECT ");
784 if (aBoundFieldName.isEmpty()) // act like a combobox
785 aStatement += "DISTINCT ";
787 aStatement += quoteName(aQuote,aFieldName);
788 if (!aBoundFieldName.isEmpty())
790 aStatement += ", ";
791 aStatement += quoteName(aQuote, aBoundFieldName);
793 aStatement += " FROM ";
795 OUString sCatalog, sSchema, sTable;
796 qualifiedNameComponents( xMeta, sListSource, sCatalog, sSchema, sTable, eInDataManipulation );
797 aStatement += composeTableNameForSelect( xConnection, sCatalog, sSchema, sTable );
799 m_aListRowSet.setEscapeProcessing( false );
800 m_aListRowSet.setCommand( aStatement );
801 bExecute = true;
803 break;
805 case ListSourceType_QUERY:
806 m_aListRowSet.setCommandFromQuery( sListSource );
807 bExecute = true;
808 break;
810 default:
811 m_aListRowSet.setEscapeProcessing( ListSourceType_SQLPASSTHROUGH != m_eListSourceType );
812 m_aListRowSet.setCommand( sListSource );
813 bExecute = true;
814 break;
817 if (bExecute)
819 if ( !_bForce && !m_aListRowSet.isDirty() )
821 // if none of the settings of the row set changed, compared to the last
822 // invocation of loadData, then don't re-fill the list. Instead, assume
823 // the list entries are the same.
824 m_nNULLPos = nNULLPosBackup;
825 m_nBoundColumnType = nBoundColumnTypeBackup;
826 return;
828 xListCursor.reset( m_aListRowSet.execute() );
831 catch(const SQLException& eSQL)
833 onError(eSQL, FRM_RES_STRING(RID_BASELISTBOX_ERROR_FILLLIST));
834 return;
836 catch(const Exception& eUnknown)
838 (void)eUnknown;
839 return;
842 // Fill display and value lists
843 ValueList aDisplayList, aValueList;
844 bool bUseNULL = hasField() && !isRequired();
846 // empty BoundColumn is treated as BoundColumn==0,
847 if(!aBoundColumn)
848 aBoundColumn = 0;
852 OSL_ENSURE( xListCursor.is() || ( ListSourceType_TABLEFIELDS == m_eListSourceType ),
853 "OListBoxModel::loadData: logic error!" );
854 if ( !xListCursor.is() && ( ListSourceType_TABLEFIELDS != m_eListSourceType ) )
855 return;
857 switch (m_eListSourceType)
859 #if HAVE_FEATURE_DBCONNECTIVITY
860 case ListSourceType_SQL:
861 case ListSourceType_SQLPASSTHROUGH:
862 case ListSourceType_TABLE:
863 case ListSourceType_QUERY:
865 // Get field of the ResultSet's 1st column
866 Reference<XColumnsSupplier> xSupplyCols(xListCursor, UNO_QUERY);
867 DBG_ASSERT(xSupplyCols.is(), "OListBoxModel::loadData : cursor supports the row set service but is no column supplier?!");
868 Reference<XIndexAccess> xColumns;
869 if (xSupplyCols.is())
871 xColumns = Reference<XIndexAccess>(xSupplyCols->getColumns(), UNO_QUERY);
872 DBG_ASSERT(xColumns.is(), "OListBoxModel::loadData : no columns supplied by the row set !");
875 Reference< XPropertySet > xDataField;
876 if ( xColumns.is() )
877 xColumns->getByIndex(0) >>= xDataField;
878 if ( !xDataField.is() )
879 return;
881 ::dbtools::FormattedColumnValue aValueFormatter( getContext(), m_xCursor, xDataField );
883 // Get the field of BoundColumn of the ResultSet
884 m_nBoundColumnType = DataType::SQLNULL;
885 if ( *aBoundColumn >= 0 )
889 Reference< XPropertySet > xBoundField( xColumns->getByIndex( *aBoundColumn ), UNO_QUERY_THROW );
890 OSL_VERIFY( xBoundField->getPropertyValue("Type") >>= m_nBoundColumnType );
892 catch( const Exception& )
894 DBG_UNHANDLED_EXCEPTION();
897 else if ( *aBoundColumn == -1)
898 m_nBoundColumnType = DataType::SMALLINT;
900 // If the LB is bound to a field and empty entries are valid, we remember the position
901 // for an empty entry
902 SAL_INFO( "forms.component", "OListBoxModel::loadData: string collection" );
903 OUString aStr;
904 sal_Int16 entryPos = 0;
905 ORowSetValue aBoundValue;
906 Reference< XRow > xCursorRow( xListCursor, UNO_QUERY_THROW );
907 while ( xListCursor->next() && ( entryPos++ < SHRT_MAX ) ) // SHRT_MAX is the maximum number of entries
909 aStr = aValueFormatter.getFormattedValue();
910 aDisplayList.push_back( aStr );
912 if(*aBoundColumn >= 0)
913 aBoundValue.fill( *aBoundColumn + 1, m_nBoundColumnType, xCursorRow );
914 else
915 // -1 because getRow() is 1-indexed, but ListBox positions are 0-indexed
916 aBoundValue = static_cast<sal_Int16>(xListCursor->getRow()-1);
917 aValueList.push_back( aBoundValue );
919 if ( m_nNULLPos == -1 && aBoundValue.isNull() )
920 m_nNULLPos = sal_Int16( aDisplayList.size() - 1 );
921 if ( bUseNULL && ( m_nNULLPos == -1 ) && aStr.isEmpty() )
922 // There is already a non-NULL entry with empty display string;
923 // adding another one for NULL would make things confusing,
924 // so back off.
925 bUseNULL = false;
928 break;
929 #endif
930 case ListSourceType_TABLEFIELDS:
932 Reference<XNameAccess> xFieldNames = getTableFields(xConnection, sListSource);
933 if (xFieldNames.is())
935 StringSequence seqNames = xFieldNames->getElementNames();
936 ::std::copy(
937 seqNames.getConstArray(),
938 seqNames.getConstArray() + seqNames.getLength(),
939 ::std::insert_iterator< ValueList >( aDisplayList, aDisplayList.end() )
941 if(*aBoundColumn == -1)
943 // the type of i matters! It will be the type of the ORowSetValue pushed to aValueList!
944 for(sal_Int16 i=0; static_cast<ValueList::size_type>(i) < aDisplayList.size(); ++i)
946 aValueList.push_back(i);
949 else
951 aValueList = aDisplayList;
955 break;
956 default:
957 SAL_WARN( "forms.component", "OListBoxModel::loadData: unreachable!" );
958 break;
961 catch(const SQLException& eSQL)
963 onError(eSQL, FRM_RES_STRING(RID_BASELISTBOX_ERROR_FILLLIST));
964 return;
966 catch( const Exception& )
968 DBG_UNHANDLED_EXCEPTION();
969 return;
973 // Create Values sequence
974 // Add NULL entry
975 if (bUseNULL && m_nNULLPos == -1)
977 aValueList.insert( aValueList.begin(), ORowSetValue() );
979 aDisplayList.insert( aDisplayList.begin(), ORowSetValue( OUString() ) );
980 m_nNULLPos = 0;
983 setBoundValues(aValueList);
985 setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( lcl_convertToStringSequence( aDisplayList ) ) );
989 void OListBoxModel::onConnectedDbColumn( const Reference< XInterface >& /*_rxForm*/ )
991 // list boxes which are bound to a db column don't have multi selection
992 // - this would be unable to reflect in the db column
993 if ( hasField() )
995 setFastPropertyValue( PROPERTY_ID_MULTISELECTION, css::uno::Any(false) );
998 if ( !hasExternalListSource() )
999 impl_refreshDbEntryList( false );
1003 void OListBoxModel::onDisconnectedDbColumn()
1005 clearBoundValues();
1006 m_nNULLPos = -1;
1007 m_nBoundColumnType = DataType::SQLNULL;
1009 if ( m_eListSourceType != ListSourceType_VALUELIST )
1011 if ( !hasExternalListSource() )
1012 setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( StringSequence() ) );
1014 m_aListRowSet.dispose();
1019 void OListBoxModel::setBoundValues(const ValueList &l)
1021 m_aConvertedBoundValues.clear();
1022 m_aBoundValues = l;
1026 void OListBoxModel::clearBoundValues()
1028 ValueList().swap(m_aConvertedBoundValues);
1029 ValueList().swap(m_aBoundValues);
1033 void OListBoxModel::convertBoundValues(const sal_Int32 nFieldType) const
1035 assert(s_aEmptyValue.isNull());
1036 m_nNULLPos = -1;
1037 m_aConvertedBoundValues.resize(m_aBoundValues.size());
1038 ValueList::const_iterator src = m_aBoundValues.begin();
1039 const ValueList::const_iterator end = m_aBoundValues.end();
1040 ValueList::iterator dst = m_aConvertedBoundValues.begin();
1041 for (; src != end; ++src, ++dst )
1043 if(m_nNULLPos == -1 &&
1044 !isRequired() &&
1045 (*src == s_aEmptyStringValue || *src == s_aEmptyValue || src->isNull()) )
1047 m_nNULLPos = src - m_aBoundValues.begin();
1048 dst->setNull();
1050 else
1052 *dst = *src;
1054 dst->setTypeKind(nFieldType);
1056 m_nConvertedBoundValuesType = nFieldType;
1057 OSL_ENSURE(dst == m_aConvertedBoundValues.end(), "OListBoxModel::convertBoundValues expected to have overwritten all of m_aConvertedBoundValues, but did not.");
1058 assert(dst == m_aConvertedBoundValues.end());
1061 sal_Int32 OListBoxModel::getValueType() const
1063 return impl_hasBoundComponent() ? m_nBoundColumnType : getFieldType();
1066 ValueList OListBoxModel::impl_getValues() const
1068 const sal_Int32 nFieldType = getValueType();
1070 if ( !m_aConvertedBoundValues.empty() && m_nConvertedBoundValuesType == nFieldType )
1071 return m_aConvertedBoundValues;
1073 if ( !m_aBoundValues.empty() )
1075 convertBoundValues(nFieldType);
1076 return m_aConvertedBoundValues;
1079 Sequence< OUString > aStringItems( getStringItemList() );
1080 ValueList aValues( aStringItems.getLength() );
1081 ValueList::iterator dst = aValues.begin();
1082 const OUString *src (aStringItems.getConstArray());
1083 const OUString * const end = src + aStringItems.getLength();
1084 for (; src < end; ++src, ++dst )
1086 *dst = *src;
1087 dst->setTypeKind(nFieldType);
1089 m_nConvertedBoundValuesType = nFieldType;
1090 OSL_ENSURE(dst == aValues.end(), "OListBoxModel::impl_getValues expected to have set all of aValues, but did not.");
1091 assert(dst == aValues.end());
1092 return aValues;
1095 ORowSetValue OListBoxModel::getFirstSelectedValue() const
1097 DBG_ASSERT( m_xAggregateFastSet.is(), "OListBoxModel::getFirstSelectedValue: invalid aggregate!" );
1098 if ( !m_xAggregateFastSet.is() )
1099 return s_aEmptyValue;
1101 Sequence< sal_Int16 > aSelectedIndices;
1102 OSL_VERIFY( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) >>= aSelectedIndices );
1103 if ( !aSelectedIndices.getLength() )
1104 // nothing selected at all
1105 return s_aEmptyValue;
1107 if ( ( m_nNULLPos != -1 ) && ( aSelectedIndices[0] == m_nNULLPos ) )
1108 // the dedicated "NULL" entry is selected
1109 return s_aEmptyValue;
1111 ValueList aValues( impl_getValues() );
1113 size_t selectedValue = aSelectedIndices[0];
1114 if ( selectedValue >= aValues.size() )
1116 SAL_WARN( "forms.component", "OListBoxModel::getFirstSelectedValue: inconsistent selection/valuelist!" );
1117 return s_aEmptyValue;
1120 return aValues[ selectedValue ];
1124 bool OListBoxModel::commitControlValueToDbColumn( bool /*_bPostReset*/ )
1126 // current selection list
1127 const ORowSetValue aCurrentValue( getFirstSelectedValue() );
1128 if ( aCurrentValue != m_aSaveValue )
1130 if ( aCurrentValue.isNull() )
1131 m_xColumnUpdate->updateNull();
1132 else
1136 m_xColumnUpdate->updateObject( aCurrentValue.makeAny() );
1138 catch ( const Exception& )
1140 return false;
1143 m_aSaveValue = aCurrentValue;
1145 return true;
1149 Sequence< sal_Int16 > OListBoxModel::translateDbValueToControlValue(const ORowSetValue &i_aValue) const
1151 Sequence< sal_Int16 > aSelectionIndicies;
1153 // reset selection for NULL values
1154 if ( i_aValue.isNull() )
1156 if ( m_nNULLPos != -1 )
1158 aSelectionIndicies.realloc(1);
1159 aSelectionIndicies[0] = m_nNULLPos;
1162 else
1164 ValueList aValues( impl_getValues() );
1165 assert( m_nConvertedBoundValuesType == getValueType());
1166 ORowSetValue v(i_aValue);
1167 v.setTypeKind( m_nConvertedBoundValuesType );
1168 ValueList::const_iterator curValuePos = ::std::find( aValues.begin(), aValues.end(), v );
1169 if ( curValuePos != aValues.end() )
1171 aSelectionIndicies.realloc( 1 );
1172 aSelectionIndicies[0] = curValuePos - aValues.begin();
1176 return aSelectionIndicies;
1179 Sequence< sal_Int16 > OListBoxModel::translateBindingValuesToControlValue(const Sequence< const Any > &i_aValues) const
1181 const ValueList aValues( impl_getValues() );
1182 assert( m_nConvertedBoundValuesType == getValueType());
1183 Sequence< sal_Int16 > aSelectionIndicies(i_aValues.getLength());
1185 sal_Int32 nCount(0);
1187 #if HAVE_FEATURE_DBCONNECTIVITY
1188 sal_Int16 *pIndex = aSelectionIndicies.getArray();
1189 const Any *pValue = i_aValues.getConstArray();
1190 const Any * const pValueEnd = i_aValues.getConstArray() + i_aValues.getLength();
1191 for (;pValue < pValueEnd; ++pValue)
1193 if ( pValue->hasValue() )
1195 ORowSetValue v;
1196 v.fill(*pValue);
1197 v.setTypeKind( m_nConvertedBoundValuesType );
1198 ValueList::const_iterator curValuePos = ::std::find( aValues.begin(), aValues.end(), v );
1199 if ( curValuePos != aValues.end() )
1201 *pIndex = curValuePos - aValues.begin();
1202 ++pIndex;
1203 ++nCount;
1206 else
1208 if ( m_nNULLPos != -1 )
1210 *pIndex = m_nNULLPos;
1211 ++pIndex;
1212 ++nCount;
1216 assert(aSelectionIndicies.getArray() + nCount == pIndex);
1217 #endif
1218 aSelectionIndicies.realloc(nCount);
1219 return aSelectionIndicies;
1222 Any OListBoxModel::translateDbColumnToControlValue()
1224 #if HAVE_FEATURE_DBCONNECTIVITY
1225 Reference< XPropertySet > xBoundField( getField() );
1226 if ( !xBoundField.is() )
1228 SAL_WARN( "forms.component", "OListBoxModel::translateDbColumnToControlValue: no field? How could that happen?!" );
1229 return Any();
1232 ORowSetValue aCurrentValue;
1233 aCurrentValue.fill( getValueType(), m_xColumn );
1235 m_aSaveValue = aCurrentValue;
1237 return makeAny( translateDbValueToControlValue(aCurrentValue) );
1238 #else
1239 return Any();
1240 #endif
1243 // XReset
1245 Any OListBoxModel::getDefaultForReset() const
1247 Any aValue;
1248 if (m_aDefaultSelectSeq.getLength())
1249 aValue <<= m_aDefaultSelectSeq;
1250 else if (m_nNULLPos != -1) // bound Listbox
1252 Sequence<sal_Int16> aSeq(1);
1253 aSeq.getArray()[0] = m_nNULLPos;
1254 aValue <<= aSeq;
1256 else
1258 Sequence<sal_Int16> aSeq;
1259 aValue <<= aSeq;
1262 return aValue;
1266 void OListBoxModel::resetNoBroadcast()
1268 OBoundControlModel::resetNoBroadcast();
1269 m_aSaveValue.setNull();
1273 void SAL_CALL OListBoxModel::disposing( const EventObject& _rSource ) throw ( RuntimeException, std::exception )
1275 if ( !OEntryListHelper::handleDisposing( _rSource ) )
1276 OBoundControlModel::disposing( _rSource );
1280 namespace
1282 // The type of how we should transfer our selection to external value bindings
1283 enum ExchangeType
1285 eIndexList, /// as list of indexes of selected entries
1286 eIndex, /// as index of the selected entry
1287 eEntryList, /// as list of string representations of selected *display* entries
1288 eEntry, /// as string representation of the selected *display* entry
1289 eValueList, /// as list of string representations of selected values
1290 eValue /// as string representation of the selected value
1294 ExchangeType lcl_getCurrentExchangeType( const Type& _rExchangeType )
1296 switch ( _rExchangeType.getTypeClass() )
1298 case TypeClass_ANY:
1299 return eValue;
1300 case TypeClass_STRING:
1301 return eEntry;
1302 case TypeClass_LONG:
1303 return eIndex;
1304 case TypeClass_SEQUENCE:
1306 Type aElementType = ::comphelper::getSequenceElementType( _rExchangeType );
1307 switch ( aElementType.getTypeClass() )
1309 case TypeClass_ANY:
1310 return eValueList;
1311 case TypeClass_STRING:
1312 return eEntryList;
1313 case TypeClass_LONG:
1314 return eIndexList;
1315 default:
1316 break;
1319 default:
1320 break;
1322 SAL_WARN( "forms.component", "lcl_getCurrentExchangeType: unsupported (unexpected) exchange type!" );
1323 return eEntry;
1328 Any OListBoxModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const
1330 Sequence< sal_Int16 > aSelectIndexes;
1332 switch ( lcl_getCurrentExchangeType( getExternalValueType() ) )
1334 case eValueList:
1336 Sequence< const Any > aExternalValues;
1337 OSL_VERIFY( _rExternalValue >>= aExternalValues );
1338 aSelectIndexes = translateBindingValuesToControlValue( aExternalValues );
1340 break;
1342 case eValue:
1343 #if HAVE_FEATURE_DBCONNECTIVITY
1345 ORowSetValue v;
1346 v.fill(_rExternalValue);
1347 aSelectIndexes = translateDbValueToControlValue(v);
1349 #endif
1350 break;
1352 case eIndexList:
1354 // unfortunately, our select sequence is a sequence<short>, while the external binding
1355 // supplies sequence<int> only -> transform this
1356 Sequence< sal_Int32 > aSelectIndexesPure;
1357 OSL_VERIFY( _rExternalValue >>= aSelectIndexesPure );
1358 aSelectIndexes.realloc( aSelectIndexesPure.getLength() );
1359 ::std::copy(
1360 aSelectIndexesPure.getConstArray(),
1361 aSelectIndexesPure.getConstArray() + aSelectIndexesPure.getLength(),
1362 aSelectIndexes.getArray()
1365 break;
1367 case eIndex:
1369 sal_Int32 nSelectIndex = -1;
1370 OSL_VERIFY( _rExternalValue >>= nSelectIndex );
1371 if ( ( nSelectIndex >= 0 ) && ( nSelectIndex < getStringItemList().getLength() ) )
1373 aSelectIndexes.realloc( 1 );
1374 aSelectIndexes[ 0 ] = static_cast< sal_Int16 >( nSelectIndex );
1377 break;
1379 case eEntryList:
1381 // we can retrieve a string list from the binding for multiple selection
1382 Sequence< OUString > aSelectEntries;
1383 OSL_VERIFY( _rExternalValue >>= aSelectEntries );
1385 ::std::set< sal_Int16 > aSelectionSet;
1387 // find the selection entries in our item list
1388 const OUString* pSelectEntries = aSelectEntries.getArray();
1389 const OUString* pSelectEntriesEnd = pSelectEntries + aSelectEntries.getLength();
1390 while ( pSelectEntries != pSelectEntriesEnd )
1392 // the indexes where the current string appears in our string items
1393 Sequence< sal_Int16 > aThisEntryIndexes;
1394 aThisEntryIndexes = findValue( getStringItemList(), *pSelectEntries++, false );
1396 // insert all the indexes of this entry into our set
1397 ::std::copy(
1398 aThisEntryIndexes.getConstArray(),
1399 aThisEntryIndexes.getConstArray() + aThisEntryIndexes.getLength(),
1400 ::std::insert_iterator< ::std::set< sal_Int16 > >( aSelectionSet, aSelectionSet.begin() )
1404 // copy the indexes to the sequence
1405 aSelectIndexes.realloc( aSelectionSet.size() );
1406 ::std::copy(
1407 aSelectionSet.begin(),
1408 aSelectionSet.end(),
1409 aSelectIndexes.getArray()
1412 break;
1414 case eEntry:
1416 OUString sStringToSelect;
1417 OSL_VERIFY( _rExternalValue >>= sStringToSelect );
1419 aSelectIndexes = findValue( getStringItemList(), sStringToSelect, false );
1421 break;
1424 return makeAny( aSelectIndexes );
1428 namespace
1431 struct ExtractStringFromSequence_Safe : public ::std::unary_function< sal_Int16, OUString >
1433 protected:
1434 const Sequence< OUString >& m_rList;
1436 public:
1437 ExtractStringFromSequence_Safe( const Sequence< OUString >& _rList ) : m_rList( _rList ) { }
1439 OUString operator ()( sal_Int16 _nIndex )
1441 OSL_ENSURE( _nIndex < m_rList.getLength(), "ExtractStringFromSequence_Safe: inconsistence!" );
1442 if ( _nIndex < m_rList.getLength() )
1443 return m_rList[ _nIndex ];
1444 return OUString();
1449 Any lcl_getSingleSelectedEntry( const Sequence< sal_Int16 >& _rSelectSequence, const Sequence< OUString >& _rStringList )
1451 Any aReturn;
1453 // by definition, multiple selected entries are transferred as NULL if the
1454 // binding does not support string lists
1455 if ( _rSelectSequence.getLength() <= 1 )
1457 OUString sSelectedEntry;
1459 if ( _rSelectSequence.getLength() == 1 )
1460 sSelectedEntry = ExtractStringFromSequence_Safe( _rStringList )( _rSelectSequence[0] );
1462 aReturn <<= sSelectedEntry;
1465 return aReturn;
1469 Any lcl_getMultiSelectedEntries( const Sequence< sal_Int16 >& _rSelectSequence, const Sequence< OUString >& _rStringList )
1471 Sequence< OUString > aSelectedEntriesTexts( _rSelectSequence.getLength() );
1472 ::std::transform(
1473 _rSelectSequence.getConstArray(),
1474 _rSelectSequence.getConstArray() + _rSelectSequence.getLength(),
1475 aSelectedEntriesTexts.getArray(),
1476 ExtractStringFromSequence_Safe( _rStringList )
1478 return makeAny( aSelectedEntriesTexts );
1482 struct ExtractAnyFromValueList_Safe : public ::std::unary_function< sal_Int16, Any >
1484 protected:
1485 const ValueList& m_rList;
1487 public:
1488 ExtractAnyFromValueList_Safe( const ValueList& _rList ) : m_rList( _rList ) { }
1490 Any operator ()( sal_Int16 _nIndex )
1492 OSL_ENSURE( static_cast<ValueList::size_type>(_nIndex) < m_rList.size(), "ExtractAnyFromValueList: inconsistence!" );
1493 if ( static_cast<ValueList::size_type>(_nIndex) < m_rList.size() )
1494 return m_rList[ _nIndex ].makeAny();
1495 return Any();
1500 Any lcl_getSingleSelectedEntryAny( const Sequence< sal_Int16 >& _rSelectSequence, const ValueList& _rStringList )
1502 Any aReturn;
1504 // by definition, multiple selected entries are transferred as NULL if the
1505 // binding does not support string lists
1506 if ( _rSelectSequence.getLength() <= 1 )
1508 if ( _rSelectSequence.getLength() == 1 )
1509 aReturn = ExtractAnyFromValueList_Safe( _rStringList )( _rSelectSequence[0] );
1512 return aReturn;
1516 Any lcl_getMultiSelectedEntriesAny( const Sequence< sal_Int16 >& _rSelectSequence, const ValueList& _rStringList )
1518 Sequence< Any > aSelectedEntriesValues( _rSelectSequence.getLength() );
1519 ::std::transform(
1520 _rSelectSequence.getConstArray(),
1521 _rSelectSequence.getConstArray() + _rSelectSequence.getLength(),
1522 aSelectedEntriesValues.getArray(),
1523 ExtractAnyFromValueList_Safe( _rStringList )
1525 return makeAny( aSelectedEntriesValues );
1530 Any OListBoxModel::translateControlValueToExternalValue( ) const
1532 OSL_PRECOND( hasExternalValueBinding(), "OListBoxModel::translateControlValueToExternalValue: no binding!" );
1534 Sequence< sal_Int16 > aSelectSequence;
1535 OSL_VERIFY( getControlValue() >>= aSelectSequence );
1537 Any aReturn;
1538 switch ( lcl_getCurrentExchangeType( getExternalValueType() ) )
1540 case eValueList:
1541 aReturn = getCurrentMultiValue();
1542 break;
1544 case eValue:
1545 aReturn = getCurrentSingleValue();
1546 break;
1548 case eIndexList:
1550 // unfortunately, the select sequence is a sequence<short>, but our binding
1551 // expects int's
1552 Sequence< sal_Int32 > aTransformed( aSelectSequence.getLength() );
1553 ::std::copy(
1554 aSelectSequence.getConstArray(),
1555 aSelectSequence.getConstArray() + aSelectSequence.getLength(),
1556 aTransformed.getArray()
1558 aReturn <<= aTransformed;
1560 break;
1562 case eIndex:
1563 if ( aSelectSequence.getLength() <= 1 )
1565 sal_Int32 nIndex = -1;
1567 if ( aSelectSequence.getLength() == 1 )
1568 nIndex = aSelectSequence[0];
1570 aReturn <<= nIndex;
1572 break;
1574 case eEntryList:
1575 aReturn = lcl_getMultiSelectedEntries( aSelectSequence, getStringItemList() );
1576 break;
1578 case eEntry:
1579 aReturn = lcl_getSingleSelectedEntry( aSelectSequence, getStringItemList() );
1580 break;
1583 return aReturn;
1587 Any OListBoxModel::translateControlValueToValidatableValue( ) const
1589 OSL_PRECOND( hasValidator(), "OListBoxModel::translateControlValueToValidatableValue: no validator, so why should I?" );
1590 return getCurrentFormComponentValue();
1594 Any OListBoxModel::getCurrentSingleValue() const
1596 Any aCurrentValue;
1600 Sequence< sal_Int16 > aSelectSequence;
1601 OSL_VERIFY( getControlValue() >>= aSelectSequence );
1602 aCurrentValue = lcl_getSingleSelectedEntryAny( aSelectSequence, impl_getValues() );
1604 catch( const Exception& )
1606 DBG_UNHANDLED_EXCEPTION();
1609 return aCurrentValue;
1612 Any OListBoxModel::getCurrentMultiValue() const
1614 Any aCurrentValue;
1618 Sequence< sal_Int16 > aSelectSequence;
1619 OSL_VERIFY( getControlValue() >>= aSelectSequence );
1620 aCurrentValue = lcl_getMultiSelectedEntriesAny( aSelectSequence, impl_getValues() );
1622 catch( const Exception& )
1624 DBG_UNHANDLED_EXCEPTION();
1627 return aCurrentValue;
1630 Any OListBoxModel::getCurrentFormComponentValue() const
1633 Reference< com::sun::star::form::validation::XValidator > vtor (const_cast<OListBoxModel*>(this)->getValidator());
1634 Reference< XValueBinding > extBinding (const_cast<OListBoxModel*>(this)->getValueBinding());
1635 if ( vtor.is() && vtor == extBinding )
1636 return translateControlValueToExternalValue();
1639 Any aCurrentValue;
1643 bool bMultiSelection( false );
1644 OSL_VERIFY( const_cast< OListBoxModel* >( this )->getPropertyValue( PROPERTY_MULTISELECTION ) >>= bMultiSelection );
1646 if ( bMultiSelection )
1647 aCurrentValue = getCurrentMultiValue();
1648 else
1649 aCurrentValue = getCurrentSingleValue();
1651 catch( const Exception& )
1653 DBG_UNHANDLED_EXCEPTION();
1656 return aCurrentValue;
1660 Sequence< Type > OListBoxModel::getSupportedBindingTypes()
1662 Sequence< Type > aTypes(6);
1663 aTypes[0] = cppu::UnoType<Sequence< Any >>::get();
1664 aTypes[1] = cppu::UnoType<Any>::get();
1665 aTypes[2] = cppu::UnoType<Sequence< sal_Int32 >>::get();
1666 aTypes[3] = cppu::UnoType<sal_Int32>::get();
1667 aTypes[4] = cppu::UnoType<Sequence< OUString >>::get();
1668 aTypes[5] = cppu::UnoType<OUString>::get();
1669 return aTypes;
1673 void OListBoxModel::stringItemListChanged( ControlModelLock& _rInstanceLock )
1675 if ( !m_xAggregateSet.is() )
1676 return;
1678 suspendValueListening();
1681 m_xAggregateSet->setPropertyValue( PROPERTY_STRINGITEMLIST, makeAny( getStringItemList() ) );
1683 catch( const Exception& )
1685 DBG_UNHANDLED_EXCEPTION();
1687 resumeValueListening();
1689 // update the selection here
1690 if ( hasExternalValueBinding( ) )
1691 transferExternalValueToControl( _rInstanceLock );
1692 else
1694 if ( hasField() )
1696 // TODO: update the selection in case we're bound to a database column
1698 else
1700 if ( m_aDefaultSelectSeq.getLength() )
1701 setControlValue( makeAny( m_aDefaultSelectSeq ), eOther );
1707 void OListBoxModel::connectedExternalListSource( )
1709 // TODO?
1713 void OListBoxModel::disconnectedExternalListSource( )
1715 // TODO: in case we're part of an already loaded form, we should probably simulate
1716 // an onConnectedDbColumn, so our list get's filled with the data as indicated
1717 // by our SQL-binding related properties
1721 void OListBoxModel::impl_refreshDbEntryList( bool _bForce )
1723 DBG_ASSERT( !hasExternalListSource(), "OListBoxModel::impl_refreshDbEntryList: invalid call!" );
1725 if ( !hasExternalListSource( )
1726 && ( m_eListSourceType != ListSourceType_VALUELIST )
1727 && ( m_xCursor.is() )
1730 loadData( _bForce );
1735 void OListBoxModel::refreshInternalEntryList()
1737 impl_refreshDbEntryList( true );
1738 if ( hasField() && m_xCursor.is() )
1739 initFromField( m_xCursor );
1743 // OListBoxControl
1745 Sequence< Type> OListBoxControl::_getTypes()
1747 return TypeBag(
1748 OBoundControl::_getTypes(),
1749 OListBoxControl_BASE::getTypes()
1750 ).getTypes();
1754 Any SAL_CALL OListBoxControl::queryAggregation(const Type& _rType) throw (RuntimeException, std::exception)
1756 Any aReturn = OListBoxControl_BASE::queryInterface( _rType );
1758 if ( !aReturn.hasValue()
1759 || _rType.equals( cppu::UnoType<XTypeProvider>::get() )
1761 aReturn = OBoundControl::queryAggregation( _rType );
1763 return aReturn;
1767 OListBoxControl::OListBoxControl(const Reference<XComponentContext>& _rxFactory)
1768 :OBoundControl( _rxFactory, VCL_CONTROL_LISTBOX, false )
1769 ,m_aChangeListeners( m_aMutex )
1770 ,m_aItemListeners( m_aMutex )
1773 osl_atomic_increment(&m_refCount);
1775 // Register as FocusListener
1776 Reference<XWindow> xComp;
1777 if (query_aggregation(m_xAggregate, xComp))
1778 xComp->addFocusListener(this);
1780 // Register as ItemListener
1781 if ( query_aggregation( m_xAggregate, m_xAggregateListBox ) )
1782 m_xAggregateListBox->addItemListener(this);
1784 // Refcount at 2 for registered Listener
1785 osl_atomic_decrement(&m_refCount);
1787 doSetDelegator();
1789 m_aChangeIdle.SetPriority(SchedulerPriority::LOWEST);
1790 m_aChangeIdle.SetIdleHdl(LINK(this,OListBoxControl,OnTimeout));
1794 OListBoxControl::~OListBoxControl()
1796 if (!OComponentHelper::rBHelper.bDisposed)
1798 acquire();
1799 dispose();
1802 doResetDelegator();
1803 m_xAggregateListBox.clear();
1808 StringSequence SAL_CALL OListBoxControl::getSupportedServiceNames() throw(RuntimeException, std::exception)
1810 StringSequence aSupported = OBoundControl::getSupportedServiceNames();
1811 aSupported.realloc(aSupported.getLength() + 2);
1813 OUString* pArray = aSupported.getArray();
1814 pArray[aSupported.getLength()-2] = FRM_SUN_CONTROL_LISTBOX;
1815 pArray[aSupported.getLength()-1] = STARDIV_ONE_FORM_CONTROL_LISTBOX;
1816 return aSupported;
1820 // XFocusListener
1822 void SAL_CALL OListBoxControl::focusGained(const FocusEvent& /*_rEvent*/) throw(RuntimeException, std::exception)
1824 ::osl::MutexGuard aGuard(m_aMutex);
1825 if ( m_aChangeListeners.getLength() ) // only if there are listeners
1827 Reference<XPropertySet> xSet(getModel(), UNO_QUERY);
1828 if (xSet.is())
1830 // memorize the current selection for posting the change event
1831 m_aCurrentSelection = xSet->getPropertyValue(PROPERTY_SELECT_SEQ);
1837 void SAL_CALL OListBoxControl::focusLost(const FocusEvent& /*_rEvent*/) throw(RuntimeException, std::exception)
1839 m_aCurrentSelection.clear();
1842 // XItemListener
1844 void SAL_CALL OListBoxControl::itemStateChanged(const ItemEvent& _rEvent) throw(RuntimeException, std::exception)
1846 // forward this to our listeners
1847 Reference< XChild > xChild( getModel(), UNO_QUERY );
1848 if ( xChild.is() && xChild->getParent().is() )
1850 ::osl::MutexGuard aGuard( m_aMutex );
1851 if ( m_aItemListeners.getLength() )
1853 if ( !m_pItemBroadcaster.is() )
1855 m_pItemBroadcaster.set(
1856 new ::comphelper::AsyncEventNotifier("ListBox"));
1857 m_pItemBroadcaster->launch();
1859 m_pItemBroadcaster->addEvent( new ItemEventDescription( _rEvent ), this );
1862 else
1863 m_aItemListeners.notifyEach( &XItemListener::itemStateChanged, _rEvent );
1865 // and do the handling for the ChangeListeners
1866 ::osl::ClearableMutexGuard aGuard(m_aMutex);
1867 if ( m_aChangeIdle.IsActive() )
1869 Reference<XPropertySet> xSet(getModel(), UNO_QUERY);
1870 m_aCurrentSelection = xSet->getPropertyValue(PROPERTY_SELECT_SEQ);
1872 m_aChangeIdle.Stop();
1873 m_aChangeIdle.Start();
1875 else
1877 if ( m_aChangeListeners.getLength() && m_aCurrentSelection.hasValue() )
1879 Reference<XPropertySet> xSet(getModel(), UNO_QUERY);
1880 if (xSet.is())
1882 // Has the selection been changed?
1883 bool bModified(false);
1884 Any aValue = xSet->getPropertyValue(PROPERTY_SELECT_SEQ);
1886 Sequence<sal_Int16> const & rSelection = *static_cast<Sequence<sal_Int16> const *>(aValue.getValue());
1887 Sequence<sal_Int16> const & rOldSelection = *static_cast<Sequence<sal_Int16> const *>(m_aCurrentSelection.getValue());
1888 sal_Int32 nLen = rSelection.getLength();
1889 if (nLen != rOldSelection.getLength())
1890 bModified = true;
1891 else
1893 const sal_Int16* pVal = rSelection.getConstArray();
1894 const sal_Int16* pCompVal = rOldSelection.getConstArray();
1896 while (nLen-- && !bModified)
1897 bModified = pVal[nLen] != pCompVal[nLen];
1900 if (bModified)
1902 m_aCurrentSelection = aValue;
1903 m_aChangeIdle.Start();
1907 else if (m_aCurrentSelection.hasValue())
1908 m_aCurrentSelection.clear();
1912 // XEventListener
1914 void SAL_CALL OListBoxControl::disposing(const EventObject& _rSource) throw (RuntimeException, std::exception)
1916 OBoundControl::disposing(_rSource);
1919 // XChangeBroadcaster
1921 void SAL_CALL OListBoxControl::addChangeListener(const Reference<XChangeListener>& _rxListener) throw(RuntimeException, std::exception)
1923 m_aChangeListeners.addInterface( _rxListener );
1927 void SAL_CALL OListBoxControl::removeChangeListener(const Reference<XChangeListener>& _rxListener) throw(RuntimeException, std::exception)
1929 m_aChangeListeners.removeInterface( _rxListener );
1932 // OComponentHelper
1934 void OListBoxControl::disposing()
1936 if (m_aChangeIdle.IsActive())
1937 m_aChangeIdle.Stop();
1939 EventObject aEvent( *this );
1940 m_aChangeListeners.disposeAndClear( aEvent );
1941 m_aItemListeners.disposeAndClear( aEvent );
1943 rtl::Reference< comphelper::AsyncEventNotifier > t;
1945 ::osl::MutexGuard aGuard( m_aMutex );
1946 if ( m_pItemBroadcaster.is() )
1948 t = m_pItemBroadcaster;
1949 m_pItemBroadcaster->removeEventsForProcessor( this );
1950 m_pItemBroadcaster->terminate();
1951 m_pItemBroadcaster = NULL;
1954 if (t.is()) {
1955 t->join();
1958 OBoundControl::disposing();
1962 void OListBoxControl::processEvent( const AnyEvent& _rEvent )
1964 Reference< XListBox > xKeepAlive( this );
1966 ::osl::MutexGuard aGuard( m_aMutex );
1967 if ( OComponentHelper::rBHelper.bDisposed )
1968 return;
1970 const ItemEventDescription& rItemEvent = static_cast< const ItemEventDescription& >( _rEvent );
1971 m_aItemListeners.notifyEach( &XItemListener::itemStateChanged, rItemEvent.getEventObject() );
1975 IMPL_LINK_NOARG_TYPED(OListBoxControl, OnTimeout, Idle*, void)
1977 m_aChangeListeners.notifyEach( &XChangeListener::changed, EventObject( *this ) );
1981 void SAL_CALL OListBoxControl::addItemListener( const Reference< XItemListener >& l ) throw (RuntimeException, std::exception)
1983 m_aItemListeners.addInterface( l );
1987 void SAL_CALL OListBoxControl::removeItemListener( const Reference< XItemListener >& l ) throw (RuntimeException, std::exception)
1989 m_aItemListeners.removeInterface( l );
1993 void SAL_CALL OListBoxControl::addActionListener( const Reference< XActionListener >& l ) throw (RuntimeException, std::exception)
1995 if ( m_xAggregateListBox.is() )
1996 m_xAggregateListBox->addActionListener( l );
2000 void SAL_CALL OListBoxControl::removeActionListener( const Reference< XActionListener >& l ) throw (RuntimeException, std::exception)
2002 if ( m_xAggregateListBox.is() )
2003 m_xAggregateListBox->removeActionListener( l );
2007 void SAL_CALL OListBoxControl::addItem( const OUString& aItem, ::sal_Int16 nPos ) throw (RuntimeException, std::exception)
2009 if ( m_xAggregateListBox.is() )
2010 m_xAggregateListBox->addItem( aItem, nPos );
2014 void SAL_CALL OListBoxControl::addItems( const Sequence< OUString >& aItems, ::sal_Int16 nPos ) throw (RuntimeException, std::exception)
2016 if ( m_xAggregateListBox.is() )
2017 m_xAggregateListBox->addItems( aItems, nPos );
2021 void SAL_CALL OListBoxControl::removeItems( ::sal_Int16 nPos, ::sal_Int16 nCount ) throw (RuntimeException, std::exception)
2023 if ( m_xAggregateListBox.is() )
2024 m_xAggregateListBox->removeItems( nPos, nCount );
2028 ::sal_Int16 SAL_CALL OListBoxControl::getItemCount( ) throw (RuntimeException, std::exception)
2030 if ( m_xAggregateListBox.is() )
2031 return m_xAggregateListBox->getItemCount();
2032 return 0;
2036 OUString SAL_CALL OListBoxControl::getItem( ::sal_Int16 nPos ) throw (RuntimeException, std::exception)
2038 if ( m_xAggregateListBox.is() )
2039 return m_xAggregateListBox->getItem( nPos );
2040 return OUString( );
2044 Sequence< OUString > SAL_CALL OListBoxControl::getItems( ) throw (RuntimeException, std::exception)
2046 if ( m_xAggregateListBox.is() )
2047 return m_xAggregateListBox->getItems();
2048 return Sequence< OUString >( );
2052 ::sal_Int16 SAL_CALL OListBoxControl::getSelectedItemPos( ) throw (RuntimeException, std::exception)
2054 if ( m_xAggregateListBox.is() )
2055 return m_xAggregateListBox->getSelectedItemPos();
2056 return 0;
2060 Sequence< ::sal_Int16 > SAL_CALL OListBoxControl::getSelectedItemsPos( ) throw (RuntimeException, std::exception)
2062 if ( m_xAggregateListBox.is() )
2063 return m_xAggregateListBox->getSelectedItemsPos();
2064 return Sequence< ::sal_Int16 >( );
2068 OUString SAL_CALL OListBoxControl::getSelectedItem( ) throw (RuntimeException, std::exception)
2070 if ( m_xAggregateListBox.is() )
2071 return m_xAggregateListBox->getSelectedItem();
2072 return OUString( );
2076 Sequence< OUString > SAL_CALL OListBoxControl::getSelectedItems( ) throw (RuntimeException, std::exception)
2078 if ( m_xAggregateListBox.is() )
2079 return m_xAggregateListBox->getSelectedItems();
2080 return Sequence< OUString >( );
2084 void SAL_CALL OListBoxControl::selectItemPos( ::sal_Int16 nPos, sal_Bool bSelect ) throw (RuntimeException, std::exception)
2086 if ( m_xAggregateListBox.is() )
2087 m_xAggregateListBox->selectItemPos( nPos, bSelect );
2091 void SAL_CALL OListBoxControl::selectItemsPos( const Sequence< ::sal_Int16 >& aPositions, sal_Bool bSelect ) throw (RuntimeException, std::exception)
2093 if ( m_xAggregateListBox.is() )
2094 m_xAggregateListBox->selectItemsPos( aPositions, bSelect );
2098 void SAL_CALL OListBoxControl::selectItem( const OUString& aItem, sal_Bool bSelect ) throw (RuntimeException, std::exception)
2100 if ( m_xAggregateListBox.is() )
2101 m_xAggregateListBox->selectItem( aItem, bSelect );
2105 sal_Bool SAL_CALL OListBoxControl::isMutipleMode( ) throw (RuntimeException, std::exception)
2107 if ( m_xAggregateListBox.is() )
2108 return m_xAggregateListBox->isMutipleMode();
2109 return sal_False;
2113 void SAL_CALL OListBoxControl::setMultipleMode( sal_Bool bMulti ) throw (RuntimeException, std::exception)
2115 if ( m_xAggregateListBox.is() )
2116 m_xAggregateListBox->setMultipleMode( bMulti );
2120 ::sal_Int16 SAL_CALL OListBoxControl::getDropDownLineCount( ) throw (RuntimeException, std::exception)
2122 if ( m_xAggregateListBox.is() )
2123 return m_xAggregateListBox->getDropDownLineCount();
2124 return 0;
2128 void SAL_CALL OListBoxControl::setDropDownLineCount( ::sal_Int16 nLines ) throw (RuntimeException, std::exception)
2130 if ( m_xAggregateListBox.is() )
2131 m_xAggregateListBox->setDropDownLineCount( nLines );
2135 void SAL_CALL OListBoxControl::makeVisible( ::sal_Int16 nEntry ) throw (RuntimeException, std::exception)
2137 if ( m_xAggregateListBox.is() )
2138 m_xAggregateListBox->makeVisible( nEntry );
2143 extern "C" SAL_DLLPUBLIC_EXPORT ::com::sun::star::uno::XInterface* SAL_CALL
2144 com_sun_star_form_OListBoxModel_get_implementation(::com::sun::star::uno::XComponentContext* component,
2145 ::com::sun::star::uno::Sequence<css::uno::Any> const &)
2147 return cppu::acquire(new frm::OListBoxModel(component));
2150 extern "C" SAL_DLLPUBLIC_EXPORT ::com::sun::star::uno::XInterface* SAL_CALL
2151 com_sun_star_form_OListBoxControl_get_implementation(::com::sun::star::uno::XComponentContext* component,
2152 ::com::sun::star::uno::Sequence<css::uno::Any> const &)
2154 return cppu::acquire(new frm::OListBoxControl(component));
2157 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */