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