1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ListBox.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_forms.hxx"
34 #include "ListBox.hxx"
35 #include "property.hxx"
36 #include "property.hrc"
37 #include "services.hxx"
38 #include "frm_resource.hxx"
39 #include "frm_resource.hrc"
40 #include "BaseListBox.hxx"
41 #include "listenercontainers.hxx"
42 #include "componenttools.hxx"
44 /** === begin UNO includes === **/
45 #include <com/sun/star/util/XNumberFormatTypes.hpp>
46 #include <com/sun/star/sdbc/XRowSet.hpp>
47 #include <com/sun/star/sdbc/DataType.hpp>
48 #include <com/sun/star/container/XIndexAccess.hpp>
49 #include <com/sun/star/sdb/XSQLQueryComposerFactory.hpp>
50 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
51 #include <com/sun/star/util/NumberFormat.hpp>
52 #include <com/sun/star/awt/XWindow.hpp>
53 #include <com/sun/star/sdbc/XConnection.hpp>
54 #include <com/sun/star/sdb/CommandType.hpp>
55 /** === end UNO includes === **/
57 #include <comphelper/basicio.hxx>
58 #include <comphelper/container.hxx>
59 #include <comphelper/numbers.hxx>
60 #include <comphelper/listenernotification.hxx>
61 #include <connectivity/dbtools.hxx>
62 #include <connectivity/formattedcolumnvalue.hxx>
63 #include <connectivity/dbconversion.hxx>
64 #include <cppuhelper/queryinterface.hxx>
65 #include <rtl/logfile.hxx>
66 #include <tools/debug.hxx>
67 #include <tools/diagnose_ex.h>
68 #include <unotools/sharedunocomponent.hxx>
69 #include <vcl/svapp.hxx>
75 //.........................................................................
78 using namespace ::com::sun::star::uno
;
79 using namespace ::com::sun::star::sdb
;
80 using namespace ::com::sun::star::sdbc
;
81 using namespace ::com::sun::star::sdbcx
;
82 using namespace ::com::sun::star::beans
;
83 using namespace ::com::sun::star::container
;
84 using namespace ::com::sun::star::form
;
85 using namespace ::com::sun::star::awt
;
86 using namespace ::com::sun::star::io
;
87 using namespace ::com::sun::star::lang
;
88 using namespace ::com::sun::star::util
;
89 using namespace ::com::sun::star::form::binding
;
90 using namespace ::dbtools
;
92 using ::connectivity::ORowSetValue
;
94 //==============================================================================
96 //==============================================================================
99 //--------------------------------------------------------------------------
100 struct RowSetValueToString
: public ::std::unary_function
< ORowSetValue
, ::rtl::OUString
>
102 ::rtl::OUString
operator()( const ORowSetValue
& _value
) const
104 return _value
.getString();
108 //--------------------------------------------------------------------------
109 struct AppendRowSetValueString
: public ::std::unary_function
< ::rtl::OUString
, void >
111 AppendRowSetValueString( ::rtl::OUString
& _string
)
116 void operator()( const ::rtl::OUString _append
)
122 ::rtl::OUString
& m_string
;
125 //--------------------------------------------------------------------------
126 Sequence
< ::rtl::OUString
> lcl_convertToStringSequence( const ValueList
& _values
)
128 Sequence
< ::rtl::OUString
> aStrings( _values
.size() );
133 RowSetValueToString()
139 //==============================================================================
140 //= ItemEventDescription
141 //==============================================================================
142 typedef ::comphelper::EventHolder
< ItemEvent
> ItemEventDescription
;
144 //==============================================================================
146 //==============================================================================
147 //------------------------------------------------------------------
148 InterfaceRef SAL_CALL
OListBoxModel_CreateInstance(const Reference
<XMultiServiceFactory
>& _rxFactory
) throw (RuntimeException
)
150 return *(new OListBoxModel(_rxFactory
));
153 //------------------------------------------------------------------------------
154 Sequence
< Type
> OListBoxModel::_getTypes()
157 OBoundControlModel::_getTypes(),
158 OEntryListHelper::getTypes(),
159 OErrorBroadcaster::getTypes()
164 DBG_NAME(OListBoxModel
);
165 //------------------------------------------------------------------
166 OListBoxModel::OListBoxModel(const Reference
<XMultiServiceFactory
>& _rxFactory
)
167 :OBoundControlModel( _rxFactory
, VCL_CONTROLMODEL_LISTBOX
, FRM_SUN_CONTROL_LISTBOX
, sal_True
, sal_True
, sal_True
)
168 // use the old control name for compytibility reasons
169 ,OEntryListHelper( (OControlModel
&)*this )
170 ,OErrorBroadcaster( OComponentHelper::rBHelper
)
171 ,m_aListRowSet( getContext() )
173 ,m_bBoundComponent(sal_False
)
175 DBG_CTOR(OListBoxModel
,NULL
);
177 m_nClassId
= FormComponentType::LISTBOX
;
178 m_eListSourceType
= ListSourceType_VALUELIST
;
179 m_aBoundColumn
<<= (sal_Int16
)1;
180 initValueProperty( PROPERTY_SELECT_SEQ
, PROPERTY_ID_SELECT_SEQ
);
183 //------------------------------------------------------------------
184 OListBoxModel::OListBoxModel( const OListBoxModel
* _pOriginal
, const Reference
<XMultiServiceFactory
>& _rxFactory
)
185 :OBoundControlModel( _pOriginal
, _rxFactory
)
186 ,OEntryListHelper( *_pOriginal
, (OControlModel
&)*this )
187 ,OErrorBroadcaster( OComponentHelper::rBHelper
)
188 ,m_aListRowSet( getContext() )
189 ,m_eListSourceType( _pOriginal
->m_eListSourceType
)
190 ,m_aBoundColumn( _pOriginal
->m_aBoundColumn
)
191 ,m_aListSourceValues( _pOriginal
->m_aListSourceValues
)
192 ,m_aBoundValues( _pOriginal
->m_aBoundValues
)
193 ,m_aDefaultSelectSeq( _pOriginal
->m_aDefaultSelectSeq
)
195 ,m_bBoundComponent(sal_False
)
197 DBG_CTOR(OListBoxModel
,NULL
);
200 //------------------------------------------------------------------
201 OListBoxModel::~OListBoxModel()
203 if (!OComponentHelper::rBHelper
.bDisposed
)
209 DBG_DTOR(OListBoxModel
,NULL
);
213 //------------------------------------------------------------------------------
214 IMPLEMENT_DEFAULT_CLONING( OListBoxModel
)
217 //------------------------------------------------------------------------------
218 StringSequence SAL_CALL
OListBoxModel::getSupportedServiceNames() throw(RuntimeException
)
220 StringSequence aSupported
= OBoundControlModel::getSupportedServiceNames();
222 sal_Int32 nOldLen
= aSupported
.getLength();
223 aSupported
.realloc( nOldLen
+ 8 );
224 ::rtl::OUString
* pStoreTo
= aSupported
.getArray() + nOldLen
;
226 *pStoreTo
++ = BINDABLE_CONTROL_MODEL
;
227 *pStoreTo
++ = DATA_AWARE_CONTROL_MODEL
;
228 *pStoreTo
++ = VALIDATABLE_CONTROL_MODEL
;
230 *pStoreTo
++ = BINDABLE_DATA_AWARE_CONTROL_MODEL
;
231 *pStoreTo
++ = VALIDATABLE_BINDABLE_CONTROL_MODEL
;
233 *pStoreTo
++ = FRM_SUN_COMPONENT_LISTBOX
;
234 *pStoreTo
++ = FRM_SUN_COMPONENT_DATABASE_LISTBOX
;
235 *pStoreTo
++ = BINDABLE_DATABASE_LIST_BOX
;
240 //------------------------------------------------------------------------------
241 Any SAL_CALL
OListBoxModel::queryAggregation(const Type
& _rType
) throw (RuntimeException
)
243 Any aReturn
= OBoundControlModel::queryAggregation( _rType
);
244 if ( !aReturn
.hasValue() )
245 aReturn
= OEntryListHelper::queryInterface( _rType
);
246 if ( !aReturn
.hasValue() )
247 aReturn
= OErrorBroadcaster::queryInterface( _rType
);
252 //------------------------------------------------------------------------------
253 void OListBoxModel::disposing()
255 OBoundControlModel::disposing();
256 OEntryListHelper::disposing();
257 OErrorBroadcaster::disposing();
260 //------------------------------------------------------------------------------
261 void OListBoxModel::getFastPropertyValue(Any
& _rValue
, sal_Int32 _nHandle
) const
265 case PROPERTY_ID_BOUNDCOLUMN
:
266 _rValue
<<= m_aBoundColumn
;
269 case PROPERTY_ID_LISTSOURCETYPE
:
270 _rValue
<<= m_eListSourceType
;
273 case PROPERTY_ID_LISTSOURCE
:
274 _rValue
<<= lcl_convertToStringSequence( m_aListSourceValues
);
277 case PROPERTY_ID_VALUE_SEQ
:
278 _rValue
<<= lcl_convertToStringSequence( m_aBoundValues
);
281 case PROPERTY_ID_DEFAULT_SELECT_SEQ
:
282 _rValue
<<= m_aDefaultSelectSeq
;
285 case PROPERTY_ID_STRINGITEMLIST
:
286 _rValue
<<= getStringItemList();
290 OBoundControlModel::getFastPropertyValue(_rValue
, _nHandle
);
294 //------------------------------------------------------------------------------
295 void OListBoxModel::setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle
, const Any
& _rValue
) throw (com::sun::star::uno::Exception
)
299 case PROPERTY_ID_BOUNDCOLUMN
:
300 DBG_ASSERT((_rValue
.getValueType().getTypeClass() == TypeClass_SHORT
) || (_rValue
.getValueType().getTypeClass() == TypeClass_VOID
),
301 "OListBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" );
302 m_aBoundColumn
= _rValue
;
305 case PROPERTY_ID_LISTSOURCETYPE
:
306 DBG_ASSERT(_rValue
.getValueType().equals(::getCppuType(reinterpret_cast<ListSourceType
*>(NULL
))),
307 "OComboBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" );
308 _rValue
>>= m_eListSourceType
;
311 case PROPERTY_ID_LISTSOURCE
:
314 Sequence
< ::rtl::OUString
> aListSource
;
315 OSL_VERIFY( _rValue
>>= aListSource
);
318 ValueList().swap(m_aListSourceValues
);
320 aListSource
.getConstArray(),
321 aListSource
.getConstArray() + aListSource
.getLength(),
322 ::std::insert_iterator
< ValueList
>( m_aListSourceValues
, m_aListSourceValues
.end() )
326 if ( m_eListSourceType
== ListSourceType_VALUELIST
)
328 m_aBoundValues
= m_aListSourceValues
;
332 if ( m_xCursor
.is() && !hasField() && !hasExternalListSource() )
333 // listbox is already connected to a database, and no external list source
334 // data source changed -> refresh
340 case PROPERTY_ID_VALUE_SEQ
:
341 OSL_ENSURE( false, "ValueItemList is read-only!" );
342 throw PropertyVetoException();
344 case PROPERTY_ID_DEFAULT_SELECT_SEQ
:
345 DBG_ASSERT(_rValue
.getValueType().equals(::getCppuType(reinterpret_cast< Sequence
<sal_Int16
>*>(NULL
))),
346 "OListBoxModel::setFastPropertyValue_NoBroadcast : invalid type !" );
347 _rValue
>>= m_aDefaultSelectSeq
;
349 DBG_ASSERT(m_xAggregateFastSet
.is(), "OListBoxModel::setFastPropertyValue_NoBroadcast(DEFAULT_SELECT_SEQ) : invalid aggregate !");
350 if ( m_xAggregateFastSet
.is() )
351 setControlValue( _rValue
, eOther
);
354 case PROPERTY_ID_STRINGITEMLIST
:
356 ControlModelLock
aLock( *this );
357 setNewStringItemList( _rValue
, aLock
);
358 // TODO: this is bogus. setNewStringItemList expects a guard which has the *only*
359 // lock to the mutex, but setFastPropertyValue_NoBroadcast is already called with
360 // a lock - so we effectively has two locks here, of which setNewStringItemList can
367 OBoundControlModel::setFastPropertyValue_NoBroadcast(_nHandle
, _rValue
);
371 //------------------------------------------------------------------------------
372 sal_Bool
OListBoxModel::convertFastPropertyValue(
373 Any
& _rConvertedValue
, Any
& _rOldValue
, sal_Int32 _nHandle
, const Any
& _rValue
)
374 throw (IllegalArgumentException
)
376 sal_Bool
bModified(sal_False
);
379 case PROPERTY_ID_BOUNDCOLUMN
:
380 bModified
= tryPropertyValue(_rConvertedValue
, _rOldValue
, _rValue
, m_aBoundColumn
, ::getCppuType(reinterpret_cast<sal_Int16
*>(NULL
)));
383 case PROPERTY_ID_LISTSOURCETYPE
:
384 bModified
= tryPropertyValueEnum(_rConvertedValue
, _rOldValue
, _rValue
, m_eListSourceType
);
387 case PROPERTY_ID_LISTSOURCE
:
388 bModified
= tryPropertyValue(_rConvertedValue
, _rOldValue
, _rValue
, lcl_convertToStringSequence( m_aListSourceValues
) );
391 case PROPERTY_ID_VALUE_SEQ
:
392 OSL_ENSURE( false, "ValueItemList is read-only!" );
393 throw PropertyVetoException();
395 case PROPERTY_ID_DEFAULT_SELECT_SEQ
:
396 bModified
= tryPropertyValue(_rConvertedValue
, _rOldValue
, _rValue
, m_aDefaultSelectSeq
);
399 case PROPERTY_ID_STRINGITEMLIST
:
400 bModified
= convertNewListSourceProperty( _rConvertedValue
, _rOldValue
, _rValue
);
404 return OBoundControlModel::convertFastPropertyValue(_rConvertedValue
, _rOldValue
, _nHandle
, _rValue
);
409 //------------------------------------------------------------------------------
410 void SAL_CALL
OListBoxModel::setPropertyValues( const Sequence
< ::rtl::OUString
>& _rPropertyNames
, const Sequence
< Any
>& _rValues
) throw(PropertyVetoException
, IllegalArgumentException
, WrappedTargetException
, RuntimeException
)
412 // if both SelectedItems and StringItemList are set, care for this
413 // #i27024# / 2004-04-05 / fs@openoffice.org
414 const Any
* pSelectSequenceValue
= NULL
;
416 const ::rtl::OUString
* pStartPos
= _rPropertyNames
.getConstArray();
417 const ::rtl::OUString
* pEndPos
= _rPropertyNames
.getConstArray() + _rPropertyNames
.getLength();
418 const ::rtl::OUString
* pSelectedItemsPos
= ::std::find_if(
420 ::std::bind2nd( ::std::equal_to
< ::rtl::OUString
>(), PROPERTY_SELECT_SEQ
)
422 const ::rtl::OUString
* pStringItemListPos
= ::std::find_if(
424 ::std::bind2nd( ::std::equal_to
< ::rtl::OUString
>(), PROPERTY_STRINGITEMLIST
)
426 if ( ( pSelectedItemsPos
!= pEndPos
) && ( pStringItemListPos
!= pEndPos
) )
428 // both properties are present
429 // -> remember the value for the select sequence
430 pSelectSequenceValue
= _rValues
.getConstArray() + ( pSelectedItemsPos
- pStartPos
);
433 OBoundControlModel::setPropertyValues( _rPropertyNames
, _rValues
);
435 if ( pSelectSequenceValue
)
437 setPropertyValue( PROPERTY_SELECT_SEQ
, *pSelectSequenceValue
);
438 // Note that this is the only reliable way, since one of the properties is implemented
439 // by ourself, and one is implemented by the aggregate, we cannot rely on any particular
440 // results when setting them both - too many undocumented behavior in all the involved
445 //------------------------------------------------------------------------------
446 void OListBoxModel::describeFixedProperties( Sequence
< Property
>& _rProps
) const
448 BEGIN_DESCRIBE_PROPERTIES( 7, OBoundControlModel
)
449 DECL_PROP1(TABINDEX
, sal_Int16
, BOUND
);
450 DECL_PROP2(BOUNDCOLUMN
, sal_Int16
, BOUND
, MAYBEVOID
);
451 DECL_PROP1(LISTSOURCETYPE
, ListSourceType
, BOUND
);
452 DECL_PROP1(LISTSOURCE
, StringSequence
, BOUND
);
453 DECL_PROP3(VALUE_SEQ
, StringSequence
, BOUND
, READONLY
, TRANSIENT
);
454 DECL_PROP1(DEFAULT_SELECT_SEQ
, Sequence
<sal_Int16
>, BOUND
);
455 DECL_PROP1(STRINGITEMLIST
, Sequence
< ::rtl::OUString
>, BOUND
);
456 END_DESCRIBE_PROPERTIES();
459 //------------------------------------------------------------------------------
460 void OListBoxModel::describeAggregateProperties( Sequence
< Property
>& _rAggregateProps
) const
462 OBoundControlModel::describeAggregateProperties( _rAggregateProps
);
464 // superseded properties:
465 RemoveProperty( _rAggregateProps
, PROPERTY_STRINGITEMLIST
);
468 //------------------------------------------------------------------------------
469 ::rtl::OUString SAL_CALL
OListBoxModel::getServiceName() throw(RuntimeException
)
471 return FRM_COMPONENT_LISTBOX
; // old (non-sun) name for compatibility !
474 //------------------------------------------------------------------------------
475 void SAL_CALL
OListBoxModel::write(const Reference
<XObjectOutputStream
>& _rxOutStream
)
476 throw(IOException
, RuntimeException
)
478 OBoundControlModel::write(_rxOutStream
);
480 // Dummy-Seq, um Kompatible zu bleiben, wenn SelectSeq nicht mehr gespeichert wird
481 Sequence
<sal_Int16
> aDummySeq
;
484 // Version 0x0002: ListSource wird StringSeq
485 _rxOutStream
->writeShort(0x0004);
487 // Maskierung fuer any
488 sal_uInt16 nAnyMask
= 0;
489 if (m_aBoundColumn
.getValueType().getTypeClass() != TypeClass_VOID
)
490 nAnyMask
|= BOUNDCOLUMN
;
492 _rxOutStream
<< nAnyMask
;
494 _rxOutStream
<< lcl_convertToStringSequence( m_aListSourceValues
);
495 _rxOutStream
<< (sal_Int16
)m_eListSourceType
;
496 _rxOutStream
<< aDummySeq
;
497 _rxOutStream
<< m_aDefaultSelectSeq
;
499 if ((nAnyMask
& BOUNDCOLUMN
) == BOUNDCOLUMN
)
501 sal_Int16 nBoundColumn
= 0;
502 m_aBoundColumn
>>= nBoundColumn
;
503 _rxOutStream
<< nBoundColumn
;
505 writeHelpTextCompatibly(_rxOutStream
);
507 // from version 0x0004 : common properties
508 writeCommonProperties(_rxOutStream
);
511 //------------------------------------------------------------------------------
512 void SAL_CALL
OListBoxModel::read(const Reference
<XObjectInputStream
>& _rxInStream
) throw(IOException
, RuntimeException
)
514 // Bei manchen Variblen muessen Abhaengigkeiten beruecksichtigt werden.
515 // Deshalb muessen sie explizit ueber setPropertyValue() gesetzt werden.
517 OBoundControlModel::read(_rxInStream
);
518 ControlModelLock
aLock( *this );
520 // since we are "overwriting" the StringItemList of our aggregate (means we have
521 // an own place to store the value, instead of relying on our aggregate storing it),
522 // we need to respect what the aggregate just read for the StringItemList property.
525 if ( m_xAggregateSet
.is() )
526 setNewStringItemList( m_xAggregateSet
->getPropertyValue( PROPERTY_STRINGITEMLIST
), aLock
);
528 catch( const Exception
& )
530 OSL_ENSURE( sal_False
, "OComboBoxModel::read: caught an exception while examining the aggregate's string item list!" );
534 sal_uInt16 nVersion
= _rxInStream
->readShort();
535 DBG_ASSERT(nVersion
> 0, "OListBoxModel::read : version 0 ? this should never have been written !");
537 if (nVersion
> 0x0004)
539 DBG_ERROR("OListBoxModel::read : invalid (means unknown) version !");
540 ValueList().swap(m_aListSourceValues
);
541 m_aBoundColumn
<<= (sal_Int16
)0;
542 ValueList().swap(m_aBoundValues
);
543 m_eListSourceType
= ListSourceType_VALUELIST
;
544 m_aDefaultSelectSeq
.realloc(0);
545 defaultCommonProperties();
549 // Maskierung fuer any
551 _rxInStream
>> nAnyMask
;
554 StringSequence aListSourceSeq
;
555 if (nVersion
== 0x0001)
557 // ListSourceSeq aus String zusammenstellen;
558 ::rtl::OUString sListSource
;
559 _rxInStream
>> sListSource
;
561 sal_Int32 nTokens
= 1;
562 const sal_Unicode
* pStr
= sListSource
.getStr();
569 aListSourceSeq
.realloc( nTokens
);
570 for (sal_uInt16 i
=0; i
<nTokens
; ++i
)
573 aListSourceSeq
.getArray()[i
] = sListSource
.getToken(i
,';',nTmp
);
577 _rxInStream
>> aListSourceSeq
;
579 sal_Int16 nListSourceType
;
580 _rxInStream
>> nListSourceType
;
581 m_eListSourceType
= (ListSourceType
)nListSourceType
;
582 Any aListSourceSeqAny
;
583 aListSourceSeqAny
<<= aListSourceSeq
;
585 setFastPropertyValue(PROPERTY_ID_LISTSOURCE
, aListSourceSeqAny
);
587 // Dummy-Seq, um Kompatible zu bleiben, wenn SelectSeq nicht mehr gespeichert wird
588 Sequence
<sal_Int16
> aDummySeq
;
589 _rxInStream
>> aDummySeq
;
592 Sequence
<sal_Int16
> aDefaultSelectSeq
;
593 _rxInStream
>> aDefaultSelectSeq
;
594 Any aDefaultSelectSeqAny
;
595 aDefaultSelectSeqAny
<<= aDefaultSelectSeq
;
596 setFastPropertyValue(PROPERTY_ID_DEFAULT_SELECT_SEQ
, aDefaultSelectSeqAny
);
599 if ((nAnyMask
& BOUNDCOLUMN
) == BOUNDCOLUMN
)
602 _rxInStream
>> nValue
;
603 m_aBoundColumn
<<= nValue
;
607 readHelpTextCompatibly(_rxInStream
);
609 // if our string list is not filled from the value list, we must empty it
610 // this can be the case when somebody saves in alive mode
611 if ( ( m_eListSourceType
!= ListSourceType_VALUELIST
)
612 && !hasExternalListSource()
615 setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST
, makeAny( StringSequence() ) );
619 readCommonProperties(_rxInStream
);
621 // Nach dem Lesen die Defaultwerte anzeigen
622 if ( getControlSource().getLength() )
623 // (not if we don't have a control source - the "State" property acts like it is persistent, then
627 //------------------------------------------------------------------------------
628 void OListBoxModel::loadData( bool _bForce
)
630 RTL_LOGFILE_CONTEXT( aLogContext
, "OListBoxModel::loadData" );
631 DBG_ASSERT( m_eListSourceType
!= ListSourceType_VALUELIST
, "OListBoxModel::loadData: cannot load value list from DB!" );
632 DBG_ASSERT( !hasExternalListSource(), "OListBoxModel::loadData: cannot load from DB when I have an external list source!" );
635 m_bBoundComponent
= sal_False
;
639 Reference
< XConnection
> xConnection
;
640 // is the active connection of our form
641 Reference
< XPropertySet
> xFormProps( m_xCursor
, UNO_QUERY
);
642 if ( xFormProps
.is() )
643 xFormProps
->getPropertyValue( PROPERTY_ACTIVE_CONNECTION
) >>= xConnection
;
646 ::rtl::OUString sListSource
;
647 // if our list source type is no value list, we need to concatenate
648 // the single list source elements
650 m_aListSourceValues
.begin(),
651 m_aListSourceValues
.end(),
652 AppendRowSetValueString( sListSource
)
655 // outta here if we don't have all pre-requisites
656 if ( !xConnection
.is() || !sListSource
.getLength() )
658 ValueList().swap(m_aBoundValues
);
662 sal_Int16 nBoundColumn
= 0;
663 if (m_aBoundColumn
.getValueType().getTypeClass() == TypeClass_SHORT
)
664 m_aBoundColumn
>>= nBoundColumn
;
666 ::utl::SharedUNOComponent
< XResultSet
> xListCursor
;
669 m_aListRowSet
.setConnection( xConnection
);
671 sal_Bool bExecute
= sal_False
;
672 switch (m_eListSourceType
)
674 case ListSourceType_TABLEFIELDS
:
675 // don't work with a statement here, the fields will be collected below
678 case ListSourceType_TABLE
:
680 Reference
<XNameAccess
> xFieldsByName
= getTableFields(xConnection
, sListSource
);
681 Reference
<XIndexAccess
> xFieldsByIndex(xFieldsByName
, UNO_QUERY
);
683 // do we have a bound column if yes we have to select it
684 // and the displayed column is the first column othwhise we act as a combobox
685 ::rtl::OUString aFieldName
;
686 ::rtl::OUString aBoundFieldName
;
688 if ((nBoundColumn
> 0) && xFieldsByIndex
.is())
690 if (xFieldsByIndex
->getCount() <= nBoundColumn
)
693 Reference
<XPropertySet
> xFieldAsSet(xFieldsByIndex
->getByIndex(nBoundColumn
),UNO_QUERY
);
694 xFieldAsSet
->getPropertyValue(PROPERTY_NAME
) >>= aBoundFieldName
;
697 xFieldAsSet
.set(xFieldsByIndex
->getByIndex(0),UNO_QUERY
);
698 xFieldAsSet
->getPropertyValue(PROPERTY_NAME
) >>= aFieldName
;
700 else if (xFieldsByName
.is())
702 if ( xFieldsByName
->hasByName( getControlSource() ) )
703 aFieldName
= getControlSource();
706 // otherwise look for the alias
707 Reference
<XSQLQueryComposerFactory
> xFactory(xConnection
, UNO_QUERY
);
711 Reference
<XSQLQueryComposer
> xComposer
= xFactory
->createQueryComposer();
714 ::rtl::OUString aStatement
;
715 xFormProps
->getPropertyValue( PROPERTY_ACTIVECOMMAND
) >>= aStatement
;
716 xComposer
->setQuery( aStatement
);
720 disposeComponent(xComposer
);
725 Reference
<XColumnsSupplier
> xSupplyFields(xComposer
, UNO_QUERY
);
726 DBG_ASSERT(xSupplyFields
.is(), "OListBoxModel::loadData : invalid query composer !");
728 Reference
<XNameAccess
> xFieldNames
= xSupplyFields
->getColumns();
729 if ( xFieldNames
->hasByName( getControlSource() ) )
731 Reference
<XPropertySet
> xComposerFieldAsSet
;
732 xFieldNames
->getByName( getControlSource() ) >>= xComposerFieldAsSet
;
733 if (hasProperty(PROPERTY_FIELDSOURCE
, xComposerFieldAsSet
))
734 xComposerFieldAsSet
->getPropertyValue(PROPERTY_FIELDSOURCE
) >>= aFieldName
;
736 disposeComponent(xComposer
);
739 if (!aFieldName
.getLength())
742 Reference
<XDatabaseMetaData
> xMeta
= xConnection
->getMetaData();
743 ::rtl::OUString aQuote
= xMeta
->getIdentifierQuoteString();
744 ::rtl::OUString aStatement
= ::rtl::OUString::createFromAscii("SELECT ");
745 if (!aBoundFieldName
.getLength()) // act like a combobox
746 aStatement
+= ::rtl::OUString::createFromAscii("DISTINCT ");
748 aStatement
+= quoteName(aQuote
,aFieldName
);
749 if (aBoundFieldName
.getLength())
751 aStatement
+= ::rtl::OUString::createFromAscii(", ");
752 aStatement
+= quoteName(aQuote
, aBoundFieldName
);
754 aStatement
+= ::rtl::OUString::createFromAscii(" FROM ");
756 ::rtl::OUString sCatalog
, sSchema
, sTable
;
757 qualifiedNameComponents( xMeta
, sListSource
, sCatalog
, sSchema
, sTable
, eInDataManipulation
);
758 aStatement
+= composeTableNameForSelect( xConnection
, sCatalog
, sSchema
, sTable
);
760 m_aListRowSet
.setEscapeProcessing( sal_False
);
761 m_aListRowSet
.setCommand( aStatement
);
766 case ListSourceType_QUERY
:
767 m_aListRowSet
.setCommandFromQuery( sListSource
);
772 m_aListRowSet
.setEscapeProcessing( ListSourceType_SQLPASSTHROUGH
!= m_eListSourceType
);
773 m_aListRowSet
.setCommand( sListSource
);
780 if ( !_bForce
&& !m_aListRowSet
.isDirty() )
782 // if none of the settings of the row set changed, compared to the last
783 // invocation of loadData, then don't re-fill the list. Instead, assume
784 // the list entries are the same.
787 xListCursor
.reset( m_aListRowSet
.execute() );
790 catch(SQLException
& eSQL
)
792 onError(eSQL
, FRM_RES_STRING(RID_BASELISTBOX_ERROR_FILLLIST
));
795 catch(const Exception
& eUnknown
)
801 // Anzeige- und Werteliste fuellen
802 ValueList aDisplayList
, aValueList
;
803 sal_Bool bUseNULL
= hasField() && !isRequired();
807 OSL_ENSURE( xListCursor
.is() || ( ListSourceType_TABLEFIELDS
== m_eListSourceType
),
808 "OListBoxModel::loadData: logic error!" );
809 if ( !xListCursor
.is() && ( ListSourceType_TABLEFIELDS
!= m_eListSourceType
) )
812 switch (m_eListSourceType
)
814 case ListSourceType_SQL
:
815 case ListSourceType_SQLPASSTHROUGH
:
816 case ListSourceType_TABLE
:
817 case ListSourceType_QUERY
:
819 // Feld der 1. Column des ResultSets holen
820 Reference
<XColumnsSupplier
> xSupplyCols(xListCursor
, UNO_QUERY
);
821 DBG_ASSERT(xSupplyCols
.is(), "OListBoxModel::loadData : cursor supports the row set service but is no column supplier?!");
822 Reference
<XIndexAccess
> xColumns
;
823 if (xSupplyCols
.is())
825 xColumns
= Reference
<XIndexAccess
>(xSupplyCols
->getColumns(), UNO_QUERY
);
826 DBG_ASSERT(xColumns
.is(), "OListBoxModel::loadData : no columns supplied by the row set !");
829 Reference
< XPropertySet
> xDataField
;
831 xColumns
->getByIndex(0) >>= xDataField
;
832 if ( !xDataField
.is() )
835 ::dbtools::FormattedColumnValue
aValueFormatter( getContext(), m_xCursor
, xDataField
);
837 // Feld der BoundColumn des ResultSets holen
838 sal_Int32 nBoundColumnType
= DataType::SQLNULL
;
839 if ( ( nBoundColumn
> 0 ) && m_xColumn
.is() )
840 { // don't look for a bound column if we're not connected to a field
843 Reference
< XPropertySet
> xBoundField( xColumns
->getByIndex( nBoundColumn
), UNO_QUERY_THROW
);
844 OSL_VERIFY( xBoundField
->getPropertyValue( ::rtl::OUString::createFromAscii( "Type" ) ) >>= nBoundColumnType
);
846 catch( const Exception
& )
848 DBG_UNHANDLED_EXCEPTION();
851 m_bBoundComponent
= ( nBoundColumnType
!= DataType::SQLNULL
);
853 // Ist die LB an ein Feld gebunden und sind Leereintraege zulaessig
854 // dann wird die Position fuer einen Leereintrag gemerkt
856 RTL_LOGFILE_CONTEXT( aLogContext
, "OListBoxModel::loadData: string collection" );
857 ::rtl::OUString aStr
;
858 sal_Int16 entryPos
= 0;
859 ORowSetValue aBoundValue
;
860 Reference
< XRow
> xCursorRow( xListCursor
, UNO_QUERY_THROW
);
861 while ( xListCursor
->next() && ( entryPos
++ < SHRT_MAX
) ) // SHRT_MAX is the maximum number of entries
863 aStr
= aValueFormatter
.getFormattedValue();
864 aDisplayList
.push_back( aStr
);
866 if ( m_bBoundComponent
)
868 aBoundValue
.fill( nBoundColumn
+ 1, nBoundColumnType
, xCursorRow
);
869 aValueList
.push_back( aBoundValue
);
872 if ( bUseNULL
&& ( m_nNULLPos
== -1 ) && !aStr
.getLength() )
873 m_nNULLPos
= sal_Int16( aDisplayList
.size() - 1 );
878 case ListSourceType_TABLEFIELDS
:
880 Reference
<XNameAccess
> xFieldNames
= getTableFields(xConnection
, sListSource
);
881 if (xFieldNames
.is())
883 StringSequence seqNames
= xFieldNames
->getElementNames();
885 seqNames
.getConstArray(),
886 seqNames
.getConstArray() + seqNames
.getLength(),
887 ::std::insert_iterator
< ValueList
>( aDisplayList
, aDisplayList
.end() )
893 OSL_ENSURE( false, "OListBoxModel::loadData: unreachable!" );
897 catch(SQLException
& eSQL
)
899 onError(eSQL
, FRM_RES_STRING(RID_BASELISTBOX_ERROR_FILLLIST
));
902 catch( const Exception
& )
904 DBG_UNHANDLED_EXCEPTION();
909 // Value-Sequence erzeugen
910 // NULL eintrag hinzufuegen
911 if (bUseNULL
&& m_nNULLPos
== -1)
913 if ( m_bBoundComponent
)
914 aValueList
.insert( aValueList
.begin(), ORowSetValue() );
916 aDisplayList
.insert( aDisplayList
.begin(), ORowSetValue( ::rtl::OUString() ) );
920 m_aBoundValues
= aValueList
;
922 setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST
, makeAny( lcl_convertToStringSequence( aDisplayList
) ) );
925 //------------------------------------------------------------------------------
926 void OListBoxModel::onConnectedDbColumn( const Reference
< XInterface
>& /*_rxForm*/ )
928 // list boxes which are bound to a db column don't have multi selection
929 // - this would be unable to reflect in the db column
932 setFastPropertyValue( PROPERTY_ID_MULTISELECTION
, ::cppu::bool2any( ( sal_False
) ) );
935 if ( !hasExternalListSource() )
936 impl_refreshDbEntryList( false );
939 //------------------------------------------------------------------------------
940 void OListBoxModel::onDisconnectedDbColumn()
942 if ( m_eListSourceType
!= ListSourceType_VALUELIST
)
944 ValueList().swap(m_aBoundValues
);
946 m_bBoundComponent
= sal_False
;
948 if ( !hasExternalListSource() )
949 setFastPropertyValue( PROPERTY_ID_STRINGITEMLIST
, makeAny( StringSequence() ) );
951 m_aListRowSet
.dispose();
955 //------------------------------------------------------------------------------
956 ValueList
OListBoxModel::impl_getValues() const
958 if ( !m_aBoundValues
.empty() )
959 return m_aBoundValues
;
961 Sequence
< ::rtl::OUString
> aStringItems( getStringItemList() );
962 ValueList
aValues( aStringItems
.getLength() );
964 aStringItems
.getConstArray(),
965 aStringItems
.getConstArray() + aStringItems
.getLength(),
971 //------------------------------------------------------------------------------
972 ORowSetValue
OListBoxModel::getFirstSelectedValue() const
974 static const ORowSetValue s_aEmptyVaue
;
976 DBG_ASSERT( m_xAggregateFastSet
.is(), "OListBoxModel::getFirstSelectedValue: invalid aggregate!" );
977 if ( !m_xAggregateFastSet
.is() )
980 Sequence
< sal_Int16
> aSelectedIndices
;
981 OSL_VERIFY( m_xAggregateFastSet
->getFastPropertyValue( getValuePropertyAggHandle() ) >>= aSelectedIndices
);
982 if ( !aSelectedIndices
.getLength() )
983 // nothing selected at all
986 if ( ( m_nNULLPos
!= -1 ) && ( aSelectedIndices
[0] == m_nNULLPos
) )
987 // the dedicated "NULL" entry is selected
990 ValueList
aValues( impl_getValues() );
992 size_t selectedValue
= aSelectedIndices
[0];
993 if ( selectedValue
>= aValues
.size() )
995 OSL_ENSURE( false, "OListBoxModel::getFirstSelectedValue: inconsistent selection/valuelist!" );
999 return aValues
[ selectedValue
];
1002 //------------------------------------------------------------------------------
1003 sal_Bool
OListBoxModel::commitControlValueToDbColumn( bool /*_bPostReset*/ )
1005 // current selektion list
1006 const ORowSetValue
rCurrentValue( getFirstSelectedValue() );
1007 if ( rCurrentValue
!= m_aSaveValue
)
1009 if ( rCurrentValue
.isNull() )
1010 m_xColumnUpdate
->updateNull();
1015 m_xColumnUpdate
->updateObject( rCurrentValue
.makeAny() );
1017 catch ( const Exception
& )
1022 m_aSaveValue
= rCurrentValue
;
1027 // XPropertiesChangeListener
1028 //------------------------------------------------------------------------------
1029 Any
OListBoxModel::translateDbColumnToControlValue()
1031 Reference
< XPropertySet
> xBoundField( getField() );
1032 if ( !xBoundField
.is() )
1034 OSL_ENSURE( false, "OListBoxModel::translateDbColumnToControlValue: no field? How could that happen?!" );
1038 Sequence
< sal_Int16
> aSelectionIndicies
;
1040 // Bei NULL-Eintraegen Selektion aufheben!
1041 ORowSetValue aCurrentValue
;
1042 aCurrentValue
.fill( xBoundField
->getPropertyValue( PROPERTY_VALUE
) );
1044 if ( aCurrentValue
.isNull() )
1046 if ( m_nNULLPos
!= -1 )
1048 aSelectionIndicies
.realloc(1);
1049 aSelectionIndicies
[0] = m_nNULLPos
;
1054 ValueList
aValues( impl_getValues() );
1055 ValueList::const_iterator curValuePos
= ::std::find( aValues
.begin(), aValues
.end(), aCurrentValue
);
1056 if ( curValuePos
!= aValues
.end() )
1058 aSelectionIndicies
.realloc( 1 );
1059 aSelectionIndicies
[0] = curValuePos
- aValues
.begin();
1063 m_aSaveValue
= aCurrentValue
;
1065 return makeAny( aSelectionIndicies
);
1069 //------------------------------------------------------------------------------
1070 Any
OListBoxModel::getDefaultForReset() const
1073 if (m_aDefaultSelectSeq
.getLength())
1074 aValue
<<= m_aDefaultSelectSeq
;
1075 else if (m_nNULLPos
!= -1) // gebundene Listbox
1077 Sequence
<sal_Int16
> aSeq(1);
1078 aSeq
.getArray()[0] = m_nNULLPos
;
1083 Sequence
<sal_Int16
> aSeq
;
1090 //--------------------------------------------------------------------
1091 void SAL_CALL
OListBoxModel::disposing( const EventObject
& _rSource
) throw ( RuntimeException
)
1093 if ( !OEntryListHelper::handleDisposing( _rSource
) )
1094 OBoundControlModel::disposing( _rSource
);
1097 //--------------------------------------------------------------------
1100 /** type how we should transfer our selection to external value bindings
1104 eIndexList
, /// as list of indexes of selected entries
1105 eIndex
, /// as index of the selected entry
1106 eEntryList
, /// as list of string representations of selected entries
1107 eEntry
/// as string representation of the selected entry
1110 //--------------------------------------------------------------------
1111 ExchangeType
lcl_getCurrentExchangeType( const Type
& _rExchangeType
)
1113 switch ( _rExchangeType
.getTypeClass() )
1115 case TypeClass_STRING
:
1117 case TypeClass_LONG
:
1119 case TypeClass_SEQUENCE
:
1121 Type aElementType
= ::comphelper::getSequenceElementType( _rExchangeType
);
1122 switch ( aElementType
.getTypeClass() )
1124 case TypeClass_STRING
:
1126 case TypeClass_LONG
:
1135 OSL_ENSURE( false, "lcl_getCurrentExchangeType: unsupported (unexpected) exchange type!" );
1140 //--------------------------------------------------------------------
1141 Any
OListBoxModel::translateExternalValueToControlValue( const Any
& _rExternalValue
) const
1143 Sequence
< sal_Int16
> aSelectIndexes
;
1145 switch ( lcl_getCurrentExchangeType( getExternalValueType() ) )
1149 // unfortunately, our select sequence is a sequence<short>, while the external binding
1150 // supplies sequence<int> only -> transform this
1151 Sequence
< sal_Int32
> aSelectIndexesPure
;
1152 OSL_VERIFY( _rExternalValue
>>= aSelectIndexesPure
);
1153 aSelectIndexes
.realloc( aSelectIndexesPure
.getLength() );
1155 aSelectIndexesPure
.getConstArray(),
1156 aSelectIndexesPure
.getConstArray() + aSelectIndexesPure
.getLength(),
1157 aSelectIndexes
.getArray()
1164 sal_Int32 nSelectIndex
= -1;
1165 OSL_VERIFY( _rExternalValue
>>= nSelectIndex
);
1166 if ( ( nSelectIndex
>= 0 ) && ( nSelectIndex
< getStringItemList().getLength() ) )
1168 aSelectIndexes
.realloc( 1 );
1169 aSelectIndexes
[ 0 ] = static_cast< sal_Int16
>( nSelectIndex
);
1176 // we can retrieve a string list from the binding for multiple selection
1177 Sequence
< ::rtl::OUString
> aSelectEntries
;
1178 OSL_VERIFY( _rExternalValue
>>= aSelectEntries
);
1180 ::std::set
< sal_Int16
> aSelectionSet
;
1182 // find the selection entries in our item list
1183 const ::rtl::OUString
* pSelectEntries
= aSelectEntries
.getArray();
1184 const ::rtl::OUString
* pSelectEntriesEnd
= pSelectEntries
+ aSelectEntries
.getLength();
1185 while ( pSelectEntries
!= pSelectEntriesEnd
)
1187 // the indexes where the current string appears in our string items
1188 Sequence
< sal_Int16
> aThisEntryIndexes
;
1189 aThisEntryIndexes
= findValue( getStringItemList(), *pSelectEntries
++, sal_False
);
1191 // insert all the indexes of this entry into our set
1193 aThisEntryIndexes
.getConstArray(),
1194 aThisEntryIndexes
.getConstArray() + aThisEntryIndexes
.getLength(),
1195 ::std::insert_iterator
< ::std::set
< sal_Int16
> >( aSelectionSet
, aSelectionSet
.begin() )
1199 // copy the indexes to the sequence
1200 aSelectIndexes
.realloc( aSelectionSet
.size() );
1202 aSelectionSet
.begin(),
1203 aSelectionSet
.end(),
1204 aSelectIndexes
.getArray()
1211 ::rtl::OUString sStringToSelect
;
1212 OSL_VERIFY( _rExternalValue
>>= sStringToSelect
);
1214 aSelectIndexes
= findValue( getStringItemList(), sStringToSelect
, sal_False
);
1219 return makeAny( aSelectIndexes
);
1222 //--------------------------------------------------------------------
1225 //................................................................
1226 struct ExtractStringFromSequence_Safe
: public ::std::unary_function
< sal_Int16
, ::rtl::OUString
>
1229 const Sequence
< ::rtl::OUString
>& m_rList
;
1232 ExtractStringFromSequence_Safe( const Sequence
< ::rtl::OUString
>& _rList
) : m_rList( _rList
) { }
1234 ::rtl::OUString
operator ()( sal_Int16 _nIndex
)
1236 OSL_ENSURE( _nIndex
< m_rList
.getLength(), "ExtractStringFromSequence_Safe: inconsistence!" );
1237 if ( _nIndex
< m_rList
.getLength() )
1238 return m_rList
[ _nIndex
];
1239 return ::rtl::OUString();
1243 //................................................................
1244 Any
lcl_getSingleSelectedEntry( const Sequence
< sal_Int16
>& _rSelectSequence
, const Sequence
< ::rtl::OUString
>& _rStringList
)
1248 // by definition, multiple selected entries are transfered as NULL if the
1249 // binding does not support string lists
1250 if ( _rSelectSequence
.getLength() <= 1 )
1252 ::rtl::OUString sSelectedEntry
;
1254 if ( _rSelectSequence
.getLength() == 1 )
1255 sSelectedEntry
= ExtractStringFromSequence_Safe( _rStringList
)( _rSelectSequence
[0] );
1257 aReturn
<<= sSelectedEntry
;
1263 //................................................................
1264 Any
lcl_getMultiSelectedEntries( const Sequence
< sal_Int16
>& _rSelectSequence
, const Sequence
< ::rtl::OUString
>& _rStringList
)
1266 Sequence
< ::rtl::OUString
> aSelectedEntriesTexts( _rSelectSequence
.getLength() );
1268 _rSelectSequence
.getConstArray(),
1269 _rSelectSequence
.getConstArray() + _rSelectSequence
.getLength(),
1270 aSelectedEntriesTexts
.getArray(),
1271 ExtractStringFromSequence_Safe( _rStringList
)
1273 return makeAny( aSelectedEntriesTexts
);
1277 //--------------------------------------------------------------------
1278 Any
OListBoxModel::translateControlValueToExternalValue( ) const
1280 OSL_PRECOND( hasExternalValueBinding(), "OListBoxModel::translateControlValueToExternalValue: no binding!" );
1282 Sequence
< sal_Int16
> aSelectSequence
;
1283 const_cast< OListBoxModel
* >( this )->getPropertyValue( PROPERTY_SELECT_SEQ
) >>= aSelectSequence
;
1286 switch ( lcl_getCurrentExchangeType( getExternalValueType() ) )
1290 // unfortunately, the select sequence is a sequence<short>, but our binding
1292 Sequence
< sal_Int32
> aTransformed( aSelectSequence
.getLength() );
1294 aSelectSequence
.getConstArray(),
1295 aSelectSequence
.getConstArray() + aSelectSequence
.getLength(),
1296 aTransformed
.getArray()
1298 aReturn
<<= aTransformed
;
1303 if ( aSelectSequence
.getLength() <= 1 )
1305 sal_Int32 nIndex
= -1;
1307 if ( aSelectSequence
.getLength() == 1 )
1308 nIndex
= aSelectSequence
[0];
1315 aReturn
= lcl_getMultiSelectedEntries( aSelectSequence
, getStringItemList() );
1319 aReturn
= lcl_getSingleSelectedEntry( aSelectSequence
, getStringItemList() );
1326 //--------------------------------------------------------------------
1327 Any
OListBoxModel::getCurrentFormComponentValue() const
1329 if ( hasValidator() )
1330 return OBoundControlModel::getCurrentFormComponentValue();
1336 Sequence
< sal_Int16
> aSelectSequence
;
1337 OSL_VERIFY( const_cast< OListBoxModel
* >( this )->getPropertyValue( PROPERTY_SELECT_SEQ
) >>= aSelectSequence
);
1339 sal_Bool
bMultiSelection( sal_False
);
1340 OSL_VERIFY( const_cast< OListBoxModel
* >( this )->getPropertyValue( PROPERTY_MULTISELECTION
) >>= bMultiSelection
);
1342 if ( bMultiSelection
)
1343 aCurretnValue
= lcl_getMultiSelectedEntries( aSelectSequence
, getStringItemList() );
1345 aCurretnValue
= lcl_getSingleSelectedEntry( aSelectSequence
, getStringItemList() );
1347 catch( const Exception
& )
1349 DBG_UNHANDLED_EXCEPTION();
1352 return aCurretnValue
;
1355 //--------------------------------------------------------------------
1356 Sequence
< Type
> OListBoxModel::getSupportedBindingTypes()
1358 Sequence
< Type
> aTypes(4);
1359 aTypes
[0] = ::getCppuType( static_cast< Sequence
< sal_Int32
>* >( NULL
) );
1360 aTypes
[1] = ::getCppuType( static_cast< sal_Int32
* >( NULL
) );
1361 aTypes
[2] = ::getCppuType( static_cast< Sequence
< ::rtl::OUString
>* >( NULL
) );
1362 aTypes
[3] = ::getCppuType( static_cast< ::rtl::OUString
* >( NULL
) );
1366 //--------------------------------------------------------------------
1367 void OListBoxModel::stringItemListChanged( ControlModelLock
& _rInstanceLock
)
1369 if ( !m_xAggregateSet
.is() )
1372 suspendValueListening();
1375 m_xAggregateSet
->setPropertyValue( PROPERTY_STRINGITEMLIST
, makeAny( getStringItemList() ) );
1377 catch( const Exception
& )
1379 DBG_UNHANDLED_EXCEPTION();
1381 resumeValueListening();
1383 // update the selection here
1384 if ( hasExternalValueBinding( ) )
1385 transferExternalValueToControl( _rInstanceLock
);
1390 // TODO: update the selection in case we're bound to a database column
1394 if ( m_aDefaultSelectSeq
.getLength() )
1395 setControlValue( makeAny( m_aDefaultSelectSeq
), eOther
);
1400 //--------------------------------------------------------------------
1401 void OListBoxModel::connectedExternalListSource( )
1406 //--------------------------------------------------------------------
1407 void OListBoxModel::disconnectedExternalListSource( )
1409 // TODO: in case we're part of an already loaded form, we should probably simulate
1410 // an onConnectedDbColumn, so our list get's filled with the data as indicated
1411 // by our SQL-binding related properties
1414 //--------------------------------------------------------------------
1415 void OListBoxModel::impl_refreshDbEntryList( bool _bForce
)
1417 DBG_ASSERT( !hasExternalListSource(), "OListBoxModel::impl_refreshDbEntryList: invalid call!" );
1419 if ( !hasExternalListSource( )
1420 && ( m_eListSourceType
!= ListSourceType_VALUELIST
)
1421 && ( m_xCursor
.is() )
1424 loadData( _bForce
);
1428 //--------------------------------------------------------------------
1429 void OListBoxModel::refreshInternalEntryList()
1431 impl_refreshDbEntryList( true );
1432 if ( hasField() && m_xCursor
.is() )
1433 initFromField( m_xCursor
);
1436 //==================================================================
1438 //==================================================================
1440 //------------------------------------------------------------------
1441 InterfaceRef SAL_CALL
OListBoxControl_CreateInstance(const Reference
<XMultiServiceFactory
>& _rxFactory
) throw (RuntimeException
)
1443 return *(new OListBoxControl(_rxFactory
));
1446 //------------------------------------------------------------------------------
1447 Sequence
< Type
> OListBoxControl::_getTypes()
1450 OBoundControl::_getTypes(),
1451 OListBoxControl_BASE::getTypes()
1455 //------------------------------------------------------------------
1456 Any SAL_CALL
OListBoxControl::queryAggregation(const Type
& _rType
) throw (RuntimeException
)
1458 Any aReturn
= OListBoxControl_BASE::queryInterface( _rType
);
1460 if ( !aReturn
.hasValue()
1461 || _rType
.equals( XTypeProvider::static_type() )
1463 aReturn
= OBoundControl::queryAggregation( _rType
);
1468 DBG_NAME(OListBoxControl
);
1469 //------------------------------------------------------------------------------
1470 OListBoxControl::OListBoxControl(const Reference
<XMultiServiceFactory
>& _rxFactory
)
1471 :OBoundControl( _rxFactory
, VCL_CONTROL_LISTBOX
, sal_False
)
1472 ,m_aChangeListeners( m_aMutex
)
1473 ,m_aItemListeners( m_aMutex
)
1474 ,m_pItemBroadcaster( NULL
)
1476 DBG_CTOR(OListBoxControl
,NULL
);
1478 increment(m_refCount
);
1480 // als FocusListener anmelden
1481 Reference
<XWindow
> xComp
;
1482 if (query_aggregation(m_xAggregate
, xComp
))
1483 xComp
->addFocusListener(this);
1485 // als ItemListener anmelden
1486 if ( query_aggregation( m_xAggregate
, m_xAggregateListBox
) )
1487 m_xAggregateListBox
->addItemListener(this);
1489 // Refcount bei 2 fuer angemeldete Listener
1490 decrement(m_refCount
);
1494 m_aChangeTimer
.SetTimeout(500);
1495 m_aChangeTimer
.SetTimeoutHdl(LINK(this,OListBoxControl
,OnTimeout
));
1498 //------------------------------------------------------------------------------
1499 OListBoxControl::~OListBoxControl()
1501 if (!OComponentHelper::rBHelper
.bDisposed
)
1508 m_xAggregateListBox
.clear();
1510 DBG_DTOR(OListBoxControl
,NULL
);
1513 //------------------------------------------------------------------------------
1514 StringSequence SAL_CALL
OListBoxControl::getSupportedServiceNames() throw(RuntimeException
)
1516 StringSequence aSupported
= OBoundControl::getSupportedServiceNames();
1517 aSupported
.realloc(aSupported
.getLength() + 1);
1519 ::rtl::OUString
* pArray
= aSupported
.getArray();
1520 pArray
[aSupported
.getLength()-1] = FRM_SUN_CONTROL_LISTBOX
;
1526 //------------------------------------------------------------------------------
1527 void SAL_CALL
OListBoxControl::focusGained(const FocusEvent
& /*_rEvent*/) throw(RuntimeException
)
1529 ::osl::MutexGuard
aGuard(m_aMutex
);
1530 if ( m_aChangeListeners
.getLength() ) // only if there are listeners
1532 Reference
<XPropertySet
> xSet(getModel(), UNO_QUERY
);
1535 // memorize the current selection for posting the change event
1536 m_aCurrentSelection
= xSet
->getPropertyValue(PROPERTY_SELECT_SEQ
);
1541 //------------------------------------------------------------------------------
1542 void SAL_CALL
OListBoxControl::focusLost(const FocusEvent
& /*_rEvent*/) throw(RuntimeException
)
1544 m_aCurrentSelection
.clear();
1548 //------------------------------------------------------------------------------
1549 void SAL_CALL
OListBoxControl::itemStateChanged(const ItemEvent
& _rEvent
) throw(RuntimeException
)
1551 // forward this to our listeners
1552 Reference
< XChild
> xChild( getModel(), UNO_QUERY
);
1553 if ( xChild
.is() && xChild
->getParent().is() )
1555 ::osl::MutexGuard
aGuard( m_aMutex
);
1556 if ( m_aItemListeners
.getLength() )
1558 if ( !m_pItemBroadcaster
.is() )
1560 m_pItemBroadcaster
.set( new ::comphelper::AsyncEventNotifier
);
1561 m_pItemBroadcaster
->create();
1563 m_pItemBroadcaster
->addEvent( new ItemEventDescription( _rEvent
), this );
1567 m_aItemListeners
.notifyEach( &XItemListener::itemStateChanged
, _rEvent
);
1569 // and do the handling for the ChangeListeners
1570 ::osl::ClearableMutexGuard
aGuard(m_aMutex
);
1571 if ( m_aChangeTimer
.IsActive() )
1573 Reference
<XPropertySet
> xSet(getModel(), UNO_QUERY
);
1574 m_aCurrentSelection
= xSet
->getPropertyValue(PROPERTY_SELECT_SEQ
);
1576 m_aChangeTimer
.Stop();
1577 m_aChangeTimer
.Start();
1581 if ( m_aChangeListeners
.getLength() && m_aCurrentSelection
.hasValue() )
1583 Reference
<XPropertySet
> xSet(getModel(), UNO_QUERY
);
1586 // Has the selection been changed?
1587 sal_Bool
bModified(sal_False
);
1588 Any aValue
= xSet
->getPropertyValue(PROPERTY_SELECT_SEQ
);
1590 Sequence
<sal_Int16
>& rSelection
= *(Sequence
<sal_Int16
> *)aValue
.getValue();
1591 Sequence
<sal_Int16
>& rOldSelection
= *(Sequence
<sal_Int16
> *)m_aCurrentSelection
.getValue();
1592 sal_Int32 nLen
= rSelection
.getLength();
1593 if (nLen
!= rOldSelection
.getLength())
1594 bModified
= sal_True
;
1597 const sal_Int16
* pVal
= rSelection
.getConstArray();
1598 const sal_Int16
* pCompVal
= rOldSelection
.getConstArray();
1600 while (nLen
-- && !bModified
)
1601 bModified
= pVal
[nLen
] != pCompVal
[nLen
];
1606 m_aCurrentSelection
= aValue
;
1607 m_aChangeTimer
.Start();
1611 else if (m_aCurrentSelection
.hasValue())
1612 m_aCurrentSelection
.clear();
1617 //------------------------------------------------------------------------------
1618 void SAL_CALL
OListBoxControl::disposing(const EventObject
& _rSource
) throw (RuntimeException
)
1620 OBoundControl::disposing(_rSource
);
1623 // XChangeBroadcaster
1624 //------------------------------------------------------------------------------
1625 void SAL_CALL
OListBoxControl::addChangeListener(const Reference
<XChangeListener
>& _rxListener
) throw(RuntimeException
)
1627 m_aChangeListeners
.addInterface( _rxListener
);
1630 //------------------------------------------------------------------------------
1631 void SAL_CALL
OListBoxControl::removeChangeListener(const Reference
<XChangeListener
>& _rxListener
) throw(RuntimeException
)
1633 m_aChangeListeners
.removeInterface( _rxListener
);
1637 //------------------------------------------------------------------------------
1638 void OListBoxControl::disposing()
1640 if (m_aChangeTimer
.IsActive())
1641 m_aChangeTimer
.Stop();
1643 EventObject
aEvent( *this );
1644 m_aChangeListeners
.disposeAndClear( aEvent
);
1645 m_aItemListeners
.disposeAndClear( aEvent
);
1648 ::osl::MutexGuard
aGuard( m_aMutex
);
1649 if ( m_pItemBroadcaster
.is() )
1651 m_pItemBroadcaster
->removeEventsForProcessor( this );
1652 m_pItemBroadcaster
->terminate();
1653 m_pItemBroadcaster
= NULL
;
1657 OBoundControl::disposing();
1660 //------------------------------------------------------------------------------
1661 void OListBoxControl::processEvent( const AnyEvent
& _rEvent
)
1663 Reference
< XListBox
> xKeepAlive( this );
1665 ::osl::MutexGuard
aGuard( m_aMutex
);
1666 if ( OComponentHelper::rBHelper
.bDisposed
)
1669 const ItemEventDescription
& rItemEvent
= static_cast< const ItemEventDescription
& >( _rEvent
);
1670 m_aItemListeners
.notifyEach( &XItemListener::itemStateChanged
, rItemEvent
.getEventObject() );
1673 //------------------------------------------------------------------------------
1674 IMPL_LINK(OListBoxControl
, OnTimeout
, void*, /*EMPTYTAG*/)
1676 m_aChangeListeners
.notifyEach( &XChangeListener::changed
, EventObject( *this ) );
1680 //--------------------------------------------------------------------
1681 void SAL_CALL
OListBoxControl::addItemListener( const Reference
< XItemListener
>& l
) throw (RuntimeException
)
1683 m_aItemListeners
.addInterface( l
);
1686 //--------------------------------------------------------------------
1687 void SAL_CALL
OListBoxControl::removeItemListener( const Reference
< XItemListener
>& l
) throw (RuntimeException
)
1689 m_aItemListeners
.removeInterface( l
);
1692 //--------------------------------------------------------------------
1693 void SAL_CALL
OListBoxControl::addActionListener( const Reference
< XActionListener
>& l
) throw (RuntimeException
)
1695 if ( m_xAggregateListBox
.is() )
1696 m_xAggregateListBox
->addActionListener( l
);
1699 //--------------------------------------------------------------------
1700 void SAL_CALL
OListBoxControl::removeActionListener( const Reference
< XActionListener
>& l
) throw (RuntimeException
)
1702 if ( m_xAggregateListBox
.is() )
1703 m_xAggregateListBox
->removeActionListener( l
);
1706 //--------------------------------------------------------------------
1707 void SAL_CALL
OListBoxControl::addItem( const ::rtl::OUString
& aItem
, ::sal_Int16 nPos
) throw (RuntimeException
)
1709 if ( m_xAggregateListBox
.is() )
1710 m_xAggregateListBox
->addItem( aItem
, nPos
);
1713 //--------------------------------------------------------------------
1714 void SAL_CALL
OListBoxControl::addItems( const Sequence
< ::rtl::OUString
>& aItems
, ::sal_Int16 nPos
) throw (RuntimeException
)
1716 if ( m_xAggregateListBox
.is() )
1717 m_xAggregateListBox
->addItems( aItems
, nPos
);
1720 //--------------------------------------------------------------------
1721 void SAL_CALL
OListBoxControl::removeItems( ::sal_Int16 nPos
, ::sal_Int16 nCount
) throw (RuntimeException
)
1723 if ( m_xAggregateListBox
.is() )
1724 m_xAggregateListBox
->removeItems( nPos
, nCount
);
1727 //--------------------------------------------------------------------
1728 ::sal_Int16 SAL_CALL
OListBoxControl::getItemCount( ) throw (RuntimeException
)
1730 if ( m_xAggregateListBox
.is() )
1731 return m_xAggregateListBox
->getItemCount();
1735 //--------------------------------------------------------------------
1736 ::rtl::OUString SAL_CALL
OListBoxControl::getItem( ::sal_Int16 nPos
) throw (RuntimeException
)
1738 if ( m_xAggregateListBox
.is() )
1739 return m_xAggregateListBox
->getItem( nPos
);
1740 return ::rtl::OUString( );
1743 //--------------------------------------------------------------------
1744 Sequence
< ::rtl::OUString
> SAL_CALL
OListBoxControl::getItems( ) throw (RuntimeException
)
1746 if ( m_xAggregateListBox
.is() )
1747 return m_xAggregateListBox
->getItems();
1748 return Sequence
< ::rtl::OUString
>( );
1751 //--------------------------------------------------------------------
1752 ::sal_Int16 SAL_CALL
OListBoxControl::getSelectedItemPos( ) throw (RuntimeException
)
1754 if ( m_xAggregateListBox
.is() )
1755 return m_xAggregateListBox
->getSelectedItemPos();
1759 //--------------------------------------------------------------------
1760 Sequence
< ::sal_Int16
> SAL_CALL
OListBoxControl::getSelectedItemsPos( ) throw (RuntimeException
)
1762 if ( m_xAggregateListBox
.is() )
1763 return m_xAggregateListBox
->getSelectedItemsPos();
1764 return Sequence
< ::sal_Int16
>( );
1767 //--------------------------------------------------------------------
1768 ::rtl::OUString SAL_CALL
OListBoxControl::getSelectedItem( ) throw (RuntimeException
)
1770 if ( m_xAggregateListBox
.is() )
1771 return m_xAggregateListBox
->getSelectedItem();
1772 return ::rtl::OUString( );
1775 //--------------------------------------------------------------------
1776 Sequence
< ::rtl::OUString
> SAL_CALL
OListBoxControl::getSelectedItems( ) throw (RuntimeException
)
1778 if ( m_xAggregateListBox
.is() )
1779 return m_xAggregateListBox
->getSelectedItems();
1780 return Sequence
< ::rtl::OUString
>( );
1783 //--------------------------------------------------------------------
1784 void SAL_CALL
OListBoxControl::selectItemPos( ::sal_Int16 nPos
, ::sal_Bool bSelect
) throw (RuntimeException
)
1786 if ( m_xAggregateListBox
.is() )
1787 m_xAggregateListBox
->selectItemPos( nPos
, bSelect
);
1790 //--------------------------------------------------------------------
1791 void SAL_CALL
OListBoxControl::selectItemsPos( const Sequence
< ::sal_Int16
>& aPositions
, ::sal_Bool bSelect
) throw (RuntimeException
)
1793 if ( m_xAggregateListBox
.is() )
1794 m_xAggregateListBox
->selectItemsPos( aPositions
, bSelect
);
1797 //--------------------------------------------------------------------
1798 void SAL_CALL
OListBoxControl::selectItem( const ::rtl::OUString
& aItem
, ::sal_Bool bSelect
) throw (RuntimeException
)
1800 if ( m_xAggregateListBox
.is() )
1801 m_xAggregateListBox
->selectItem( aItem
, bSelect
);
1804 //--------------------------------------------------------------------
1805 ::sal_Bool SAL_CALL
OListBoxControl::isMutipleMode( ) throw (RuntimeException
)
1807 if ( m_xAggregateListBox
.is() )
1808 return m_xAggregateListBox
->isMutipleMode();
1812 //--------------------------------------------------------------------
1813 void SAL_CALL
OListBoxControl::setMultipleMode( ::sal_Bool bMulti
) throw (RuntimeException
)
1815 if ( m_xAggregateListBox
.is() )
1816 m_xAggregateListBox
->setMultipleMode( bMulti
);
1819 //--------------------------------------------------------------------
1820 ::sal_Int16 SAL_CALL
OListBoxControl::getDropDownLineCount( ) throw (RuntimeException
)
1822 if ( m_xAggregateListBox
.is() )
1823 return m_xAggregateListBox
->getDropDownLineCount();
1827 //--------------------------------------------------------------------
1828 void SAL_CALL
OListBoxControl::setDropDownLineCount( ::sal_Int16 nLines
) throw (RuntimeException
)
1830 if ( m_xAggregateListBox
.is() )
1831 m_xAggregateListBox
->setDropDownLineCount( nLines
);
1834 //--------------------------------------------------------------------
1835 void SAL_CALL
OListBoxControl::makeVisible( ::sal_Int16 nEntry
) throw (RuntimeException
)
1837 if ( m_xAggregateListBox
.is() )
1838 m_xAggregateListBox
->makeVisible( nEntry
);
1841 //.........................................................................
1843 //.........................................................................