xref: /trunk/main/forms/source/component/ListBox.cxx (revision a72d41dc)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_forms.hxx"
26 
27 #include "ListBox.hxx"
28 #include "property.hxx"
29 #include "property.hrc"
30 #include "services.hxx"
31 #include "frm_resource.hxx"
32 #include "frm_resource.hrc"
33 #include "BaseListBox.hxx"
34 #include "listenercontainers.hxx"
35 #include "componenttools.hxx"
36 
37 /** === begin UNO includes === **/
38 #include <com/sun/star/util/XNumberFormatTypes.hpp>
39 #include <com/sun/star/sdbc/XRowSet.hpp>
40 #include <com/sun/star/container/XIndexAccess.hpp>
41 #include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp>
42 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
43 #include <com/sun/star/util/NumberFormat.hpp>
44 #include <com/sun/star/awt/XWindow.hpp>
45 #include <com/sun/star/sdbc/XConnection.hpp>
46 #include <com/sun/star/sdb/CommandType.hpp>
47 /** === end UNO includes === **/
48 
49 #include <comphelper/basicio.hxx>
50 #include <comphelper/container.hxx>
51 #include <comphelper/numbers.hxx>
52 #include <comphelper/listenernotification.hxx>
53 #include <connectivity/dbtools.hxx>
54 #include <connectivity/formattedcolumnvalue.hxx>
55 #include <connectivity/dbconversion.hxx>
56 #include <cppuhelper/queryinterface.hxx>
57 #include <rtl/logfile.hxx>
58 #include <tools/debug.hxx>
59 #include <tools/diagnose_ex.h>
60 #include <unotools/sharedunocomponent.hxx>
61 #include <vcl/svapp.hxx>
62 
63 #include <boost/optional.hpp>
64 
65 #include <algorithm>
66 #include <functional>
67 
68 
69 //.........................................................................
70 namespace frm
71 {
72     using namespace ::com::sun::star::uno;
73     using namespace ::com::sun::star::sdb;
74     using namespace ::com::sun::star::sdbc;
75     using namespace ::com::sun::star::sdbcx;
76     using namespace ::com::sun::star::beans;
77     using namespace ::com::sun::star::container;
78     using namespace ::com::sun::star::form;
79     using namespace ::com::sun::star::awt;
80     using namespace ::com::sun::star::io;
81     using namespace ::com::sun::star::lang;
82     using namespace ::com::sun::star::util;
83     using namespace ::com::sun::star::form::binding;
84     using namespace ::dbtools;
85 
86     using ::connectivity::ORowSetValue;
87 
88     //==============================================================================
89     //= helper
90     //==============================================================================
91     namespace
92     {
93         //--------------------------------------------------------------------------
94         struct RowSetValueToString : public ::std::unary_function< ORowSetValue, ::rtl::OUString >
95         {
operator ()frm::__anon0dfb244c0111::RowSetValueToString96             ::rtl::OUString operator()( const ORowSetValue& _value ) const
97             {
98                 return _value.getString();
99             }
100         };
101 
102         //--------------------------------------------------------------------------
103         struct AppendRowSetValueString : public ::std::unary_function< ::rtl::OUString, void >
104         {
AppendRowSetValueStringfrm::__anon0dfb244c0111::AppendRowSetValueString105             AppendRowSetValueString( ::rtl::OUString& _string )
106                 :m_string( _string )
107             {
108             }
109 
operator ()frm::__anon0dfb244c0111::AppendRowSetValueString110             void operator()( const ::rtl::OUString _append )
111             {
112                 m_string += _append;
113             }
114 
115         private:
116             ::rtl::OUString&    m_string;
117         };
118 
119         //--------------------------------------------------------------------------
lcl_convertToStringSequence(const ValueList & _values)120         Sequence< ::rtl::OUString > lcl_convertToStringSequence( const ValueList& _values )
121         {
122             Sequence< ::rtl::OUString > aStrings( _values.size() );
123             ::std::transform(
124                 _values.begin(),
125                 _values.end(),
126                 aStrings.getArray(),
127                 RowSetValueToString()
128             );
129             return aStrings;
130         }
131     }
132 
133     //==============================================================================
134     //= ItemEventDescription
135     //==============================================================================
136     typedef ::comphelper::EventHolder< ItemEvent >    ItemEventDescription;
137 
138     //==============================================================================
139     //= OListBoxModel
140     //==============================================================================
141     //------------------------------------------------------------------
OListBoxModel_CreateInstance(const Reference<XMultiServiceFactory> & _rxFactory)142     InterfaceRef SAL_CALL OListBoxModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException)
143     {
144         return *(new OListBoxModel(_rxFactory));
145     }
146 
147     //------------------------------------------------------------------------------
_getTypes()148     Sequence< Type> OListBoxModel::_getTypes()
149     {
150         return TypeBag(
151             OBoundControlModel::_getTypes(),
152             OEntryListHelper::getTypes(),
153             OErrorBroadcaster::getTypes()
154         ).getTypes();
155     }
156 
157 
158     DBG_NAME(OListBoxModel);
159     //------------------------------------------------------------------
OListBoxModel(const Reference<XMultiServiceFactory> & _rxFactory)160     OListBoxModel::OListBoxModel(const Reference<XMultiServiceFactory>& _rxFactory)
161         :OBoundControlModel( _rxFactory, VCL_CONTROLMODEL_LISTBOX, FRM_SUN_CONTROL_LISTBOX, sal_True, sal_True, sal_True )
162         // use the old control name for compytibility reasons
163         ,OEntryListHelper( (OControlModel&)*this )
164         ,OErrorBroadcaster( OComponentHelper::rBHelper )
165         ,m_aListRowSet( getContext() )
166         ,m_nNULLPos(-1)
167         ,m_nBoundColumnType( DataType::SQLNULL )
168     {
169         DBG_CTOR(OListBoxModel,NULL);
170 
171         m_nClassId = FormComponentType::LISTBOX;
172         m_eListSourceType = ListSourceType_VALUELIST;
173         m_aBoundColumn <<= (sal_Int16)1;
174         initValueProperty( PROPERTY_SELECT_SEQ, PROPERTY_ID_SELECT_SEQ);
175 
176         startAggregatePropertyListening( PROPERTY_STRINGITEMLIST );
177     }
178 
179     //------------------------------------------------------------------
OListBoxModel(const OListBoxModel * _pOriginal,const Reference<XMultiServiceFactory> & _rxFactory)180     OListBoxModel::OListBoxModel( const OListBoxModel* _pOriginal, const Reference<XMultiServiceFactory>& _rxFactory )
181         :OBoundControlModel( _pOriginal, _rxFactory )
182         ,OEntryListHelper( *_pOriginal, (OControlModel&)*this )
183         ,OErrorBroadcaster( OComponentHelper::rBHelper )
184         ,m_aListRowSet( getContext() )
185         ,m_eListSourceType( _pOriginal->m_eListSourceType )
186         ,m_aBoundColumn( _pOriginal->m_aBoundColumn )
187         ,m_aListSourceValues( _pOriginal->m_aListSourceValues )
188         ,m_aBoundValues( _pOriginal->m_aBoundValues )
189         ,m_aDefaultSelectSeq( _pOriginal->m_aDefaultSelectSeq )
190         ,m_nNULLPos(-1)
191         ,m_nBoundColumnType( DataType::SQLNULL )
192     {
193         DBG_CTOR(OListBoxModel,NULL);
194 
195         startAggregatePropertyListening( PROPERTY_STRINGITEMLIST );
196     }
197 
198     //------------------------------------------------------------------
~OListBoxModel()199     OListBoxModel::~OListBoxModel()
200     {
201         if (!OComponentHelper::rBHelper.bDisposed)
202         {
203             acquire();
204             dispose();
205         }
206 
207         DBG_DTOR(OListBoxModel,NULL);
208     }
209 
210     // XCloneable
211     //------------------------------------------------------------------------------
IMPLEMENT_DEFAULT_CLONING(OListBoxModel)212     IMPLEMENT_DEFAULT_CLONING( OListBoxModel )
213 
214     // XServiceInfo
215     //------------------------------------------------------------------------------
216     StringSequence SAL_CALL OListBoxModel::getSupportedServiceNames() throw(RuntimeException)
217     {
218         StringSequence aSupported = OBoundControlModel::getSupportedServiceNames();
219 
220         sal_Int32 nOldLen = aSupported.getLength();
221 	    aSupported.realloc( nOldLen + 8 );
222 	    ::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen;
223 
224         *pStoreTo++ = BINDABLE_CONTROL_MODEL;
225         *pStoreTo++ = DATA_AWARE_CONTROL_MODEL;
226         *pStoreTo++ = VALIDATABLE_CONTROL_MODEL;
227 
228         *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL;
229         *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL;
230 
231         *pStoreTo++ = FRM_SUN_COMPONENT_LISTBOX;
232         *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_LISTBOX;
233         *pStoreTo++ = BINDABLE_DATABASE_LIST_BOX;
234 
235         return aSupported;
236     }
237 
238     //------------------------------------------------------------------------------
queryAggregation(const Type & _rType)239     Any SAL_CALL OListBoxModel::queryAggregation(const Type& _rType) throw (RuntimeException)
240     {
241         Any aReturn = OBoundControlModel::queryAggregation( _rType );
242         if ( !aReturn.hasValue() )
243             aReturn = OEntryListHelper::queryInterface( _rType );
244         if ( !aReturn.hasValue() )
245             aReturn = OErrorBroadcaster::queryInterface( _rType );
246         return aReturn;
247     }
248 
249     // OComponentHelper
250     //------------------------------------------------------------------------------
disposing()251     void OListBoxModel::disposing()
252     {
253         OBoundControlModel::disposing();
254         OEntryListHelper::disposing();
255         OErrorBroadcaster::disposing();
256     }
257 
258     //------------------------------------------------------------------------------
getFastPropertyValue(Any & _rValue,sal_Int32 _nHandle) const259     void OListBoxModel::getFastPropertyValue(Any& _rValue, sal_Int32 _nHandle) const
260     {
261         switch (_nHandle)
262         {
263         case PROPERTY_ID_BOUNDCOLUMN:
264             _rValue <<= m_aBoundColumn;
265             break;
266 
267         case PROPERTY_ID_LISTSOURCETYPE:
268             _rValue <<= m_eListSourceType;
269             break;
270 
271         case PROPERTY_ID_LISTSOURCE:
272             _rValue <<= lcl_convertToStringSequence( m_aListSourceValues );
273             break;
274 
275         case PROPERTY_ID_VALUE_SEQ:
276             _rValue <<= lcl_convertToStringSequence( m_aBoundValues );
277             break;
278 
279         case PROPERTY_ID_DEFAULT_SELECT_SEQ:
280             _rValue <<= m_aDefaultSelectSeq;
281             break;
282 
283         case PROPERTY_ID_STRINGITEMLIST:
284             _rValue <<= getStringItemList();
285             break;
286 
287         default:
288             OBoundControlModel::getFastPropertyValue(_rValue, _nHandle);
289         }
290     }
291 
292     //------------------------------------------------------------------------------
setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle,const Any & _rValue)293     void OListBoxModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const Any& _rValue) throw (com::sun::star::uno::Exception)
294     {
295         switch (_nHandle)
296         {
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;
302 
303         case PROPERTY_ID_LISTSOURCETYPE :
304             DBG_ASSERT(_rValue.getValueType().equals(::getCppuType(static_cast<ListSourceType*>(NULL))),
305                 "OComboBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" );
306             _rValue >>= m_eListSourceType;
307             break;
308 
309         case PROPERTY_ID_LISTSOURCE:
310         {
311             // extract
312             Sequence< ::rtl::OUString > aListSource;
313             OSL_VERIFY( _rValue >>= aListSource );
314 
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() )
321             );
322 
323             // propagate
324             if ( m_eListSourceType == ListSourceType_VALUELIST )
325             {
326                 m_aBoundValues = m_aListSourceValues;
327             }
328             else
329             {
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 );
334             }
335         }
336         break;
337 
338         case PROPERTY_ID_VALUE_SEQ :
339             OSL_ENSURE( false, "ValueItemList is read-only!" );
340             throw PropertyVetoException();
341 
342         case PROPERTY_ID_DEFAULT_SELECT_SEQ :
343             DBG_ASSERT(_rValue.getValueType().equals(::getCppuType(static_cast< Sequence<sal_Int16>*>(NULL))),
344                 "OListBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" );
345             _rValue >>= m_aDefaultSelectSeq;
346 
347             DBG_ASSERT(m_xAggregateFastSet.is(), "OListBoxModel::setFastPropertyValue_NoBroadcast(DEFAULT_SELECT_SEQ) : invalid aggregate !");
348             if ( m_xAggregateFastSet.is() )
349                 setControlValue( _rValue, eOther );
350             break;
351 
352         case PROPERTY_ID_STRINGITEMLIST:
353         {
354 			ControlModelLock aLock( *this );
355             setNewStringItemList( _rValue, aLock );
356                 // TODO: this is bogus. setNewStringItemList expects a guard which has the *only*
357                 // lock to the mutex, but setFastPropertyValue_NoBroadcast is already called with
358                 // a lock - so we effectively has two locks here, of which setNewStringItemList can
359                 // only control one.
360         }
361         resetNoBroadcast();
362         break;
363 
364         default:
365             OBoundControlModel::setFastPropertyValue_NoBroadcast(_nHandle, _rValue);
366         }
367     }
368 
369     //------------------------------------------------------------------------------
convertFastPropertyValue(Any & _rConvertedValue,Any & _rOldValue,sal_Int32 _nHandle,const Any & _rValue)370     sal_Bool OListBoxModel::convertFastPropertyValue(
371         Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue)
372         throw (IllegalArgumentException)
373     {
374         sal_Bool bModified(sal_False);
375         switch (_nHandle)
376         {
377         case PROPERTY_ID_BOUNDCOLUMN :
378             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aBoundColumn, ::getCppuType(static_cast<sal_Int16*>(NULL)));
379             break;
380 
381         case PROPERTY_ID_LISTSOURCETYPE:
382             bModified = tryPropertyValueEnum(_rConvertedValue, _rOldValue, _rValue, m_eListSourceType);
383             break;
384 
385         case PROPERTY_ID_LISTSOURCE:
386             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, lcl_convertToStringSequence( m_aListSourceValues ) );
387             break;
388 
389         case PROPERTY_ID_VALUE_SEQ :
390             OSL_ENSURE( false, "ValueItemList is read-only!" );
391             throw PropertyVetoException();
392 
393         case PROPERTY_ID_DEFAULT_SELECT_SEQ :
394             bModified = tryPropertyValue(_rConvertedValue, _rOldValue, _rValue, m_aDefaultSelectSeq);
395             break;
396 
397         case PROPERTY_ID_STRINGITEMLIST:
398             bModified = convertNewListSourceProperty( _rConvertedValue, _rOldValue, _rValue );
399             break;
400 
401         default:
402             return OBoundControlModel::convertFastPropertyValue(_rConvertedValue, _rOldValue, _nHandle, _rValue);
403         }
404         return bModified;
405     }
406 
407     //------------------------------------------------------------------------------
setPropertyValues(const Sequence<::rtl::OUString> & _rPropertyNames,const Sequence<Any> & _rValues)408     void SAL_CALL OListBoxModel::setPropertyValues( const Sequence< ::rtl::OUString >& _rPropertyNames, const Sequence< Any >& _rValues ) throw(PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
409     {
410         // if both SelectedItems and StringItemList are set, care for this
411         // #i27024# / 2004-04-05 / fs@openoffice.org
412         const Any* pSelectSequenceValue = NULL;
413 
414         const ::rtl::OUString* pStartPos = _rPropertyNames.getConstArray();
415         const ::rtl::OUString* pEndPos   = _rPropertyNames.getConstArray() + _rPropertyNames.getLength();
416         const ::rtl::OUString* pSelectedItemsPos = ::std::find_if(
417             pStartPos, pEndPos,
418              ::std::bind2nd( ::std::equal_to< ::rtl::OUString >(), PROPERTY_SELECT_SEQ )
419         );
420         const ::rtl::OUString* pStringItemListPos = ::std::find_if(
421             pStartPos, pEndPos,
422              ::std::bind2nd( ::std::equal_to< ::rtl::OUString >(), PROPERTY_STRINGITEMLIST )
423         );
424         if ( ( pSelectedItemsPos != pEndPos ) && ( pStringItemListPos != pEndPos ) )
425         {
426             // both properties are present
427             // -> remember the value for the select sequence
428             pSelectSequenceValue = _rValues.getConstArray() + ( pSelectedItemsPos - pStartPos );
429         }
430 
431         OBoundControlModel::setPropertyValues( _rPropertyNames, _rValues );
432 
433         if ( pSelectSequenceValue )
434         {
435             setPropertyValue( PROPERTY_SELECT_SEQ, *pSelectSequenceValue );
436             // Note that this is the only reliable way, since one of the properties is implemented
437             // by ourself, and one is implemented by the aggregate, we cannot rely on any particular
438             // results when setting them both - too many undocumented behavior in all the involved
439             // classes
440         }
441     }
442 
443     //------------------------------------------------------------------------------
describeFixedProperties(Sequence<Property> & _rProps) const444     void OListBoxModel::describeFixedProperties( Sequence< Property >& _rProps ) const
445     {
446         BEGIN_DESCRIBE_PROPERTIES( 7, OBoundControlModel )
447             DECL_PROP1(TABINDEX,            sal_Int16,                      BOUND);
448             DECL_PROP2(BOUNDCOLUMN,         sal_Int16,                      BOUND, MAYBEVOID);
449             DECL_PROP1(LISTSOURCETYPE,      ListSourceType,                 BOUND);
450             DECL_PROP1(LISTSOURCE,          StringSequence,                 BOUND);
451             DECL_PROP3(VALUE_SEQ,           StringSequence,                 BOUND, READONLY, TRANSIENT);
452             DECL_PROP1(DEFAULT_SELECT_SEQ,  Sequence<sal_Int16>,            BOUND);
453             DECL_PROP1(STRINGITEMLIST,      Sequence< ::rtl::OUString >,    BOUND);
454         END_DESCRIBE_PROPERTIES();
455     }
456 
457     //------------------------------------------------------------------------------
_propertyChanged(const PropertyChangeEvent & i_rEvent)458     void OListBoxModel::_propertyChanged( const PropertyChangeEvent& i_rEvent ) throw ( RuntimeException )
459     {
460         if ( i_rEvent.PropertyName == PROPERTY_STRINGITEMLIST )
461         {
462             ControlModelLock aLock( *this );
463             // SYNCHRONIZED ----->
464             // our aggregate internally changed its StringItemList property - reflect this in our "overridden"
465             // version of the property
466             setNewStringItemList( i_rEvent.NewValue, aLock );
467             // <----- SYNCHRONIZED
468             return;
469         }
470         OBoundControlModel::_propertyChanged( i_rEvent );
471     }
472 
473     //------------------------------------------------------------------------------
describeAggregateProperties(Sequence<Property> & _rAggregateProps) const474     void OListBoxModel::describeAggregateProperties( Sequence< Property >& _rAggregateProps ) const
475     {
476         OBoundControlModel::describeAggregateProperties( _rAggregateProps );
477 
478         // superseded properties:
479         RemoveProperty( _rAggregateProps, PROPERTY_STRINGITEMLIST );
480     }
481 
482     //------------------------------------------------------------------------------
getServiceName()483     ::rtl::OUString SAL_CALL OListBoxModel::getServiceName() throw(RuntimeException)
484     {
485         return FRM_COMPONENT_LISTBOX;   // old (non-sun) name for compatibility !
486     }
487 
488     //------------------------------------------------------------------------------
write(const Reference<XObjectOutputStream> & _rxOutStream)489     void SAL_CALL OListBoxModel::write(const Reference<XObjectOutputStream>& _rxOutStream)
490         throw(IOException, RuntimeException)
491     {
492         OBoundControlModel::write(_rxOutStream);
493 
494         // Dummy-Seq, um Kompatible zu bleiben, wenn SelectSeq nicht mehr gespeichert wird
495         Sequence<sal_Int16> aDummySeq;
496 
497         // Version
498         // Version 0x0002: ListSource wird StringSeq
499         _rxOutStream->writeShort(0x0004);
500 
501         // Maskierung fuer any
502         sal_uInt16 nAnyMask = 0;
503         if (m_aBoundColumn.getValueType().getTypeClass() != TypeClass_VOID)
504             nAnyMask |= BOUNDCOLUMN;
505 
506         _rxOutStream << nAnyMask;
507 
508         _rxOutStream << lcl_convertToStringSequence( m_aListSourceValues );
509         _rxOutStream << (sal_Int16)m_eListSourceType;
510         _rxOutStream << aDummySeq;
511         _rxOutStream << m_aDefaultSelectSeq;
512 
513         if ((nAnyMask & BOUNDCOLUMN) == BOUNDCOLUMN)
514         {
515             sal_Int16 nBoundColumn = 0;
516             m_aBoundColumn >>= nBoundColumn;
517             _rxOutStream << nBoundColumn;
518         }
519         writeHelpTextCompatibly(_rxOutStream);
520 
521         // from version 0x0004 : common properties
522         writeCommonProperties(_rxOutStream);
523     }
524 
525     //------------------------------------------------------------------------------
read(const Reference<XObjectInputStream> & _rxInStream)526     void SAL_CALL OListBoxModel::read(const Reference<XObjectInputStream>& _rxInStream) throw(IOException, RuntimeException)
527     {
528         // Bei manchen Variblen muessen Abhaengigkeiten beruecksichtigt werden.
529         // Deshalb muessen sie explizit ueber setPropertyValue() gesetzt werden.
530 
531         OBoundControlModel::read(_rxInStream);
532         ControlModelLock aLock( *this );
533 
534         // since we are "overwriting" the StringItemList of our aggregate (means we have
535         // an own place to store the value, instead of relying on our aggregate storing it),
536         // we need to respect what the aggregate just read for the StringItemList property.
537         try
538         {
539             if ( m_xAggregateSet.is() )
540                 setNewStringItemList( m_xAggregateSet->getPropertyValue( PROPERTY_STRINGITEMLIST ), aLock );
541         }
542         catch( const Exception& )
543         {
544     	    OSL_ENSURE( sal_False, "OComboBoxModel::read: caught an exception while examining the aggregate's string item list!" );
545         }
546 
547         // Version
548         sal_uInt16 nVersion = _rxInStream->readShort();
549         DBG_ASSERT(nVersion > 0, "OListBoxModel::read : version 0 ? this should never have been written !");
550 
551         if (nVersion > 0x0004)
552         {
553             DBG_ERROR("OListBoxModel::read : invalid (means unknown) version !");
554             ValueList().swap(m_aListSourceValues);
555             m_aBoundColumn <<= (sal_Int16)0;
556             ValueList().swap(m_aBoundValues);
557             m_eListSourceType = ListSourceType_VALUELIST;
558             m_aDefaultSelectSeq.realloc(0);
559             defaultCommonProperties();
560             return;
561         }
562 
563         // Maskierung fuer any
564         sal_uInt16 nAnyMask;
565         _rxInStream >> nAnyMask;
566 
567         // ListSourceSeq
568         StringSequence aListSourceSeq;
569         if (nVersion == 0x0001)
570         {
571             // ListSourceSeq aus String zusammenstellen;
572             ::rtl::OUString sListSource;
573             _rxInStream >> sListSource;
574 
575             sal_Int32 nTokens = 1;
576             const sal_Unicode* pStr = sListSource.getStr();
577             while ( *pStr )
578             {
579                 if ( *pStr == ';' )
580                     nTokens++;
581                 pStr++;
582             }
583             aListSourceSeq.realloc( nTokens );
584             for (sal_uInt16 i=0; i<nTokens; ++i)
585             {
586                 sal_Int32 nTmp = 0;
587                 aListSourceSeq.getArray()[i] = sListSource.getToken(i,';',nTmp);
588             }
589         }
590         else
591             _rxInStream >> aListSourceSeq;
592 
593         sal_Int16 nListSourceType;
594         _rxInStream >> nListSourceType;
595         m_eListSourceType = (ListSourceType)nListSourceType;
596         Any aListSourceSeqAny;
597         aListSourceSeqAny <<= aListSourceSeq;
598 
599         setFastPropertyValue(PROPERTY_ID_LISTSOURCE, aListSourceSeqAny );
600 
601         // Dummy-Seq, um Kompatible zu bleiben, wenn SelectSeq nicht mehr gespeichert wird
602         Sequence<sal_Int16> aDummySeq;
603         _rxInStream >> aDummySeq;
604 
605         // DefaultSelectSeq
606         Sequence<sal_Int16> aDefaultSelectSeq;
607         _rxInStream >> aDefaultSelectSeq;
608         Any aDefaultSelectSeqAny;
609         aDefaultSelectSeqAny <<= aDefaultSelectSeq;
610         setFastPropertyValue(PROPERTY_ID_DEFAULT_SELECT_SEQ, aDefaultSelectSeqAny);
611 
612         // BoundColumn
613         if ((nAnyMask & BOUNDCOLUMN) == BOUNDCOLUMN)
614         {
615             sal_Int16 nValue;
616             _rxInStream >> nValue;
617             m_aBoundColumn <<= nValue;
618         }
619 
620         if (nVersion > 2)
621             readHelpTextCompatibly(_rxInStream);
622 
623         // if our string list is not filled from the value list, we must empty it
624         // this can be the case when somebody saves in alive mode
625         if  (   ( m_eListSourceType != ListSourceType_VALUELIST )
626             &&  !hasExternalListSource()
627             )
628         {
629             setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( StringSequence() ) );
630         }
631 
632         if (nVersion > 3)
633             readCommonProperties(_rxInStream);
634 
635         // Nach dem Lesen die Defaultwerte anzeigen
636         if ( getControlSource().getLength() )
637             // (not if we don't have a control source - the "State" property acts like it is persistent, then
638             resetNoBroadcast();
639     }
640 
641     //------------------------------------------------------------------------------
loadData(bool _bForce)642     void OListBoxModel::loadData( bool _bForce )
643     {
644         RTL_LOGFILE_CONTEXT( aLogContext, "OListBoxModel::loadData" );
645         DBG_ASSERT( m_eListSourceType != ListSourceType_VALUELIST, "OListBoxModel::loadData: cannot load value list from DB!" );
646         DBG_ASSERT( !hasExternalListSource(), "OListBoxModel::loadData: cannot load from DB when I have an external list source!" );
647 
648         const sal_Int16 nNULLPosBackup( m_nNULLPos );
649         const sal_Int32 nBoundColumnTypeBackup( m_nBoundColumnType );
650         m_nNULLPos = -1;
651         m_nBoundColumnType = DataType::SQLNULL;
652 
653         // pre-requisites:
654         // PRE1: connection
655         Reference< XConnection > xConnection;
656         // is the active connection of our form
657         Reference< XPropertySet > xFormProps( m_xCursor, UNO_QUERY );
658         if ( xFormProps.is() )
659             xFormProps->getPropertyValue( PROPERTY_ACTIVE_CONNECTION ) >>= xConnection;
660 
661         // PRE2: list source
662         ::rtl::OUString sListSource;
663         // if our list source type is no value list, we need to concatenate
664         // the single list source elements
665         ::std::for_each(
666             m_aListSourceValues.begin(),
667             m_aListSourceValues.end(),
668             AppendRowSetValueString( sListSource )
669         );
670 
671         // outta here if we don't have all pre-requisites
672         if ( !xConnection.is() || !sListSource.getLength() )
673         {
674             ValueList().swap(m_aBoundValues);
675             return;
676         }
677 
678         ::boost::optional< sal_Int16 > aBoundColumn;
679         if ( m_aBoundColumn.getValueType().getTypeClass() == TypeClass_SHORT )
680         {
681             sal_Int16 nBoundColumn( 0 );
682             m_aBoundColumn >>= nBoundColumn;
683             aBoundColumn.reset( nBoundColumn );
684         }
685 
686         ::utl::SharedUNOComponent< XResultSet > xListCursor;
687         try
688         {
689             m_aListRowSet.setConnection( xConnection );
690 
691             sal_Bool bExecute = sal_False;
692             switch (m_eListSourceType)
693             {
694             case ListSourceType_TABLEFIELDS:
695                 // don't work with a statement here, the fields will be collected below
696                 break;
697 
698             case ListSourceType_TABLE:
699                 {
700                     Reference<XNameAccess> xFieldsByName = getTableFields(xConnection, sListSource);
701                     Reference<XIndexAccess> xFieldsByIndex(xFieldsByName, UNO_QUERY);
702 
703                     // do we have a bound column if yes we have to select it
704                     // and the displayed column is the first column othwhise we act as a combobox
705                     ::rtl::OUString aFieldName;
706                     ::rtl::OUString aBoundFieldName;
707 
708                     if ( !!aBoundColumn && ( *aBoundColumn >= 0 ) && xFieldsByIndex.is() )
709                     {
710                         if ( *aBoundColumn >= xFieldsByIndex->getCount() )
711                             break;
712 
713 						Reference<XPropertySet> xFieldAsSet(xFieldsByIndex->getByIndex( *aBoundColumn ),UNO_QUERY);
714                         xFieldAsSet->getPropertyValue(PROPERTY_NAME) >>= aBoundFieldName;
715                         aBoundColumn.reset( 1 );
716 
717 						xFieldAsSet.set(xFieldsByIndex->getByIndex(0),UNO_QUERY);
718                         xFieldAsSet->getPropertyValue(PROPERTY_NAME) >>= aFieldName;
719                     }
720                     else if (xFieldsByName.is())
721                     {
722                         if ( xFieldsByName->hasByName( getControlSource() ) )
723                             aFieldName = getControlSource();
724                         else
725                         {
726                             // otherwise look for the alias
727                             Reference< XColumnsSupplier > xSupplyFields;
728                             xFormProps->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SingleSelectQueryComposer"))) >>= xSupplyFields;
729 
730                             // search the field
731                             DBG_ASSERT(xSupplyFields.is(), "OListBoxModel::loadData : invalid query composer !");
732 
733                             Reference<XNameAccess> xFieldNames = xSupplyFields->getColumns();
734                             if ( xFieldNames->hasByName( getControlSource() ) )
735                             {
736                                 Reference<XPropertySet> xComposerFieldAsSet;
737                                 xFieldNames->getByName( getControlSource() ) >>= xComposerFieldAsSet;
738                                 if (hasProperty(PROPERTY_FIELDSOURCE, xComposerFieldAsSet))
739                                     xComposerFieldAsSet->getPropertyValue(PROPERTY_FIELDSOURCE) >>= aFieldName;
740                             }
741                         }
742                     }
743                     if (!aFieldName.getLength())
744                         break;
745 
746                     Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
747                     ::rtl::OUString aQuote = xMeta->getIdentifierQuoteString();
748                     ::rtl::OUString aStatement = ::rtl::OUString::createFromAscii("SELECT ");
749                     if (!aBoundFieldName.getLength())   // act like a combobox
750                         aStatement += ::rtl::OUString::createFromAscii("DISTINCT ");
751 
752                     aStatement += quoteName(aQuote,aFieldName);
753                     if (aBoundFieldName.getLength())
754                     {
755                         aStatement += ::rtl::OUString::createFromAscii(", ");
756                         aStatement += quoteName(aQuote, aBoundFieldName);
757                     }
758                     aStatement += ::rtl::OUString::createFromAscii(" FROM ");
759 
760                     ::rtl::OUString sCatalog, sSchema, sTable;
761 	                qualifiedNameComponents( xMeta, sListSource, sCatalog, sSchema, sTable, eInDataManipulation );
762                     aStatement += composeTableNameForSelect( xConnection, sCatalog, sSchema, sTable );
763 
764                     m_aListRowSet.setEscapeProcessing( sal_False );
765                     m_aListRowSet.setCommand( aStatement );
766                     bExecute = sal_True;
767                 }
768                 break;
769 
770             case ListSourceType_QUERY:
771                 m_aListRowSet.setCommandFromQuery( sListSource );
772                 bExecute = sal_True;
773                 break;
774 
775             default:
776                 m_aListRowSet.setEscapeProcessing( ListSourceType_SQLPASSTHROUGH != m_eListSourceType );
777                 m_aListRowSet.setCommand( sListSource );
778                 bExecute = sal_True;
779                 break;
780             }
781 
782             if (bExecute)
783             {
784                 if ( !_bForce && !m_aListRowSet.isDirty() )
785                 {
786                     // if none of the settings of the row set changed, compared to the last
787                     // invocation of loadData, then don't re-fill the list. Instead, assume
788                     // the list entries are the same.
789                     m_nNULLPos = nNULLPosBackup;
790                     m_nBoundColumnType = nBoundColumnTypeBackup;
791                     return;
792                 }
793                 xListCursor.reset( m_aListRowSet.execute() );
794             }
795         }
796         catch(SQLException& eSQL)
797         {
798             onError(eSQL, FRM_RES_STRING(RID_BASELISTBOX_ERROR_FILLLIST));
799             return;
800         }
801         catch(const Exception& eUnknown)
802         {
803             (void)eUnknown;
804             return;
805         }
806 
807         // Anzeige- und Werteliste fuellen
808         ValueList aDisplayList, aValueList;
809         sal_Bool bUseNULL = hasField() && !isRequired();
810 
811         try
812         {
813             OSL_ENSURE( xListCursor.is() || ( ListSourceType_TABLEFIELDS == m_eListSourceType ),
814                 "OListBoxModel::loadData: logic error!" );
815             if ( !xListCursor.is() && ( ListSourceType_TABLEFIELDS != m_eListSourceType ) )
816                 return;
817 
818             switch (m_eListSourceType)
819             {
820             case ListSourceType_SQL:
821             case ListSourceType_SQLPASSTHROUGH:
822             case ListSourceType_TABLE:
823             case ListSourceType_QUERY:
824                 {
825                     // Feld der 1. Column des ResultSets holen
826                     Reference<XColumnsSupplier> xSupplyCols(xListCursor, UNO_QUERY);
827                     DBG_ASSERT(xSupplyCols.is(), "OListBoxModel::loadData : cursor supports the row set service but is no column supplier?!");
828                     Reference<XIndexAccess> xColumns;
829                     if (xSupplyCols.is())
830                     {
831                         xColumns = Reference<XIndexAccess>(xSupplyCols->getColumns(), UNO_QUERY);
832                         DBG_ASSERT(xColumns.is(), "OListBoxModel::loadData : no columns supplied by the row set !");
833                     }
834 
835                     Reference< XPropertySet > xDataField;
836                     if ( xColumns.is() )
837                         xColumns->getByIndex(0) >>= xDataField;
838                     if ( !xDataField.is() )
839                         return;
840 
841                     ::dbtools::FormattedColumnValue aValueFormatter( getContext(), m_xCursor, xDataField );
842 
843                     // Feld der BoundColumn des ResultSets holen
844                     m_nBoundColumnType = DataType::SQLNULL;
845                     if ( !!aBoundColumn && ( *aBoundColumn >= 0 ) && m_xColumn.is() )
846                     {   // don't look for a bound column if we're not connected to a field
847                         try
848                         {
849                             Reference< XPropertySet > xBoundField( xColumns->getByIndex( *aBoundColumn ), UNO_QUERY_THROW );
850                             OSL_VERIFY( xBoundField->getPropertyValue( ::rtl::OUString::createFromAscii( "Type" ) ) >>= m_nBoundColumnType );
851                         }
852                         catch( const Exception& )
853                         {
854                             DBG_UNHANDLED_EXCEPTION();
855                         }
856                     }
857 
858                     //  Ist die LB an ein Feld gebunden und sind Leereintraege zulaessig
859                     //  dann wird die Position fuer einen Leereintrag gemerkt
860 
861                     RTL_LOGFILE_CONTEXT( aLogContext, "OListBoxModel::loadData: string collection" );
862                     ::rtl::OUString aStr;
863                     sal_Int16 entryPos = 0;
864                     ORowSetValue aBoundValue;
865                     Reference< XRow > xCursorRow( xListCursor, UNO_QUERY_THROW );
866                     while ( xListCursor->next() && ( entryPos++ < SHRT_MAX ) ) // SHRT_MAX is the maximum number of entries
867                     {
868                         aStr = aValueFormatter.getFormattedValue();
869                         aDisplayList.push_back( aStr );
870 
871                         if ( impl_hasBoundComponent() )
872                         {
873                             aBoundValue.fill( *aBoundColumn + 1, m_nBoundColumnType, xCursorRow );
874                             aValueList.push_back( aBoundValue );
875                         }
876 
877                         if ( bUseNULL && ( m_nNULLPos == -1 ) && !aStr.getLength() )
878                             m_nNULLPos = sal_Int16( aDisplayList.size() - 1 );
879                     }
880                 }
881                 break;
882 
883             case ListSourceType_TABLEFIELDS:
884                 {
885                     Reference<XNameAccess> xFieldNames = getTableFields(xConnection, sListSource);
886                     if (xFieldNames.is())
887                     {
888                         StringSequence seqNames = xFieldNames->getElementNames();
889                         ::std::copy(
890                             seqNames.getConstArray(),
891                             seqNames.getConstArray() + seqNames.getLength(),
892                             ::std::insert_iterator< ValueList >( aDisplayList, aDisplayList.end() )
893                         );
894                     }
895                 }
896                 break;
897                 default:
898                     OSL_ENSURE( false, "OListBoxModel::loadData: unreachable!" );
899                     break;
900             }
901         }
902         catch(SQLException& eSQL)
903         {
904             onError(eSQL, FRM_RES_STRING(RID_BASELISTBOX_ERROR_FILLLIST));
905             return;
906         }
907         catch( const Exception& )
908         {
909             DBG_UNHANDLED_EXCEPTION();
910             return;
911         }
912 
913 
914         // Value-Sequence erzeugen
915         // NULL eintrag hinzufuegen
916         if (bUseNULL && m_nNULLPos == -1)
917         {
918             if ( impl_hasBoundComponent() )
919                 aValueList.insert( aValueList.begin(), ORowSetValue() );
920 
921             aDisplayList.insert( aDisplayList.begin(), ORowSetValue( ::rtl::OUString() ) );
922             m_nNULLPos = 0;
923         }
924 
925         m_aBoundValues = aValueList;
926 
927         setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( lcl_convertToStringSequence( aDisplayList ) ) );
928     }
929 
930     //------------------------------------------------------------------------------
onConnectedDbColumn(const Reference<XInterface> &)931     void OListBoxModel::onConnectedDbColumn( const Reference< XInterface >& /*_rxForm*/ )
932     {
933         // list boxes which are bound to a db column don't have multi selection
934         // - this would be unable to reflect in the db column
935         if ( hasField() )
936         {
937             setFastPropertyValue( PROPERTY_ID_MULTISELECTION, ::cppu::bool2any( ( sal_False ) ) );
938         }
939 
940         if ( !hasExternalListSource() )
941             impl_refreshDbEntryList( false );
942     }
943 
944     //------------------------------------------------------------------------------
onDisconnectedDbColumn()945     void OListBoxModel::onDisconnectedDbColumn()
946     {
947         if ( m_eListSourceType != ListSourceType_VALUELIST )
948         {
949             ValueList().swap(m_aBoundValues);
950             m_nNULLPos = -1;
951             m_nBoundColumnType = DataType::SQLNULL;
952 
953             if ( !hasExternalListSource() )
954                 setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST, makeAny( StringSequence() ) );
955 
956             m_aListRowSet.dispose();
957         }
958     }
959 
960     //------------------------------------------------------------------------------
impl_getValues() const961     ValueList OListBoxModel::impl_getValues() const
962     {
963         if ( !m_aBoundValues.empty() )
964             return m_aBoundValues;
965 
966         Sequence< ::rtl::OUString > aStringItems( getStringItemList() );
967         ValueList aValues( aStringItems.getLength() );
968         ::std::copy(
969             aStringItems.getConstArray(),
970             aStringItems.getConstArray() + aStringItems.getLength(),
971             aValues.begin()
972         );
973 
974         return aValues;
975     }
976     //------------------------------------------------------------------------------
getFirstSelectedValue() const977     ORowSetValue OListBoxModel::getFirstSelectedValue() const
978     {
979         static const ORowSetValue s_aEmptyVaue;
980 
981         DBG_ASSERT( m_xAggregateFastSet.is(), "OListBoxModel::getFirstSelectedValue: invalid aggregate!" );
982         if ( !m_xAggregateFastSet.is() )
983             return s_aEmptyVaue;
984 
985         Sequence< sal_Int16 > aSelectedIndices;
986         OSL_VERIFY( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) >>= aSelectedIndices );
987         if ( !aSelectedIndices.getLength() )
988             // nothing selected at all
989             return s_aEmptyVaue;
990 
991         if ( ( m_nNULLPos != -1 ) && ( aSelectedIndices[0] == m_nNULLPos ) )
992             // the dedicated "NULL" entry is selected
993             return s_aEmptyVaue;
994 
995         ValueList aValues( impl_getValues() );
996 
997         size_t selectedValue = aSelectedIndices[0];
998         if ( selectedValue >= aValues.size() )
999         {
1000             OSL_ENSURE( false, "OListBoxModel::getFirstSelectedValue: inconsistent selection/valuelist!" );
1001             return s_aEmptyVaue;
1002         }
1003 
1004         return aValues[ selectedValue ];
1005     }
1006 
1007     //------------------------------------------------------------------------------
commitControlValueToDbColumn(bool)1008     sal_Bool OListBoxModel::commitControlValueToDbColumn( bool /*_bPostReset*/ )
1009     {
1010         // current selektion list
1011         const ORowSetValue aCurrentValue( getFirstSelectedValue() );
1012         if ( aCurrentValue != m_aSaveValue )
1013         {
1014             if ( aCurrentValue.isNull() )
1015                 m_xColumnUpdate->updateNull();
1016             else
1017             {
1018                 try
1019                 {
1020                     m_xColumnUpdate->updateObject( aCurrentValue.makeAny() );
1021                 }
1022                 catch ( const Exception& )
1023                 {
1024                     return sal_False;
1025                 }
1026             }
1027             m_aSaveValue = aCurrentValue;
1028         }
1029         return sal_True;
1030     }
1031 
1032     // XPropertiesChangeListener
1033     //------------------------------------------------------------------------------
translateDbColumnToControlValue()1034     Any OListBoxModel::translateDbColumnToControlValue()
1035     {
1036         Reference< XPropertySet > xBoundField( getField() );
1037         if ( !xBoundField.is() )
1038         {
1039             OSL_ENSURE( false, "OListBoxModel::translateDbColumnToControlValue: no field? How could that happen?!" );
1040             return Any();
1041         }
1042 
1043         Sequence< sal_Int16 > aSelectionIndicies;
1044 
1045         ORowSetValue aCurrentValue;
1046         aCurrentValue.fill( impl_hasBoundComponent() ? m_nBoundColumnType : getFieldType(), m_xColumn );
1047 
1048         // reset selection for NULL values
1049         if ( aCurrentValue.isNull() )
1050         {
1051             if ( m_nNULLPos != -1 )
1052             {
1053                 aSelectionIndicies.realloc(1);
1054                 aSelectionIndicies[0] = m_nNULLPos;
1055             }
1056         }
1057         else
1058         {
1059             ValueList aValues( impl_getValues() );
1060             ValueList::const_iterator curValuePos = ::std::find( aValues.begin(), aValues.end(), aCurrentValue );
1061             if ( curValuePos != aValues.end() )
1062             {
1063                 aSelectionIndicies.realloc( 1 );
1064                 aSelectionIndicies[0] = curValuePos - aValues.begin();
1065             }
1066         }
1067 
1068         m_aSaveValue = aCurrentValue;
1069 
1070         return makeAny( aSelectionIndicies );
1071     }
1072 
1073     // XReset
1074     //------------------------------------------------------------------------------
getDefaultForReset() const1075     Any OListBoxModel::getDefaultForReset() const
1076     {
1077         Any aValue;
1078         if (m_aDefaultSelectSeq.getLength())
1079             aValue <<= m_aDefaultSelectSeq;
1080         else if (m_nNULLPos != -1)  // gebundene Listbox
1081         {
1082             Sequence<sal_Int16> aSeq(1);
1083             aSeq.getArray()[0] = m_nNULLPos;
1084             aValue <<= aSeq;
1085         }
1086         else
1087         {
1088             Sequence<sal_Int16> aSeq;
1089             aValue <<= aSeq;
1090         }
1091 
1092         return aValue;
1093     }
1094 
1095     //--------------------------------------------------------------------
resetNoBroadcast()1096     void OListBoxModel::resetNoBroadcast()
1097     {
1098         OBoundControlModel::resetNoBroadcast();
1099         m_aSaveValue.setNull();
1100     }
1101 
1102     //--------------------------------------------------------------------
disposing(const EventObject & _rSource)1103     void SAL_CALL OListBoxModel::disposing( const EventObject& _rSource ) throw ( RuntimeException )
1104     {
1105         if ( !OEntryListHelper::handleDisposing( _rSource ) )
1106             OBoundControlModel::disposing( _rSource );
1107     }
1108 
1109     //--------------------------------------------------------------------
1110     namespace
1111     {
1112         /** type how we should transfer our selection to external value bindings
1113         */
1114         enum ExchangeType
1115         {
1116             eIndexList,     /// as list of indexes of selected entries
1117             eIndex,         /// as index of the selected entry
1118             eEntryList,     /// as list of string representations of selected entries
1119             eEntry          /// as string representation of the selected entry
1120         };
1121 
1122         //--------------------------------------------------------------------
lcl_getCurrentExchangeType(const Type & _rExchangeType)1123         ExchangeType lcl_getCurrentExchangeType( const Type& _rExchangeType )
1124         {
1125             switch ( _rExchangeType.getTypeClass() )
1126             {
1127             case TypeClass_STRING:
1128                 return eEntry;
1129             case TypeClass_LONG:
1130                 return eIndex;
1131             case TypeClass_SEQUENCE:
1132             {
1133                 Type aElementType = ::comphelper::getSequenceElementType( _rExchangeType );
1134                 switch ( aElementType.getTypeClass() )
1135                 {
1136                 case TypeClass_STRING:
1137                     return eEntryList;
1138                 case TypeClass_LONG:
1139                     return eIndexList;
1140                 default:
1141                     break;
1142                 }
1143             }
1144             default:
1145                 break;
1146             }
1147             OSL_ENSURE( false, "lcl_getCurrentExchangeType: unsupported (unexpected) exchange type!" );
1148             return eEntry;
1149         }
1150     }
1151 
1152     //--------------------------------------------------------------------
translateExternalValueToControlValue(const Any & _rExternalValue) const1153     Any OListBoxModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const
1154     {
1155         Sequence< sal_Int16 > aSelectIndexes;
1156 
1157         switch ( lcl_getCurrentExchangeType( getExternalValueType() ) )
1158         {
1159         case eIndexList:
1160         {
1161             // unfortunately, our select sequence is a sequence<short>, while the external binding
1162             // supplies sequence<int> only -> transform this
1163             Sequence< sal_Int32 > aSelectIndexesPure;
1164             OSL_VERIFY( _rExternalValue >>= aSelectIndexesPure );
1165             aSelectIndexes.realloc( aSelectIndexesPure.getLength() );
1166             ::std::copy(
1167                 aSelectIndexesPure.getConstArray(),
1168                 aSelectIndexesPure.getConstArray() + aSelectIndexesPure.getLength(),
1169                 aSelectIndexes.getArray()
1170             );
1171         }
1172         break;
1173 
1174         case eIndex:
1175         {
1176             sal_Int32 nSelectIndex = -1;
1177             OSL_VERIFY( _rExternalValue >>= nSelectIndex );
1178             if ( ( nSelectIndex >= 0 ) && ( nSelectIndex < getStringItemList().getLength() ) )
1179             {
1180                 aSelectIndexes.realloc( 1 );
1181                 aSelectIndexes[ 0 ] = static_cast< sal_Int16 >( nSelectIndex );
1182             }
1183         }
1184         break;
1185 
1186         case eEntryList:
1187         {
1188             // we can retrieve a string list from the binding for multiple selection
1189             Sequence< ::rtl::OUString > aSelectEntries;
1190             OSL_VERIFY( _rExternalValue >>= aSelectEntries );
1191 
1192             ::std::set< sal_Int16 > aSelectionSet;
1193 
1194             // find the selection entries in our item list
1195             const ::rtl::OUString* pSelectEntries = aSelectEntries.getArray();
1196             const ::rtl::OUString* pSelectEntriesEnd = pSelectEntries + aSelectEntries.getLength();
1197             while ( pSelectEntries != pSelectEntriesEnd )
1198             {
1199                 // the indexes where the current string appears in our string items
1200                 Sequence< sal_Int16 > aThisEntryIndexes;
1201                 aThisEntryIndexes = findValue( getStringItemList(), *pSelectEntries++, sal_False );
1202 
1203                 // insert all the indexes of this entry into our set
1204                 ::std::copy(
1205                     aThisEntryIndexes.getConstArray(),
1206                     aThisEntryIndexes.getConstArray() + aThisEntryIndexes.getLength(),
1207                     ::std::insert_iterator< ::std::set< sal_Int16 > >( aSelectionSet, aSelectionSet.begin() )
1208                 );
1209             }
1210 
1211             // copy the indexes to the sequence
1212             aSelectIndexes.realloc( aSelectionSet.size() );
1213             ::std::copy(
1214                 aSelectionSet.begin(),
1215                 aSelectionSet.end(),
1216                 aSelectIndexes.getArray()
1217             );
1218         }
1219         break;
1220 
1221         case eEntry:
1222         {
1223             ::rtl::OUString sStringToSelect;
1224             OSL_VERIFY( _rExternalValue >>= sStringToSelect );
1225 
1226             aSelectIndexes = findValue( getStringItemList(), sStringToSelect, sal_False );
1227         }
1228         break;
1229         }
1230 
1231         return makeAny( aSelectIndexes );
1232     }
1233 
1234     //--------------------------------------------------------------------
1235     namespace
1236     {
1237         //................................................................
1238         struct ExtractStringFromSequence_Safe : public ::std::unary_function< sal_Int16, ::rtl::OUString >
1239         {
1240         protected:
1241             const Sequence< ::rtl::OUString >&  m_rList;
1242 
1243         public:
ExtractStringFromSequence_Safefrm::__anon0dfb244c0311::ExtractStringFromSequence_Safe1244             ExtractStringFromSequence_Safe( const Sequence< ::rtl::OUString >& _rList ) : m_rList( _rList ) { }
1245 
operator ()frm::__anon0dfb244c0311::ExtractStringFromSequence_Safe1246             ::rtl::OUString operator ()( sal_Int16 _nIndex )
1247             {
1248                 OSL_ENSURE( _nIndex < m_rList.getLength(), "ExtractStringFromSequence_Safe: inconsistence!" );
1249                 if ( _nIndex < m_rList.getLength() )
1250                     return m_rList[ _nIndex ];
1251                 return ::rtl::OUString();
1252             }
1253         };
1254 
1255         //................................................................
lcl_getSingleSelectedEntry(const Sequence<sal_Int16> & _rSelectSequence,const Sequence<::rtl::OUString> & _rStringList)1256         Any lcl_getSingleSelectedEntry( const Sequence< sal_Int16 >& _rSelectSequence, const Sequence< ::rtl::OUString >& _rStringList )
1257         {
1258             Any aReturn;
1259 
1260             // by definition, multiple selected entries are transferred as NULL if the
1261             // binding does not support string lists
1262             if ( _rSelectSequence.getLength() <= 1 )
1263             {
1264                 ::rtl::OUString sSelectedEntry;
1265 
1266                 if ( _rSelectSequence.getLength() == 1 )
1267                     sSelectedEntry = ExtractStringFromSequence_Safe( _rStringList )( _rSelectSequence[0] );
1268 
1269                 aReturn <<= sSelectedEntry;
1270             }
1271 
1272             return aReturn;
1273         }
1274 
1275         //................................................................
lcl_getMultiSelectedEntries(const Sequence<sal_Int16> & _rSelectSequence,const Sequence<::rtl::OUString> & _rStringList)1276         Any lcl_getMultiSelectedEntries( const Sequence< sal_Int16 >& _rSelectSequence, const Sequence< ::rtl::OUString >& _rStringList )
1277         {
1278             Sequence< ::rtl::OUString > aSelectedEntriesTexts( _rSelectSequence.getLength() );
1279             ::std::transform(
1280                 _rSelectSequence.getConstArray(),
1281                 _rSelectSequence.getConstArray() + _rSelectSequence.getLength(),
1282                 aSelectedEntriesTexts.getArray(),
1283                 ExtractStringFromSequence_Safe( _rStringList )
1284             );
1285             return makeAny( aSelectedEntriesTexts );
1286         }
1287     }
1288 
1289     //--------------------------------------------------------------------
translateControlValueToExternalValue() const1290     Any OListBoxModel::translateControlValueToExternalValue( ) const
1291     {
1292         OSL_PRECOND( hasExternalValueBinding(), "OListBoxModel::translateControlValueToExternalValue: no binding!" );
1293 
1294         Sequence< sal_Int16 > aSelectSequence;
1295         const_cast< OListBoxModel* >( this )->getPropertyValue( PROPERTY_SELECT_SEQ ) >>= aSelectSequence;
1296 
1297         Any aReturn;
1298         switch ( lcl_getCurrentExchangeType( getExternalValueType() ) )
1299         {
1300         case eIndexList:
1301         {
1302             // unfortunately, the select sequence is a sequence<short>, but our binding
1303             // expects int's
1304             Sequence< sal_Int32 > aTransformed( aSelectSequence.getLength() );
1305             ::std::copy(
1306                 aSelectSequence.getConstArray(),
1307                 aSelectSequence.getConstArray() + aSelectSequence.getLength(),
1308                 aTransformed.getArray()
1309             );
1310             aReturn <<= aTransformed;
1311         }
1312         break;
1313 
1314         case eIndex:
1315         if ( aSelectSequence.getLength() <= 1 )
1316         {
1317             sal_Int32 nIndex = -1;
1318 
1319             if ( aSelectSequence.getLength() == 1 )
1320                 nIndex = aSelectSequence[0];
1321 
1322             aReturn <<= nIndex;
1323         }
1324         break;
1325 
1326         case eEntryList:
1327             aReturn = lcl_getMultiSelectedEntries( aSelectSequence, getStringItemList() );
1328             break;
1329 
1330         case eEntry:
1331             aReturn = lcl_getSingleSelectedEntry( aSelectSequence, getStringItemList() );
1332             break;
1333         }
1334 
1335         return aReturn;
1336     }
1337 
1338     //--------------------------------------------------------------------
getCurrentFormComponentValue() const1339     Any OListBoxModel::getCurrentFormComponentValue() const
1340     {
1341         if ( hasValidator() )
1342             return OBoundControlModel::getCurrentFormComponentValue();
1343 
1344         Any aCurretnValue;
1345 
1346         try
1347         {
1348             Sequence< sal_Int16 > aSelectSequence;
1349             OSL_VERIFY( const_cast< OListBoxModel* >( this )->getPropertyValue( PROPERTY_SELECT_SEQ ) >>= aSelectSequence );
1350 
1351             sal_Bool bMultiSelection( sal_False );
1352             OSL_VERIFY( const_cast< OListBoxModel* >( this )->getPropertyValue( PROPERTY_MULTISELECTION ) >>= bMultiSelection );
1353 
1354             if ( bMultiSelection )
1355                 aCurretnValue = lcl_getMultiSelectedEntries( aSelectSequence, getStringItemList() );
1356             else
1357                 aCurretnValue = lcl_getSingleSelectedEntry( aSelectSequence, getStringItemList() );
1358         }
1359         catch( const Exception& )
1360         {
1361         	DBG_UNHANDLED_EXCEPTION();
1362         }
1363 
1364         return aCurretnValue;
1365     }
1366 
1367     //--------------------------------------------------------------------
getSupportedBindingTypes()1368     Sequence< Type > OListBoxModel::getSupportedBindingTypes()
1369     {
1370         Sequence< Type > aTypes(4);
1371         aTypes[0] = ::getCppuType( static_cast< Sequence< sal_Int32 >* >( NULL ) );
1372         aTypes[1] = ::getCppuType( static_cast< sal_Int32* >( NULL ) );
1373         aTypes[2] = ::getCppuType( static_cast< Sequence< ::rtl::OUString >* >( NULL ) );
1374         aTypes[3] = ::getCppuType( static_cast< ::rtl::OUString* >( NULL ) );
1375         return aTypes;
1376     }
1377 
1378     //--------------------------------------------------------------------
stringItemListChanged(ControlModelLock & _rInstanceLock)1379     void OListBoxModel::stringItemListChanged( ControlModelLock& _rInstanceLock )
1380     {
1381         if ( !m_xAggregateSet.is() )
1382             return;
1383 
1384         suspendValueListening();
1385         try
1386         {
1387             m_xAggregateSet->setPropertyValue( PROPERTY_STRINGITEMLIST, makeAny( getStringItemList() ) );
1388         }
1389         catch( const Exception& )
1390         {
1391             DBG_UNHANDLED_EXCEPTION();
1392         }
1393         resumeValueListening();
1394 
1395         // update the selection here
1396         if ( hasExternalValueBinding( ) )
1397             transferExternalValueToControl( _rInstanceLock );
1398         else
1399         {
1400             if ( hasField() )
1401             {
1402                 // TODO: update the selection in case we're bound to a database column
1403             }
1404             else
1405             {
1406                 if ( m_aDefaultSelectSeq.getLength() )
1407                     setControlValue( makeAny( m_aDefaultSelectSeq ), eOther );
1408             }
1409         }
1410     }
1411 
1412     //--------------------------------------------------------------------
connectedExternalListSource()1413     void OListBoxModel::connectedExternalListSource( )
1414     {
1415         // TODO?
1416     }
1417 
1418     //--------------------------------------------------------------------
disconnectedExternalListSource()1419     void OListBoxModel::disconnectedExternalListSource( )
1420     {
1421         // TODO: in case we're part of an already loaded form, we should probably simulate
1422         // an onConnectedDbColumn, so our list get's filled with the data as indicated
1423         // by our SQL-binding related properties
1424     }
1425 
1426     //--------------------------------------------------------------------
impl_refreshDbEntryList(bool _bForce)1427     void OListBoxModel::impl_refreshDbEntryList( bool _bForce )
1428     {
1429         DBG_ASSERT( !hasExternalListSource(), "OListBoxModel::impl_refreshDbEntryList: invalid call!" );
1430 
1431         if  (   !hasExternalListSource( )
1432             &&  ( m_eListSourceType != ListSourceType_VALUELIST )
1433             &&  ( m_xCursor.is() )
1434             )
1435         {
1436             loadData( _bForce );
1437         }
1438     }
1439 
1440     //--------------------------------------------------------------------
refreshInternalEntryList()1441     void OListBoxModel::refreshInternalEntryList()
1442     {
1443         impl_refreshDbEntryList( true );
1444         if ( hasField() && m_xCursor.is() )
1445             initFromField( m_xCursor );
1446     }
1447 
1448     //==================================================================
1449     // OListBoxControl
1450     //==================================================================
1451 
1452     //------------------------------------------------------------------
OListBoxControl_CreateInstance(const Reference<XMultiServiceFactory> & _rxFactory)1453     InterfaceRef SAL_CALL OListBoxControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory) throw (RuntimeException)
1454     {
1455         return *(new OListBoxControl(_rxFactory));
1456     }
1457 
1458     //------------------------------------------------------------------------------
_getTypes()1459     Sequence< Type> OListBoxControl::_getTypes()
1460     {
1461         return TypeBag(
1462             OBoundControl::_getTypes(),
1463             OListBoxControl_BASE::getTypes()
1464         ).getTypes();
1465     }
1466 
1467     //------------------------------------------------------------------
queryAggregation(const Type & _rType)1468     Any SAL_CALL OListBoxControl::queryAggregation(const Type& _rType) throw (RuntimeException)
1469     {
1470         Any aReturn = OListBoxControl_BASE::queryInterface( _rType );
1471 
1472         if  (   !aReturn.hasValue()
1473             ||  _rType.equals( XTypeProvider::static_type() )
1474             )
1475             aReturn = OBoundControl::queryAggregation( _rType );
1476 
1477         return aReturn;
1478     }
1479 
1480     DBG_NAME(OListBoxControl);
1481     //------------------------------------------------------------------------------
OListBoxControl(const Reference<XMultiServiceFactory> & _rxFactory)1482     OListBoxControl::OListBoxControl(const Reference<XMultiServiceFactory>& _rxFactory)
1483         :OBoundControl( _rxFactory, VCL_CONTROL_LISTBOX, sal_False )
1484         ,m_aChangeListeners( m_aMutex )
1485         ,m_aItemListeners( m_aMutex )
1486         ,m_pItemBroadcaster( NULL )
1487     {
1488         DBG_CTOR(OListBoxControl,NULL);
1489 
1490         increment(m_refCount);
1491         {
1492             // als FocusListener anmelden
1493             Reference<XWindow> xComp;
1494             if (query_aggregation(m_xAggregate, xComp))
1495                 xComp->addFocusListener(this);
1496 
1497             // als ItemListener anmelden
1498             if ( query_aggregation( m_xAggregate, m_xAggregateListBox ) )
1499                 m_xAggregateListBox->addItemListener(this);
1500         }
1501         // Refcount bei 2 fuer angemeldete Listener
1502         decrement(m_refCount);
1503 
1504         doSetDelegator();
1505 
1506         m_aChangeTimer.SetTimeout(500);
1507         m_aChangeTimer.SetTimeoutHdl(LINK(this,OListBoxControl,OnTimeout));
1508     }
1509 
1510     //------------------------------------------------------------------------------
~OListBoxControl()1511     OListBoxControl::~OListBoxControl()
1512     {
1513         if (!OComponentHelper::rBHelper.bDisposed)
1514         {
1515             acquire();
1516             dispose();
1517         }
1518 
1519         doResetDelegator();
1520         m_xAggregateListBox.clear();
1521 
1522         DBG_DTOR(OListBoxControl,NULL);
1523     }
1524 
1525     //------------------------------------------------------------------------------
getSupportedServiceNames()1526     StringSequence SAL_CALL OListBoxControl::getSupportedServiceNames() throw(RuntimeException)
1527     {
1528         StringSequence aSupported = OBoundControl::getSupportedServiceNames();
1529         aSupported.realloc(aSupported.getLength() + 1);
1530 
1531         ::rtl::OUString* pArray = aSupported.getArray();
1532         pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_LISTBOX;
1533         return aSupported;
1534     }
1535 
1536 
1537     // XFocusListener
1538     //------------------------------------------------------------------------------
focusGained(const FocusEvent &)1539     void SAL_CALL OListBoxControl::focusGained(const FocusEvent& /*_rEvent*/) throw(RuntimeException)
1540     {
1541         ::osl::MutexGuard aGuard(m_aMutex);
1542         if ( m_aChangeListeners.getLength() ) // only if there are listeners
1543         {
1544             Reference<XPropertySet> xSet(getModel(), UNO_QUERY);
1545             if (xSet.is())
1546             {
1547                 // memorize the current selection for posting the change event
1548                 m_aCurrentSelection = xSet->getPropertyValue(PROPERTY_SELECT_SEQ);
1549             }
1550         }
1551     }
1552 
1553     //------------------------------------------------------------------------------
focusLost(const FocusEvent &)1554     void SAL_CALL OListBoxControl::focusLost(const FocusEvent& /*_rEvent*/) throw(RuntimeException)
1555     {
1556         m_aCurrentSelection.clear();
1557     }
1558 
1559     // XItemListener
1560     //------------------------------------------------------------------------------
itemStateChanged(const ItemEvent & _rEvent)1561     void SAL_CALL OListBoxControl::itemStateChanged(const ItemEvent& _rEvent) throw(RuntimeException)
1562     {
1563         // forward this to our listeners
1564         {
1565             ::osl::MutexGuard aGuard( m_aMutex );
1566             if ( m_aItemListeners.getLength() )
1567             {
1568                 if ( !m_pItemBroadcaster.is() )
1569                 {
1570                     m_pItemBroadcaster.set( new ::comphelper::AsyncEventNotifier );
1571                     m_pItemBroadcaster->create();
1572                 }
1573 		        m_pItemBroadcaster->addEvent( new ItemEventDescription( _rEvent ), this );
1574             }
1575         }
1576 
1577         // and do the handling for the ChangeListeners
1578         ::osl::ClearableMutexGuard aGuard(m_aMutex);
1579         if ( m_aChangeTimer.IsActive() )
1580         {
1581             Reference<XPropertySet> xSet(getModel(), UNO_QUERY);
1582             m_aCurrentSelection = xSet->getPropertyValue(PROPERTY_SELECT_SEQ);
1583 
1584             m_aChangeTimer.Stop();
1585             m_aChangeTimer.Start();
1586         }
1587         else
1588         {
1589             if ( m_aChangeListeners.getLength() && m_aCurrentSelection.hasValue() )
1590             {
1591                 Reference<XPropertySet> xSet(getModel(), UNO_QUERY);
1592                 if (xSet.is())
1593                 {
1594                     // Has the selection been changed?
1595                     sal_Bool bModified(sal_False);
1596                     Any aValue = xSet->getPropertyValue(PROPERTY_SELECT_SEQ);
1597 
1598                     Sequence<sal_Int16>& rSelection = *(Sequence<sal_Int16> *)aValue.getValue();
1599                     Sequence<sal_Int16>& rOldSelection = *(Sequence<sal_Int16> *)m_aCurrentSelection.getValue();
1600                     sal_Int32 nLen = rSelection.getLength();
1601                     if (nLen != rOldSelection.getLength())
1602                         bModified = sal_True;
1603                     else
1604                     {
1605                         const sal_Int16* pVal = rSelection.getConstArray();
1606                         const sal_Int16* pCompVal = rOldSelection.getConstArray();
1607 
1608                         while (nLen-- && !bModified)
1609                             bModified = pVal[nLen] != pCompVal[nLen];
1610                     }
1611 
1612                     if (bModified)
1613                     {
1614                         m_aCurrentSelection = aValue;
1615                         m_aChangeTimer.Start();
1616                     }
1617                 }
1618             }
1619             else if (m_aCurrentSelection.hasValue())
1620                 m_aCurrentSelection.clear();
1621         }
1622     }
1623 
1624     // XEventListener
1625     //------------------------------------------------------------------------------
disposing(const EventObject & _rSource)1626     void SAL_CALL OListBoxControl::disposing(const EventObject& _rSource) throw (RuntimeException)
1627     {
1628         OBoundControl::disposing(_rSource);
1629     }
1630 
1631     // XChangeBroadcaster
1632     //------------------------------------------------------------------------------
addChangeListener(const Reference<XChangeListener> & _rxListener)1633     void SAL_CALL OListBoxControl::addChangeListener(const Reference<XChangeListener>& _rxListener) throw(RuntimeException)
1634     {
1635         m_aChangeListeners.addInterface( _rxListener );
1636     }
1637 
1638     //------------------------------------------------------------------------------
removeChangeListener(const Reference<XChangeListener> & _rxListener)1639     void SAL_CALL OListBoxControl::removeChangeListener(const Reference<XChangeListener>& _rxListener) throw(RuntimeException)
1640     {
1641         m_aChangeListeners.removeInterface( _rxListener );
1642     }
1643 
1644     // OComponentHelper
1645     //------------------------------------------------------------------------------
disposing()1646     void OListBoxControl::disposing()
1647     {
1648         if (m_aChangeTimer.IsActive())
1649             m_aChangeTimer.Stop();
1650 
1651         EventObject aEvent( *this );
1652         m_aChangeListeners.disposeAndClear( aEvent );
1653         m_aItemListeners.disposeAndClear( aEvent );
1654 
1655         {
1656             ::osl::MutexGuard aGuard( m_aMutex );
1657             if ( m_pItemBroadcaster.is() )
1658             {
1659                 m_pItemBroadcaster->removeEventsForProcessor( this );
1660                 m_pItemBroadcaster->terminate();
1661                 m_pItemBroadcaster = NULL;
1662             }
1663         }
1664 
1665         OBoundControl::disposing();
1666     }
1667 
1668     //------------------------------------------------------------------------------
processEvent(const AnyEvent & _rEvent)1669     void OListBoxControl::processEvent( const AnyEvent& _rEvent )
1670     {
1671         Reference< XListBox > xKeepAlive( this );
1672         {
1673             ::osl::MutexGuard aGuard( m_aMutex );
1674             if ( OComponentHelper::rBHelper.bDisposed )
1675                 return;
1676         }
1677         const ItemEventDescription& rItemEvent = static_cast< const ItemEventDescription& >( _rEvent );
1678         m_aItemListeners.notifyEach( &XItemListener::itemStateChanged, rItemEvent.getEventObject() );
1679     }
1680 
1681     //------------------------------------------------------------------------------
1682     IMPL_LINK(OListBoxControl, OnTimeout, void*, /*EMPTYTAG*/)
1683     {
1684         m_aChangeListeners.notifyEach( &XChangeListener::changed, EventObject( *this ) );
1685         return 0L;
1686     }
1687 
1688     //--------------------------------------------------------------------
addItemListener(const Reference<XItemListener> & l)1689     void SAL_CALL OListBoxControl::addItemListener( const Reference< XItemListener >& l ) throw (RuntimeException)
1690     {
1691         m_aItemListeners.addInterface( l );
1692     }
1693 
1694     //--------------------------------------------------------------------
removeItemListener(const Reference<XItemListener> & l)1695     void SAL_CALL OListBoxControl::removeItemListener( const Reference< XItemListener >& l ) throw (RuntimeException)
1696     {
1697         m_aItemListeners.removeInterface( l );
1698     }
1699 
1700     //--------------------------------------------------------------------
addActionListener(const Reference<XActionListener> & l)1701     void SAL_CALL OListBoxControl::addActionListener( const Reference< XActionListener >& l ) throw (RuntimeException)
1702     {
1703         if ( m_xAggregateListBox.is() )
1704             m_xAggregateListBox->addActionListener( l );
1705     }
1706 
1707     //--------------------------------------------------------------------
removeActionListener(const Reference<XActionListener> & l)1708     void SAL_CALL OListBoxControl::removeActionListener( const Reference< XActionListener >& l ) throw (RuntimeException)
1709     {
1710         if ( m_xAggregateListBox.is() )
1711             m_xAggregateListBox->removeActionListener( l );
1712     }
1713 
1714     //--------------------------------------------------------------------
addItem(const::rtl::OUString & aItem,::sal_Int16 nPos)1715     void SAL_CALL OListBoxControl::addItem( const ::rtl::OUString& aItem, ::sal_Int16 nPos ) throw (RuntimeException)
1716     {
1717         if ( m_xAggregateListBox.is() )
1718             m_xAggregateListBox->addItem( aItem, nPos );
1719     }
1720 
1721     //--------------------------------------------------------------------
addItems(const Sequence<::rtl::OUString> & aItems,::sal_Int16 nPos)1722     void SAL_CALL OListBoxControl::addItems( const Sequence< ::rtl::OUString >& aItems, ::sal_Int16 nPos ) throw (RuntimeException)
1723     {
1724         if ( m_xAggregateListBox.is() )
1725             m_xAggregateListBox->addItems( aItems, nPos );
1726     }
1727 
1728     //--------------------------------------------------------------------
removeItems(::sal_Int16 nPos,::sal_Int16 nCount)1729     void SAL_CALL OListBoxControl::removeItems( ::sal_Int16 nPos, ::sal_Int16 nCount ) throw (RuntimeException)
1730     {
1731         if ( m_xAggregateListBox.is() )
1732             m_xAggregateListBox->removeItems( nPos, nCount );
1733     }
1734 
1735     //--------------------------------------------------------------------
getItemCount()1736     ::sal_Int16 SAL_CALL OListBoxControl::getItemCount(  ) throw (RuntimeException)
1737     {
1738         if ( m_xAggregateListBox.is() )
1739             return m_xAggregateListBox->getItemCount();
1740         return 0;
1741     }
1742 
1743     //--------------------------------------------------------------------
getItem(::sal_Int16 nPos)1744     ::rtl::OUString SAL_CALL OListBoxControl::getItem( ::sal_Int16 nPos ) throw (RuntimeException)
1745     {
1746         if ( m_xAggregateListBox.is() )
1747             return m_xAggregateListBox->getItem( nPos );
1748         return ::rtl::OUString( );
1749     }
1750 
1751     //--------------------------------------------------------------------
getItems()1752     Sequence< ::rtl::OUString > SAL_CALL OListBoxControl::getItems(  ) throw (RuntimeException)
1753     {
1754         if ( m_xAggregateListBox.is() )
1755             return m_xAggregateListBox->getItems();
1756         return Sequence< ::rtl::OUString >( );
1757     }
1758 
1759     //--------------------------------------------------------------------
getSelectedItemPos()1760     ::sal_Int16 SAL_CALL OListBoxControl::getSelectedItemPos(  ) throw (RuntimeException)
1761     {
1762         if ( m_xAggregateListBox.is() )
1763             return m_xAggregateListBox->getSelectedItemPos();
1764         return 0;
1765     }
1766 
1767     //--------------------------------------------------------------------
getSelectedItemsPos()1768     Sequence< ::sal_Int16 > SAL_CALL OListBoxControl::getSelectedItemsPos(  ) throw (RuntimeException)
1769     {
1770         if ( m_xAggregateListBox.is() )
1771             return m_xAggregateListBox->getSelectedItemsPos();
1772         return Sequence< ::sal_Int16 >( );
1773     }
1774 
1775     //--------------------------------------------------------------------
getSelectedItem()1776     ::rtl::OUString SAL_CALL OListBoxControl::getSelectedItem(  ) throw (RuntimeException)
1777     {
1778         if ( m_xAggregateListBox.is() )
1779             return m_xAggregateListBox->getSelectedItem();
1780         return ::rtl::OUString( );
1781     }
1782 
1783     //--------------------------------------------------------------------
getSelectedItems()1784     Sequence< ::rtl::OUString > SAL_CALL OListBoxControl::getSelectedItems(  ) throw (RuntimeException)
1785     {
1786         if ( m_xAggregateListBox.is() )
1787             return m_xAggregateListBox->getSelectedItems();
1788         return Sequence< ::rtl::OUString >( );
1789     }
1790 
1791     //--------------------------------------------------------------------
selectItemPos(::sal_Int16 nPos,::sal_Bool bSelect)1792     void SAL_CALL OListBoxControl::selectItemPos( ::sal_Int16 nPos, ::sal_Bool bSelect ) throw (RuntimeException)
1793     {
1794         if ( m_xAggregateListBox.is() )
1795             m_xAggregateListBox->selectItemPos( nPos, bSelect );
1796     }
1797 
1798     //--------------------------------------------------------------------
selectItemsPos(const Sequence<::sal_Int16> & aPositions,::sal_Bool bSelect)1799     void SAL_CALL OListBoxControl::selectItemsPos( const Sequence< ::sal_Int16 >& aPositions, ::sal_Bool bSelect ) throw (RuntimeException)
1800     {
1801         if ( m_xAggregateListBox.is() )
1802             m_xAggregateListBox->selectItemsPos( aPositions, bSelect );
1803     }
1804 
1805     //--------------------------------------------------------------------
selectItem(const::rtl::OUString & aItem,::sal_Bool bSelect)1806     void SAL_CALL OListBoxControl::selectItem( const ::rtl::OUString& aItem, ::sal_Bool bSelect ) throw (RuntimeException)
1807     {
1808         if ( m_xAggregateListBox.is() )
1809             m_xAggregateListBox->selectItem( aItem, bSelect );
1810     }
1811 
1812     //--------------------------------------------------------------------
isMutipleMode()1813     ::sal_Bool SAL_CALL OListBoxControl::isMutipleMode(  ) throw (RuntimeException)
1814     {
1815         if ( m_xAggregateListBox.is() )
1816             return m_xAggregateListBox->isMutipleMode();
1817         return sal_False;
1818     }
1819 
1820     //--------------------------------------------------------------------
setMultipleMode(::sal_Bool bMulti)1821     void SAL_CALL OListBoxControl::setMultipleMode( ::sal_Bool bMulti ) throw (RuntimeException)
1822     {
1823         if ( m_xAggregateListBox.is() )
1824             m_xAggregateListBox->setMultipleMode( bMulti );
1825     }
1826 
1827     //--------------------------------------------------------------------
getDropDownLineCount()1828     ::sal_Int16 SAL_CALL OListBoxControl::getDropDownLineCount(  ) throw (RuntimeException)
1829     {
1830         if ( m_xAggregateListBox.is() )
1831             return m_xAggregateListBox->getDropDownLineCount();
1832         return 0;
1833     }
1834 
1835     //--------------------------------------------------------------------
setDropDownLineCount(::sal_Int16 nLines)1836     void SAL_CALL OListBoxControl::setDropDownLineCount( ::sal_Int16 nLines ) throw (RuntimeException)
1837     {
1838         if ( m_xAggregateListBox.is() )
1839             m_xAggregateListBox->setDropDownLineCount( nLines );
1840     }
1841 
1842     //--------------------------------------------------------------------
makeVisible(::sal_Int16 nEntry)1843     void SAL_CALL OListBoxControl::makeVisible( ::sal_Int16 nEntry ) throw (RuntimeException)
1844     {
1845         if ( m_xAggregateListBox.is() )
1846             m_xAggregateListBox->makeVisible( nEntry );
1847     }
1848 
1849 //.........................................................................
1850 }
1851 //.........................................................................
1852 
1853