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_toolkit.hxx" 30 31 #include "defaultgridcolumnmodel.hxx" 32 #include "gridcolumn.hxx" 33 34 /** === begin UNO includes === **/ 35 #include <com/sun/star/awt/XVclWindowPeer.hpp> 36 /** === end UNO includes === **/ 37 38 #include <comphelper/sequence.hxx> 39 #include <comphelper/componentguard.hxx> 40 #include <toolkit/helper/servicenames.hxx> 41 #include <rtl/ustrbuf.hxx> 42 #include <tools/diagnose_ex.h> 43 44 //...................................................................................................................... 45 namespace toolkit 46 //...................................................................................................................... 47 { 48 /** === begin UNO using === **/ 49 using ::com::sun::star::uno::Reference; 50 using ::com::sun::star::lang::XMultiServiceFactory; 51 using ::com::sun::star::uno::RuntimeException; 52 using ::com::sun::star::uno::Sequence; 53 using ::com::sun::star::uno::UNO_QUERY_THROW; 54 using ::com::sun::star::uno::UNO_QUERY; 55 using ::com::sun::star::awt::grid::XGridColumn; 56 using ::com::sun::star::uno::XInterface; 57 using ::com::sun::star::lang::XMultiServiceFactory; 58 using ::com::sun::star::lang::XComponent; 59 using ::com::sun::star::lang::EventObject; 60 using ::com::sun::star::container::XContainerListener; 61 using ::com::sun::star::container::ContainerEvent; 62 using ::com::sun::star::uno::Exception; 63 using ::com::sun::star::lang::IndexOutOfBoundsException; 64 using ::com::sun::star::util::XCloneable; 65 using ::com::sun::star::lang::IllegalArgumentException; 66 /** === end UNO using === **/ 67 68 //================================================================================================================== 69 //= DefaultGridColumnModel 70 //================================================================================================================== 71 //------------------------------------------------------------------------------------------------------------------ 72 DefaultGridColumnModel::DefaultGridColumnModel( const Reference< XMultiServiceFactory >& i_factory ) 73 :DefaultGridColumnModel_Base( m_aMutex ) 74 ,m_aContext( i_factory ) 75 ,m_aContainerListeners( m_aMutex ) 76 ,m_aColumns() 77 { 78 } 79 80 //------------------------------------------------------------------------------------------------------------------ 81 DefaultGridColumnModel::DefaultGridColumnModel( DefaultGridColumnModel const & i_copySource ) 82 :cppu::BaseMutex() 83 ,DefaultGridColumnModel_Base( m_aMutex ) 84 ,m_aContext( i_copySource.m_aContext ) 85 ,m_aContainerListeners( m_aMutex ) 86 ,m_aColumns() 87 { 88 Columns aColumns; 89 aColumns.reserve( i_copySource.m_aColumns.size() ); 90 try 91 { 92 for ( Columns::const_iterator col = i_copySource.m_aColumns.begin(); 93 col != i_copySource.m_aColumns.end(); 94 ++col 95 ) 96 { 97 Reference< XCloneable > const xCloneable( *col, UNO_QUERY_THROW ); 98 Reference< XGridColumn > const xClone( xCloneable->createClone(), UNO_QUERY_THROW ); 99 100 GridColumn* const pGridColumn = GridColumn::getImplementation( xClone ); 101 if ( pGridColumn == NULL ) 102 throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "invalid clone source implementation" ) ), *this ); 103 // that's indeed a RuntimeException, not an IllegalArgumentException or some such: 104 // a DefaultGridColumnModel implementation whose columns are not GridColumn implementations 105 // is borked. 106 pGridColumn->setIndex( col - i_copySource.m_aColumns.begin() ); 107 108 aColumns.push_back( xClone ); 109 } 110 } 111 catch( const Exception& ) 112 { 113 DBG_UNHANDLED_EXCEPTION(); 114 } 115 if ( aColumns.size() == i_copySource.m_aColumns.size() ) 116 m_aColumns.swap( aColumns ); 117 } 118 119 //------------------------------------------------------------------------------------------------------------------ 120 DefaultGridColumnModel::~DefaultGridColumnModel() 121 { 122 } 123 124 //------------------------------------------------------------------------------------------------------------------ 125 ::sal_Int32 SAL_CALL DefaultGridColumnModel::getColumnCount() throw (RuntimeException) 126 { 127 return m_aColumns.size(); 128 } 129 130 //------------------------------------------------------------------------------------------------------------------ 131 Reference< XGridColumn > SAL_CALL DefaultGridColumnModel::createColumn( ) throw (RuntimeException) 132 { 133 ::comphelper::ComponentGuard aGuard( *this, rBHelper ); 134 return new GridColumn(); 135 } 136 137 //------------------------------------------------------------------------------------------------------------------ 138 ::sal_Int32 SAL_CALL DefaultGridColumnModel::addColumn( const Reference< XGridColumn > & i_column ) throw (RuntimeException, IllegalArgumentException) 139 { 140 ::comphelper::ComponentGuard aGuard( *this, rBHelper ); 141 142 GridColumn* const pGridColumn = GridColumn::getImplementation( i_column ); 143 if ( pGridColumn == NULL ) 144 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "invalid column implementation" ) ), *this, 1 ); 145 146 m_aColumns.push_back( i_column ); 147 sal_Int32 index = m_aColumns.size() - 1; 148 pGridColumn->setIndex( index ); 149 150 // fire insertion notifications 151 ContainerEvent aEvent; 152 aEvent.Source = *this; 153 aEvent.Accessor <<= index; 154 aEvent.Element <<= i_column; 155 156 aGuard.clear(); 157 m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvent ); 158 159 return index; 160 } 161 162 //------------------------------------------------------------------------------------------------------------------ 163 void SAL_CALL DefaultGridColumnModel::removeColumn( ::sal_Int32 i_columnIndex ) throw (RuntimeException, IndexOutOfBoundsException) 164 { 165 ::comphelper::ComponentGuard aGuard( *this, rBHelper ); 166 167 if ( ( i_columnIndex < 0 ) || ( size_t( i_columnIndex ) >= m_aColumns.size() ) ) 168 throw IndexOutOfBoundsException( ::rtl::OUString(), *this ); 169 170 Columns::iterator const pos = m_aColumns.begin() + i_columnIndex; 171 Reference< XGridColumn > const xColumn( *pos ); 172 m_aColumns.erase( pos ); 173 174 // update indexes of all subsequent columns 175 sal_Int32 columnIndex( i_columnIndex ); 176 for ( Columns::iterator updatePos = m_aColumns.begin() + columnIndex; 177 updatePos != m_aColumns.end(); 178 ++updatePos, ++columnIndex 179 ) 180 { 181 GridColumn* pColumnImpl = GridColumn::getImplementation( *updatePos ); 182 ENSURE_OR_CONTINUE( pColumnImpl, "DefaultGridColumnModel::removeColumn: invalid column implementation!" ); 183 pColumnImpl->setIndex( columnIndex ); 184 } 185 186 // fire removal notifications 187 ContainerEvent aEvent; 188 aEvent.Source = *this; 189 aEvent.Accessor <<= i_columnIndex; 190 aEvent.Element <<= xColumn; 191 192 aGuard.clear(); 193 m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvent ); 194 195 // dispose the removed column 196 try 197 { 198 Reference< XComponent > const xColComp( xColumn, UNO_QUERY_THROW ); 199 xColComp->dispose(); 200 } 201 catch( const Exception& ) 202 { 203 DBG_UNHANDLED_EXCEPTION(); 204 } 205 } 206 207 //------------------------------------------------------------------------------------------------------------------ 208 Sequence< Reference< XGridColumn > > SAL_CALL DefaultGridColumnModel::getColumns() throw (RuntimeException) 209 { 210 ::comphelper::ComponentGuard aGuard( *this, rBHelper ); 211 return ::comphelper::containerToSequence( m_aColumns ); 212 } 213 214 //------------------------------------------------------------------------------------------------------------------ 215 Reference< XGridColumn > SAL_CALL DefaultGridColumnModel::getColumn(::sal_Int32 index) throw (IndexOutOfBoundsException, RuntimeException) 216 { 217 ::comphelper::ComponentGuard aGuard( *this, rBHelper ); 218 219 if ( index >=0 && index < ((sal_Int32)m_aColumns.size())) 220 return m_aColumns[index]; 221 222 throw IndexOutOfBoundsException(); 223 } 224 225 //------------------------------------------------------------------------------------------------------------------ 226 void SAL_CALL DefaultGridColumnModel::setDefaultColumns(sal_Int32 rowElements) throw (RuntimeException) 227 { 228 ::std::vector< ContainerEvent > aRemovedColumns; 229 ::std::vector< ContainerEvent > aInsertedColumns; 230 231 { 232 ::comphelper::ComponentGuard aGuard( *this, rBHelper ); 233 234 // remove existing columns 235 while ( !m_aColumns.empty() ) 236 { 237 const size_t lastColIndex = m_aColumns.size() - 1; 238 239 ContainerEvent aEvent; 240 aEvent.Source = *this; 241 aEvent.Accessor <<= sal_Int32( lastColIndex ); 242 aEvent.Element <<= m_aColumns[ lastColIndex ]; 243 aRemovedColumns.push_back( aEvent ); 244 245 m_aColumns.erase( m_aColumns.begin() + lastColIndex ); 246 } 247 248 // add new columns 249 for ( sal_Int32 i=0; i<rowElements; ++i ) 250 { 251 ::rtl::Reference< GridColumn > const pGridColumn = new GridColumn(); 252 Reference< XGridColumn > const xColumn( pGridColumn.get() ); 253 ::rtl::OUStringBuffer colTitle; 254 colTitle.appendAscii( "Column " ); 255 colTitle.append( i + 1 ); 256 pGridColumn->setTitle( colTitle.makeStringAndClear() ); 257 pGridColumn->setColumnWidth( 80 /* APPFONT */ ); 258 pGridColumn->setFlexibility( 1 ); 259 pGridColumn->setResizeable( sal_True ); 260 pGridColumn->setDataColumnIndex( i ); 261 262 ContainerEvent aEvent; 263 aEvent.Source = *this; 264 aEvent.Accessor <<= i; 265 aEvent.Element <<= xColumn; 266 aInsertedColumns.push_back( aEvent ); 267 268 m_aColumns.push_back( xColumn ); 269 pGridColumn->setIndex( i ); 270 } 271 } 272 273 // fire removal notifications 274 for ( ::std::vector< ContainerEvent >::const_iterator event = aRemovedColumns.begin(); 275 event != aRemovedColumns.end(); 276 ++event 277 ) 278 { 279 m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, *event ); 280 } 281 282 // fire insertion notifications 283 for ( ::std::vector< ContainerEvent >::const_iterator event = aInsertedColumns.begin(); 284 event != aInsertedColumns.end(); 285 ++event 286 ) 287 { 288 m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, *event ); 289 } 290 291 // dispose removed columns 292 for ( ::std::vector< ContainerEvent >::const_iterator event = aRemovedColumns.begin(); 293 event != aRemovedColumns.end(); 294 ++event 295 ) 296 { 297 try 298 { 299 const Reference< XComponent > xColComp( event->Element, UNO_QUERY_THROW ); 300 xColComp->dispose(); 301 } 302 catch( const Exception& ) 303 { 304 DBG_UNHANDLED_EXCEPTION(); 305 } 306 } 307 } 308 309 //------------------------------------------------------------------------------------------------------------------ 310 ::rtl::OUString SAL_CALL DefaultGridColumnModel::getImplementationName( ) throw (RuntimeException) 311 { 312 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.toolkit.DefaultGridColumnModel" ) ); 313 } 314 315 //------------------------------------------------------------------------------------------------------------------ 316 sal_Bool SAL_CALL DefaultGridColumnModel::supportsService( const ::rtl::OUString& i_serviceName ) throw (RuntimeException) 317 { 318 const Sequence< ::rtl::OUString > aServiceNames( getSupportedServiceNames() ); 319 for ( sal_Int32 i=0; i<aServiceNames.getLength(); ++i ) 320 if ( aServiceNames[i] == i_serviceName ) 321 return sal_True; 322 return sal_False; 323 } 324 325 //------------------------------------------------------------------------------------------------------------------ 326 Sequence< ::rtl::OUString > SAL_CALL DefaultGridColumnModel::getSupportedServiceNames( ) throw (RuntimeException) 327 { 328 const ::rtl::OUString aServiceName( ::rtl::OUString::createFromAscii( szServiceName_DefaultGridColumnModel ) ); 329 const Sequence< ::rtl::OUString > aSeq( &aServiceName, 1 ); 330 return aSeq; 331 } 332 333 //------------------------------------------------------------------------------------------------------------------ 334 void SAL_CALL DefaultGridColumnModel::addContainerListener( const Reference< XContainerListener >& i_listener ) throw (RuntimeException) 335 { 336 if ( i_listener.is() ) 337 m_aContainerListeners.addInterface( i_listener ); 338 } 339 340 //------------------------------------------------------------------------------------------------------------------ 341 void SAL_CALL DefaultGridColumnModel::removeContainerListener( const Reference< XContainerListener >& i_listener ) throw (RuntimeException) 342 { 343 if ( i_listener.is() ) 344 m_aContainerListeners.removeInterface( i_listener ); 345 } 346 347 //------------------------------------------------------------------------------------------------------------------ 348 void SAL_CALL DefaultGridColumnModel::disposing() 349 { 350 DefaultGridColumnModel_Base::disposing(); 351 352 EventObject aEvent( *this ); 353 m_aContainerListeners.disposeAndClear( aEvent ); 354 355 ::osl::MutexGuard aGuard( m_aMutex ); 356 357 // remove, dispose and clear columns 358 while ( !m_aColumns.empty() ) 359 { 360 try 361 { 362 const Reference< XComponent > xColComponent( m_aColumns[ 0 ], UNO_QUERY_THROW ); 363 xColComponent->dispose(); 364 } 365 catch( const Exception& ) 366 { 367 DBG_UNHANDLED_EXCEPTION(); 368 } 369 370 m_aColumns.erase( m_aColumns.begin() ); 371 } 372 373 Columns aEmpty; 374 m_aColumns.swap( aEmpty ); 375 } 376 377 //------------------------------------------------------------------------------------------------------------------ 378 Reference< XCloneable > SAL_CALL DefaultGridColumnModel::createClone( ) throw (RuntimeException) 379 { 380 ::comphelper::ComponentGuard aGuard( *this, rBHelper ); 381 return new DefaultGridColumnModel( *this ); 382 } 383 384 //...................................................................................................................... 385 } // namespace toolkit 386 //...................................................................................................................... 387 388 //---------------------------------------------------------------------------------------------------------------------- 389 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL DefaultGridColumnModel_CreateInstance( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rFactory) 390 { 391 return ::com::sun::star::uno::Reference < ::com::sun::star::uno::XInterface >( ( ::cppu::OWeakObject* ) new ::toolkit::DefaultGridColumnModel( _rFactory ) ); 392 } 393