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