1*24acc546SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*24acc546SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*24acc546SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*24acc546SAndrew Rist  * distributed with this work for additional information
6*24acc546SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*24acc546SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*24acc546SAndrew Rist  * "License"); you may not use this file except in compliance
9*24acc546SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*24acc546SAndrew Rist  *
11*24acc546SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*24acc546SAndrew Rist  *
13*24acc546SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*24acc546SAndrew Rist  * software distributed under the License is distributed on an
15*24acc546SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*24acc546SAndrew Rist  * KIND, either express or implied.  See the License for the
17*24acc546SAndrew Rist  * specific language governing permissions and limitations
18*24acc546SAndrew Rist  * under the License.
19*24acc546SAndrew Rist  *
20*24acc546SAndrew Rist  *************************************************************/
21*24acc546SAndrew Rist 
22*24acc546SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_forms.hxx"
26cdf0e10cSrcweir #include "entrylisthelper.hxx"
27cdf0e10cSrcweir #include "FormComponent.hxx"
28cdf0e10cSrcweir 
29cdf0e10cSrcweir #include <osl/diagnose.h>
30cdf0e10cSrcweir #include <comphelper/sequence.hxx>
31cdf0e10cSrcweir #include <comphelper/property.hxx>
32cdf0e10cSrcweir #include <algorithm>
33cdf0e10cSrcweir 
34cdf0e10cSrcweir //.........................................................................
35cdf0e10cSrcweir namespace frm
36cdf0e10cSrcweir {
37cdf0e10cSrcweir //.........................................................................
38cdf0e10cSrcweir 
39cdf0e10cSrcweir     using namespace ::com::sun::star::uno;
40cdf0e10cSrcweir     using namespace ::com::sun::star::lang;
41cdf0e10cSrcweir     using namespace ::com::sun::star::util;
42cdf0e10cSrcweir     using namespace ::com::sun::star::form::binding;
43cdf0e10cSrcweir 
44cdf0e10cSrcweir     //=====================================================================
45cdf0e10cSrcweir     //= OEntryListHelper
46cdf0e10cSrcweir     //=====================================================================
47cdf0e10cSrcweir     //---------------------------------------------------------------------
OEntryListHelper(OControlModel & _rControlModel)48cdf0e10cSrcweir     OEntryListHelper::OEntryListHelper( OControlModel& _rControlModel )
49cdf0e10cSrcweir         :m_rControlModel( _rControlModel )
50cdf0e10cSrcweir         ,m_aRefreshListeners( _rControlModel.getInstanceMutex() )
51cdf0e10cSrcweir     {
52cdf0e10cSrcweir     }
53cdf0e10cSrcweir 
54cdf0e10cSrcweir     //---------------------------------------------------------------------
OEntryListHelper(const OEntryListHelper & _rSource,OControlModel & _rControlModel)55cdf0e10cSrcweir     OEntryListHelper::OEntryListHelper( const OEntryListHelper& _rSource, OControlModel& _rControlModel )
56cdf0e10cSrcweir         :m_rControlModel( _rControlModel )
57cdf0e10cSrcweir         ,m_xListSource ( _rSource.m_xListSource  )
58cdf0e10cSrcweir         ,m_aStringItems( _rSource.m_aStringItems )
59cdf0e10cSrcweir         ,m_aRefreshListeners( _rControlModel.getInstanceMutex() )
60cdf0e10cSrcweir     {
61cdf0e10cSrcweir     }
62cdf0e10cSrcweir 
63cdf0e10cSrcweir     //---------------------------------------------------------------------
~OEntryListHelper()64cdf0e10cSrcweir     OEntryListHelper::~OEntryListHelper( )
65cdf0e10cSrcweir     {
66cdf0e10cSrcweir     }
67cdf0e10cSrcweir 
68cdf0e10cSrcweir     //---------------------------------------------------------------------
setListEntrySource(const Reference<XListEntrySource> & _rxSource)69cdf0e10cSrcweir     void SAL_CALL OEntryListHelper::setListEntrySource( const Reference< XListEntrySource >& _rxSource ) throw (RuntimeException)
70cdf0e10cSrcweir     {
71cdf0e10cSrcweir         ControlModelLock aLock( m_rControlModel );
72cdf0e10cSrcweir 
73cdf0e10cSrcweir         // disconnect from the current external list source
74cdf0e10cSrcweir         disconnectExternalListSource();
75cdf0e10cSrcweir 
76cdf0e10cSrcweir         // and connect to the new one
77cdf0e10cSrcweir         if ( _rxSource.is() )
78cdf0e10cSrcweir             connectExternalListSource( _rxSource, aLock );
79cdf0e10cSrcweir     }
80cdf0e10cSrcweir 
81cdf0e10cSrcweir     //---------------------------------------------------------------------
getListEntrySource()82cdf0e10cSrcweir     Reference< XListEntrySource > SAL_CALL OEntryListHelper::getListEntrySource(  ) throw (RuntimeException)
83cdf0e10cSrcweir     {
84cdf0e10cSrcweir         return m_xListSource;
85cdf0e10cSrcweir     }
86cdf0e10cSrcweir 
87cdf0e10cSrcweir 
88cdf0e10cSrcweir     //---------------------------------------------------------------------
entryChanged(const ListEntryEvent & _rEvent)89cdf0e10cSrcweir     void SAL_CALL OEntryListHelper::entryChanged( const ListEntryEvent& _rEvent ) throw (RuntimeException)
90cdf0e10cSrcweir     {
91cdf0e10cSrcweir         ControlModelLock aLock( m_rControlModel );
92cdf0e10cSrcweir 
93cdf0e10cSrcweir         OSL_ENSURE( _rEvent.Source == m_xListSource,
94cdf0e10cSrcweir             "OEntryListHelper::entryChanged: where did this come from?" );
95cdf0e10cSrcweir         OSL_ENSURE( ( _rEvent.Position >= 0 ) && ( _rEvent.Position < m_aStringItems.getLength() ),
96cdf0e10cSrcweir             "OEntryListHelper::entryChanged: invalid index!" );
97cdf0e10cSrcweir         OSL_ENSURE( _rEvent.Entries.getLength() == 1,
98cdf0e10cSrcweir             "OEntryListHelper::entryChanged: invalid string list!" );
99cdf0e10cSrcweir 
100cdf0e10cSrcweir         if  (   ( _rEvent.Position >= 0 )
101cdf0e10cSrcweir             &&  ( _rEvent.Position < m_aStringItems.getLength() )
102cdf0e10cSrcweir             &&  ( _rEvent.Entries.getLength() > 0 )
103cdf0e10cSrcweir             )
104cdf0e10cSrcweir         {
105cdf0e10cSrcweir             m_aStringItems[ _rEvent.Position ] = _rEvent.Entries[ 0 ];
106cdf0e10cSrcweir             stringItemListChanged( aLock );
107cdf0e10cSrcweir         }
108cdf0e10cSrcweir     }
109cdf0e10cSrcweir 
110cdf0e10cSrcweir     //---------------------------------------------------------------------
entryRangeInserted(const ListEntryEvent & _rEvent)111cdf0e10cSrcweir     void SAL_CALL OEntryListHelper::entryRangeInserted( const ListEntryEvent& _rEvent ) throw (RuntimeException)
112cdf0e10cSrcweir     {
113cdf0e10cSrcweir         ControlModelLock aLock( m_rControlModel );
114cdf0e10cSrcweir 
115cdf0e10cSrcweir         OSL_ENSURE( _rEvent.Source == m_xListSource,
116cdf0e10cSrcweir             "OEntryListHelper::entryRangeInserted: where did this come from?" );
117cdf0e10cSrcweir         OSL_ENSURE( ( _rEvent.Position > 0 ) && ( _rEvent.Position < m_aStringItems.getLength() ) && ( _rEvent.Entries.getLength() > 0 ),
118cdf0e10cSrcweir             "OEntryListHelper::entryRangeRemoved: invalid count and/or position!" );
119cdf0e10cSrcweir 
120cdf0e10cSrcweir         if  (   ( _rEvent.Position > 0 )
121cdf0e10cSrcweir             &&  ( _rEvent.Position < m_aStringItems.getLength() )
122cdf0e10cSrcweir             &&  ( _rEvent.Entries.getLength() > 0 )
123cdf0e10cSrcweir             )
124cdf0e10cSrcweir         {
125cdf0e10cSrcweir             // the entries *before* the insertion pos
126cdf0e10cSrcweir             Sequence< ::rtl::OUString > aKeepEntries(
127cdf0e10cSrcweir                 m_aStringItems.getConstArray(),
128cdf0e10cSrcweir                 _rEvent.Position
129cdf0e10cSrcweir             );
130cdf0e10cSrcweir             // the entries *behind* the insertion pos
131cdf0e10cSrcweir             Sequence< ::rtl::OUString > aMovedEntries(
132cdf0e10cSrcweir                 m_aStringItems.getConstArray() + _rEvent.Position,
133cdf0e10cSrcweir                 m_aStringItems.getLength() - _rEvent.Position
134cdf0e10cSrcweir             );
135cdf0e10cSrcweir 
136cdf0e10cSrcweir             // concat all three parts
137cdf0e10cSrcweir             m_aStringItems = ::comphelper::concatSequences(
138cdf0e10cSrcweir                 aKeepEntries,
139cdf0e10cSrcweir                 _rEvent.Entries,
140cdf0e10cSrcweir                 aMovedEntries
141cdf0e10cSrcweir             );
142cdf0e10cSrcweir 
143cdf0e10cSrcweir             stringItemListChanged( aLock );
144cdf0e10cSrcweir         }
145cdf0e10cSrcweir     }
146cdf0e10cSrcweir 
147cdf0e10cSrcweir     //---------------------------------------------------------------------
entryRangeRemoved(const ListEntryEvent & _rEvent)148cdf0e10cSrcweir     void SAL_CALL OEntryListHelper::entryRangeRemoved( const ListEntryEvent& _rEvent ) throw (RuntimeException)
149cdf0e10cSrcweir     {
150cdf0e10cSrcweir         ControlModelLock aLock( m_rControlModel );
151cdf0e10cSrcweir 
152cdf0e10cSrcweir         OSL_ENSURE( _rEvent.Source == m_xListSource,
153cdf0e10cSrcweir             "OEntryListHelper::entryRangeRemoved: where did this come from?" );
154cdf0e10cSrcweir         OSL_ENSURE( ( _rEvent.Position > 0 ) && ( _rEvent.Count > 0 ) && ( _rEvent.Position + _rEvent.Count <= m_aStringItems.getLength() ),
155cdf0e10cSrcweir             "OEntryListHelper::entryRangeRemoved: invalid count and/or position!" );
156cdf0e10cSrcweir 
157cdf0e10cSrcweir         if  (   ( _rEvent.Position > 0 )
158cdf0e10cSrcweir             &&  ( _rEvent.Count > 0 )
159cdf0e10cSrcweir             &&  ( _rEvent.Position + _rEvent.Count <= m_aStringItems.getLength() )
160cdf0e10cSrcweir             )
161cdf0e10cSrcweir         {
162cdf0e10cSrcweir             // copy all items after the removed ones
163cdf0e10cSrcweir             ::std::copy(
164cdf0e10cSrcweir                 m_aStringItems.getConstArray() + _rEvent.Position + _rEvent.Count,
165cdf0e10cSrcweir                 m_aStringItems.getConstArray() + m_aStringItems.getLength(),
166cdf0e10cSrcweir                 m_aStringItems.getArray( ) + _rEvent.Position
167cdf0e10cSrcweir             );
168cdf0e10cSrcweir             // shrink the array
169cdf0e10cSrcweir             m_aStringItems.realloc( m_aStringItems.getLength() - _rEvent.Count );
170cdf0e10cSrcweir 
171cdf0e10cSrcweir             stringItemListChanged( aLock );
172cdf0e10cSrcweir         }
173cdf0e10cSrcweir     }
174cdf0e10cSrcweir 
175cdf0e10cSrcweir     //---------------------------------------------------------------------
allEntriesChanged(const EventObject & _rEvent)176cdf0e10cSrcweir     void SAL_CALL OEntryListHelper::allEntriesChanged( const EventObject& _rEvent ) throw (RuntimeException)
177cdf0e10cSrcweir     {
178cdf0e10cSrcweir         ControlModelLock aLock( m_rControlModel );
179cdf0e10cSrcweir 
180cdf0e10cSrcweir         OSL_ENSURE( _rEvent.Source == m_xListSource,
181cdf0e10cSrcweir             "OEntryListHelper::allEntriesChanged: where did this come from?" );
182cdf0e10cSrcweir 
183cdf0e10cSrcweir         Reference< XListEntrySource > xSource( _rEvent.Source, UNO_QUERY );
184cdf0e10cSrcweir         if ( _rEvent.Source == m_xListSource )
185cdf0e10cSrcweir         {
186cdf0e10cSrcweir             impl_lock_refreshList( aLock );
187cdf0e10cSrcweir         }
188cdf0e10cSrcweir     }
189cdf0e10cSrcweir 
190cdf0e10cSrcweir     // XRefreshable
191cdf0e10cSrcweir     //------------------------------------------------------------------------------
addRefreshListener(const Reference<XRefreshListener> & _rxListener)192cdf0e10cSrcweir     void SAL_CALL OEntryListHelper::addRefreshListener(const Reference<XRefreshListener>& _rxListener) throw(RuntimeException)
193cdf0e10cSrcweir     {
194cdf0e10cSrcweir         if ( _rxListener.is() )
195cdf0e10cSrcweir             m_aRefreshListeners.addInterface( _rxListener );
196cdf0e10cSrcweir     }
197cdf0e10cSrcweir 
198cdf0e10cSrcweir     //------------------------------------------------------------------------------
removeRefreshListener(const Reference<XRefreshListener> & _rxListener)199cdf0e10cSrcweir     void SAL_CALL OEntryListHelper::removeRefreshListener(const Reference<XRefreshListener>& _rxListener) throw(RuntimeException)
200cdf0e10cSrcweir     {
201cdf0e10cSrcweir         if ( _rxListener.is() )
202cdf0e10cSrcweir             m_aRefreshListeners.removeInterface( _rxListener );
203cdf0e10cSrcweir     }
204cdf0e10cSrcweir 
205cdf0e10cSrcweir     //------------------------------------------------------------------------------
refresh()206cdf0e10cSrcweir     void SAL_CALL OEntryListHelper::refresh() throw(RuntimeException)
207cdf0e10cSrcweir     {
208cdf0e10cSrcweir         {
209cdf0e10cSrcweir             ControlModelLock aLock( m_rControlModel );
210cdf0e10cSrcweir             impl_lock_refreshList( aLock );
211cdf0e10cSrcweir         }
212cdf0e10cSrcweir 
213cdf0e10cSrcweir         EventObject aEvt( static_cast< XRefreshable* >( this ) );
214cdf0e10cSrcweir         m_aRefreshListeners.notifyEach( &XRefreshListener::refreshed, aEvt );
215cdf0e10cSrcweir     }
216cdf0e10cSrcweir 
217cdf0e10cSrcweir     //---------------------------------------------------------------------
impl_lock_refreshList(ControlModelLock & _rInstanceLock)218cdf0e10cSrcweir     void OEntryListHelper::impl_lock_refreshList( ControlModelLock& _rInstanceLock )
219cdf0e10cSrcweir     {
220cdf0e10cSrcweir         if ( hasExternalListSource() )
221cdf0e10cSrcweir         {
222cdf0e10cSrcweir             m_aStringItems = m_xListSource->getAllListEntries( );
223cdf0e10cSrcweir             stringItemListChanged( _rInstanceLock );
224cdf0e10cSrcweir         }
225cdf0e10cSrcweir         else
226cdf0e10cSrcweir             refreshInternalEntryList();
227cdf0e10cSrcweir     }
228cdf0e10cSrcweir 
229cdf0e10cSrcweir     //---------------------------------------------------------------------
handleDisposing(const EventObject & _rEvent)230cdf0e10cSrcweir     bool OEntryListHelper::handleDisposing( const EventObject& _rEvent )
231cdf0e10cSrcweir     {
232cdf0e10cSrcweir         if ( m_xListSource .is() && ( _rEvent.Source == m_xListSource ) )
233cdf0e10cSrcweir         {
234cdf0e10cSrcweir             disconnectExternalListSource( );
235cdf0e10cSrcweir             return true;
236cdf0e10cSrcweir         }
237cdf0e10cSrcweir         return false;
238cdf0e10cSrcweir     }
239cdf0e10cSrcweir 
240cdf0e10cSrcweir     //---------------------------------------------------------------------
disposing()241cdf0e10cSrcweir     void OEntryListHelper::disposing( )
242cdf0e10cSrcweir     {
243cdf0e10cSrcweir         EventObject aEvt( static_cast< XRefreshable* >( this ) );
244cdf0e10cSrcweir         m_aRefreshListeners.disposeAndClear(aEvt);
245cdf0e10cSrcweir 
246cdf0e10cSrcweir         if ( hasExternalListSource( ) )
247cdf0e10cSrcweir             disconnectExternalListSource( );
248cdf0e10cSrcweir     }
249cdf0e10cSrcweir 
250cdf0e10cSrcweir     //---------------------------------------------------------------------
disconnectExternalListSource()251cdf0e10cSrcweir     void OEntryListHelper::disconnectExternalListSource( )
252cdf0e10cSrcweir     {
253cdf0e10cSrcweir         if ( m_xListSource.is() )
254cdf0e10cSrcweir             m_xListSource->removeListEntryListener( this );
255cdf0e10cSrcweir 
256cdf0e10cSrcweir         m_xListSource.clear();
257cdf0e10cSrcweir 
258cdf0e10cSrcweir         disconnectedExternalListSource();
259cdf0e10cSrcweir     }
260cdf0e10cSrcweir 
261cdf0e10cSrcweir     //---------------------------------------------------------------------
connectedExternalListSource()262cdf0e10cSrcweir     void OEntryListHelper::connectedExternalListSource( )
263cdf0e10cSrcweir     {
264cdf0e10cSrcweir         // nothing to do here
265cdf0e10cSrcweir     }
266cdf0e10cSrcweir 
267cdf0e10cSrcweir     //---------------------------------------------------------------------
disconnectedExternalListSource()268cdf0e10cSrcweir     void OEntryListHelper::disconnectedExternalListSource( )
269cdf0e10cSrcweir     {
270cdf0e10cSrcweir         // nothing to do here
271cdf0e10cSrcweir     }
272cdf0e10cSrcweir 
273cdf0e10cSrcweir     //---------------------------------------------------------------------
connectExternalListSource(const Reference<XListEntrySource> & _rxSource,ControlModelLock & _rInstanceLock)274cdf0e10cSrcweir     void OEntryListHelper::connectExternalListSource( const Reference< XListEntrySource >& _rxSource, ControlModelLock& _rInstanceLock )
275cdf0e10cSrcweir     {
276cdf0e10cSrcweir         OSL_ENSURE( !hasExternalListSource(), "OEntryListHelper::connectExternalListSource: only to be called if no external source is active!" );
277cdf0e10cSrcweir         OSL_ENSURE( _rxSource.is(), "OEntryListHelper::connectExternalListSource: invalid list source!" );
278cdf0e10cSrcweir 
279cdf0e10cSrcweir         // remember it
280cdf0e10cSrcweir         m_xListSource = _rxSource;
281cdf0e10cSrcweir 
282cdf0e10cSrcweir         // initially fill our item list
283cdf0e10cSrcweir         if ( m_xListSource.is() )
284cdf0e10cSrcweir         {
285cdf0e10cSrcweir             // be notified when the list changes ...
286cdf0e10cSrcweir             m_xListSource->addListEntryListener( this );
287cdf0e10cSrcweir 
288cdf0e10cSrcweir             m_aStringItems = m_xListSource->getAllListEntries( );
289cdf0e10cSrcweir             stringItemListChanged( _rInstanceLock );
290cdf0e10cSrcweir 
291cdf0e10cSrcweir             // let derivees react on the new list source
292cdf0e10cSrcweir             connectedExternalListSource();
293cdf0e10cSrcweir         }
294cdf0e10cSrcweir     }
295cdf0e10cSrcweir 
296cdf0e10cSrcweir     //---------------------------------------------------------------------
convertNewListSourceProperty(Any & _rConvertedValue,Any & _rOldValue,const Any & _rValue)297cdf0e10cSrcweir     sal_Bool OEntryListHelper::convertNewListSourceProperty( Any& _rConvertedValue,
298cdf0e10cSrcweir         Any& _rOldValue, const Any& _rValue ) SAL_THROW( ( IllegalArgumentException ) )
299cdf0e10cSrcweir     {
300cdf0e10cSrcweir         if ( hasExternalListSource() )
301cdf0e10cSrcweir             throw IllegalArgumentException( );
302cdf0e10cSrcweir             // TODO: error message
303cdf0e10cSrcweir 
304cdf0e10cSrcweir         return ::comphelper::tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, m_aStringItems );
305cdf0e10cSrcweir     }
306cdf0e10cSrcweir 
307cdf0e10cSrcweir     //---------------------------------------------------------------------
setNewStringItemList(const::com::sun::star::uno::Any & _rValue,ControlModelLock & _rInstanceLock)308cdf0e10cSrcweir     void OEntryListHelper::setNewStringItemList( const ::com::sun::star::uno::Any& _rValue, ControlModelLock& _rInstanceLock )
309cdf0e10cSrcweir     {
310cdf0e10cSrcweir         OSL_PRECOND( !hasExternalListSource(), "OEntryListHelper::setNewStringItemList: this should never have survived convertNewListSourceProperty!" );
311cdf0e10cSrcweir         OSL_VERIFY( _rValue >>= m_aStringItems );
312cdf0e10cSrcweir         stringItemListChanged( _rInstanceLock );
313cdf0e10cSrcweir     }
314cdf0e10cSrcweir 
315cdf0e10cSrcweir //.........................................................................
316cdf0e10cSrcweir }   // namespace frm
317cdf0e10cSrcweir //.........................................................................
318