Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <com/sun/star/table/XMergeableCell.hpp>
31 : :
32 : : #include <algorithm>
33 : :
34 : : #include <vcl/svapp.hxx>
35 : : #include <osl/mutex.hxx>
36 : :
37 : : #include "cell.hxx"
38 : : #include "cellcursor.hxx"
39 : : #include "tablemodel.hxx"
40 : : #include "tablerow.hxx"
41 : : #include "tablerows.hxx"
42 : : #include "tablecolumn.hxx"
43 : : #include "tablecolumns.hxx"
44 : : #include "tableundo.hxx"
45 : : #include "svx/svdotable.hxx"
46 : : #include "svx/svdmodel.hxx"
47 : : #include "svx/svdstr.hrc"
48 : : #include "svx/svdglob.hxx"
49 : :
50 : : using ::rtl::OUString;
51 : : using namespace ::osl;
52 : : using namespace ::com::sun::star::uno;
53 : : using namespace ::com::sun::star::table;
54 : : using namespace ::com::sun::star::lang;
55 : : using namespace ::com::sun::star::container;
56 : : using namespace ::com::sun::star::beans;
57 : : using namespace ::com::sun::star::util;
58 : :
59 : : // -----------------------------------------------------------------------------
60 : :
61 : : namespace sdr { namespace table {
62 : :
63 : : // -----------------------------------------------------------------------------
64 : :
65 : : // removes the given range from a vector
66 : 0 : template< class Vec, class Iter > void remove_range( Vec& rVector, sal_Int32 nIndex, sal_Int32 nCount )
67 : : {
68 : 0 : const sal_Int32 nSize = static_cast<sal_Int32>(rVector.size());
69 [ # # ]: 0 : if( nCount && (nIndex >= 0) && (nIndex < nSize) )
[ # # # # ]
[ # # ][ # # ]
[ # # ]
70 : : {
71 [ # # ][ # # ]: 0 : if( (nIndex + nCount) >= nSize )
72 : : {
73 : : // remove at end
74 : 0 : rVector.resize( nIndex );
75 : : }
76 : : else
77 : : {
78 : 0 : Iter aBegin( rVector.begin() );
79 [ # # ][ # # ]: 0 : while( nIndex-- )
80 [ # # ][ # # ]: 0 : aBegin++;
81 [ # # ][ # # ]: 0 : if( nCount == 1 )
82 : : {
83 [ # # ][ # # ]: 0 : rVector.erase( aBegin );
84 : : }
85 : : else
86 : : {
87 : 0 : Iter aEnd( aBegin );
88 : :
89 [ # # ][ # # ]: 0 : while( nCount-- )
90 [ # # ][ # # ]: 0 : aEnd++;
91 [ # # ][ # # ]: 0 : rVector.erase( aBegin, aEnd );
92 : : }
93 : : }
94 : : }
95 : 0 : }
96 : :
97 : : // -----------------------------------------------------------------------------
98 : :
99 : : /** inserts a range into a vector */
100 : 27 : template< class Vec, class Iter, class Entry > sal_Int32 insert_range( Vec& rVector, sal_Int32 nIndex, sal_Int32 nCount )
101 : : {
102 [ + - ][ + - ]: 27 : if( nCount )
103 : : {
104 [ + - ][ + - ]: 27 : if( nIndex >= static_cast< sal_Int32 >( rVector.size() ) )
105 : : {
106 : : // append at end
107 : 27 : nIndex = static_cast< sal_Int32 >( rVector.size() ); // cap to end
108 : 27 : rVector.resize( nIndex + nCount );
109 : : }
110 : : else
111 : : {
112 : : // insert
113 : 0 : sal_Int32 nFind = nIndex;
114 : 0 : Iter aIter( rVector.begin() );
115 [ # # ][ # # ]: 0 : while( nFind-- )
116 [ # # ][ # # ]: 0 : aIter++;
117 : :
118 : 0 : Entry aEmpty;
119 [ # # ][ # # ]: 0 : rVector.insert( aIter, nCount, aEmpty );
120 : : }
121 : : }
122 : 27 : return nIndex;
123 : : }
124 : :
125 : : // -----------------------------------------------------------------------------
126 : :
127 : 6 : TableModel::TableModel( SdrTableObj* pTableObj )
128 : : : TableModelBase( m_aMutex )
129 : : , mpTableObj( pTableObj )
130 : : , mbModified( sal_False )
131 : : , mbNotifyPending( false )
132 [ + - ][ + - ]: 6 : , mnNotifyLock( 0 )
[ + - ]
133 : : {
134 : 6 : }
135 : :
136 : 0 : TableModel::TableModel( SdrTableObj* pTableObj, const TableModelRef& xSourceTable )
137 : : : TableModelBase( m_aMutex )
138 : : , mpTableObj( pTableObj )
139 : : , mbModified( sal_False )
140 : : , mbNotifyPending( false )
141 [ # # ][ # # ]: 0 : , mnNotifyLock( 0 )
[ # # ]
142 : : {
143 [ # # ]: 0 : if( xSourceTable.is() )
144 : : {
145 : 0 : const sal_Int32 nColCount = xSourceTable->getColumnCountImpl();
146 : 0 : const sal_Int32 nRowCount = xSourceTable->getRowCountImpl();
147 : :
148 [ # # ]: 0 : init( nColCount, nRowCount );
149 : :
150 : 0 : sal_Int32 nRows = nRowCount;
151 [ # # ]: 0 : while( nRows-- )
152 [ # # ]: 0 : (*maRows[nRows]) = (*xSourceTable->maRows[nRows]);
153 : :
154 : 0 : sal_Int32 nColumns = nColCount;
155 [ # # ]: 0 : while( nColumns-- )
156 [ # # ]: 0 : (*maColumns[nColumns]) = (*xSourceTable->maColumns[nColumns]);
157 : :
158 : : // copy cells
159 [ # # ]: 0 : for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
160 : : {
161 [ # # ]: 0 : for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
162 : : {
163 [ # # ]: 0 : CellRef xTargetCell( getCell( nCol, nRow ) );
164 [ # # ]: 0 : if( xTargetCell.is() )
165 [ # # ][ # # ]: 0 : xTargetCell->cloneFrom( xSourceTable->getCell( nCol, nRow ) );
166 : 0 : }
167 : : }
168 : : }
169 : 0 : }
170 : :
171 : : // -----------------------------------------------------------------------------
172 : :
173 [ + - ]: 6 : TableModel::~TableModel()
174 : : {
175 [ - + ]: 12 : }
176 : :
177 : : // -----------------------------------------------------------------------------
178 : :
179 : 6 : void TableModel::init( sal_Int32 nColumns, sal_Int32 nRows )
180 : : {
181 [ + - ]: 6 : if( nRows < 20 )
182 : 6 : maRows.reserve( 20 );
183 : :
184 [ + - ]: 6 : if( nColumns < 20 )
185 : 6 : maColumns.reserve( 20 );
186 : :
187 [ + - ][ + - ]: 6 : if( nRows && nColumns )
188 : : {
189 : 6 : maColumns.resize( nColumns );
190 : 6 : maRows.resize( nRows );
191 : :
192 [ + + ]: 12 : while( nRows-- )
193 [ + - ]: 6 : maRows[nRows].set( new TableRow( this, nRows, nColumns ) );
194 : :
195 [ + + ]: 12 : while( nColumns-- )
196 [ + - ]: 6 : maColumns[nColumns].set( new TableColumn( this, nColumns ) );
197 : : }
198 : 6 : }
199 : :
200 : : // -----------------------------------------------------------------------------
201 : : // ICellRange
202 : : // -----------------------------------------------------------------------------
203 : :
204 : 0 : sal_Int32 TableModel::getLeft()
205 : : {
206 : 0 : return 0;
207 : : }
208 : :
209 : : // -----------------------------------------------------------------------------
210 : :
211 : 0 : sal_Int32 TableModel::getTop()
212 : : {
213 : 0 : return 0;
214 : : }
215 : :
216 : : // -----------------------------------------------------------------------------
217 : :
218 : 0 : sal_Int32 TableModel::getRight()
219 : : {
220 : 0 : return getColumnCount();
221 : : }
222 : :
223 : : // -----------------------------------------------------------------------------
224 : :
225 : 0 : sal_Int32 TableModel::getBottom()
226 : : {
227 : 0 : return getRowCount();
228 : : }
229 : :
230 : : // -----------------------------------------------------------------------------
231 : :
232 : 0 : Reference< XTable > TableModel::getTable()
233 : : {
234 : 0 : return this;
235 : : }
236 : :
237 : : // -----------------------------------------------------------------------------
238 : :
239 : 0 : void TableModel::UndoInsertRows( sal_Int32 nIndex, sal_Int32 nCount )
240 : : {
241 [ # # ]: 0 : TableModelNotifyGuard aGuard( this );
242 : :
243 : : // remove the rows
244 [ # # ]: 0 : remove_range<RowVector,RowVector::iterator>( maRows, nIndex, nCount );
245 [ # # ]: 0 : updateRows();
246 [ # # ][ # # ]: 0 : setModified(sal_True);
247 : 0 : }
248 : :
249 : : // -----------------------------------------------------------------------------
250 : :
251 : 0 : void TableModel::UndoRemoveRows( sal_Int32 nIndex, RowVector& aRows )
252 : : {
253 [ # # ]: 0 : TableModelNotifyGuard aGuard( this );
254 : :
255 : 0 : const sal_Int32 nCount = sal::static_int_cast< sal_Int32 >( aRows.size() );
256 : :
257 [ # # ]: 0 : nIndex = insert_range<RowVector,RowVector::iterator,TableRowRef>( maRows, nIndex, nCount );
258 : :
259 [ # # ]: 0 : for( sal_Int32 nOffset = 0; nOffset < nCount; ++nOffset )
260 : 0 : maRows[nIndex+nOffset] = aRows[nOffset];
261 : :
262 [ # # ]: 0 : updateRows();
263 [ # # ][ # # ]: 0 : setModified(sal_True);
264 : 0 : }
265 : :
266 : : // -----------------------------------------------------------------------------
267 : :
268 : 0 : void TableModel::UndoInsertColumns( sal_Int32 nIndex, sal_Int32 nCount )
269 : : {
270 [ # # ]: 0 : TableModelNotifyGuard aGuard( this );
271 : :
272 : : // now remove the columns
273 [ # # ]: 0 : remove_range<ColumnVector,ColumnVector::iterator>( maColumns, nIndex, nCount );
274 : 0 : sal_Int32 nRows = getRowCountImpl();
275 [ # # ]: 0 : while( nRows-- )
276 [ # # ]: 0 : maRows[nRows]->removeColumns( nIndex, nCount );
277 : :
278 [ # # ]: 0 : updateColumns();
279 [ # # ][ # # ]: 0 : setModified(sal_True);
280 : 0 : }
281 : :
282 : : // -----------------------------------------------------------------------------
283 : :
284 : 0 : void TableModel::UndoRemoveColumns( sal_Int32 nIndex, ColumnVector& aCols, CellVector& aCells )
285 : : {
286 [ # # ]: 0 : TableModelNotifyGuard aGuard( this );
287 : :
288 : 0 : const sal_Int32 nCount = sal::static_int_cast< sal_Int32 >( aCols.size() );
289 : :
290 : : // assert if there are not enough cells saved
291 : : DBG_ASSERT( (aCols.size() * maRows.size()) == aCells.size(), "sdr::table::TableModel::UndoRemoveColumns(), invalid undo data!" );
292 : :
293 [ # # ]: 0 : nIndex = insert_range<ColumnVector,ColumnVector::iterator,TableColumnRef>( maColumns, nIndex, nCount );
294 [ # # ]: 0 : for( sal_Int32 nOffset = 0; nOffset < nCount; ++nOffset )
295 : 0 : maColumns[nIndex+nOffset] = aCols[nOffset];
296 : :
297 : 0 : CellVector::iterator aIter( aCells.begin() );
298 : :
299 : 0 : sal_Int32 nRows = getRowCountImpl();
300 [ # # ]: 0 : for( sal_Int32 nRow = 0; nRow < nRows; ++nRow )
301 [ # # ]: 0 : maRows[nRow]->insertColumns( nIndex, nCount, &aIter );
302 : :
303 [ # # ]: 0 : updateColumns();
304 [ # # ][ # # ]: 0 : setModified(sal_True);
305 : 0 : }
306 : :
307 : : // -----------------------------------------------------------------------------
308 : : // XTable
309 : : // -----------------------------------------------------------------------------
310 : :
311 : 0 : Reference< XCellCursor > SAL_CALL TableModel::createCursor() throw (RuntimeException)
312 : : {
313 [ # # ]: 0 : ::SolarMutexGuard aGuard;
314 [ # # ][ # # ]: 0 : return createCursorByRange( Reference< XCellRange >( this ) );
[ # # ]
315 : : }
316 : :
317 : : // -----------------------------------------------------------------------------
318 : :
319 : 0 : Reference< XCellCursor > SAL_CALL TableModel::createCursorByRange( const Reference< XCellRange >& Range ) throw (IllegalArgumentException, RuntimeException)
320 : : {
321 [ # # ]: 0 : ::SolarMutexGuard aGuard;
322 : :
323 [ # # ][ # # ]: 0 : ICellRange* pRange = dynamic_cast< ICellRange* >( Range.get() );
324 [ # # ][ # # ]: 0 : if( (pRange == 0) || (pRange->getTable().get() != this) )
[ # # ][ # # ]
[ # # ]
[ # # # # ]
325 [ # # ]: 0 : throw IllegalArgumentException();
326 : :
327 : 0 : TableModelRef xModel( this );
328 [ # # ][ # # ]: 0 : return new CellCursor( xModel, pRange->getLeft(), pRange->getTop(), pRange->getRight(), pRange->getBottom() );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
329 : : }
330 : :
331 : : // -----------------------------------------------------------------------------
332 : :
333 : 306 : sal_Int32 SAL_CALL TableModel::getRowCount() throw (RuntimeException)
334 : : {
335 [ + - ]: 306 : ::SolarMutexGuard aGuard;
336 [ + - ]: 306 : return getRowCountImpl();
337 : : }
338 : :
339 : : // -----------------------------------------------------------------------------
340 : :
341 : 876 : sal_Int32 SAL_CALL TableModel::getColumnCount() throw (RuntimeException)
342 : : {
343 [ + - ]: 876 : ::SolarMutexGuard aGuard;
344 [ + - ]: 876 : return getColumnCountImpl();
345 : : }
346 : :
347 : : // -----------------------------------------------------------------------------
348 : : // XComponent
349 : : // -----------------------------------------------------------------------------
350 : :
351 : 6 : void TableModel::dispose() throw (RuntimeException)
352 : : {
353 [ + - ]: 6 : ::SolarMutexGuard aGuard;
354 [ + - ][ + - ]: 6 : TableModelBase::dispose();
355 : 6 : }
356 : :
357 : : // -----------------------------------------------------------------------------
358 : :
359 : 48 : void SAL_CALL TableModel::addEventListener( const Reference< XEventListener >& xListener ) throw (RuntimeException)
360 : : {
361 : 48 : TableModelBase::addEventListener( xListener );
362 : 48 : }
363 : :
364 : : // -----------------------------------------------------------------------------
365 : :
366 : 0 : void SAL_CALL TableModel::removeEventListener( const Reference< XEventListener >& xListener ) throw (RuntimeException)
367 : : {
368 : 0 : TableModelBase::removeEventListener( xListener );
369 : 0 : }
370 : :
371 : : // -----------------------------------------------------------------------------
372 : : // XModifiable
373 : : // -----------------------------------------------------------------------------
374 : :
375 : 0 : sal_Bool SAL_CALL TableModel::isModified( ) throw (RuntimeException)
376 : : {
377 [ # # ]: 0 : ::SolarMutexGuard aGuard;
378 [ # # ]: 0 : return mbModified;
379 : : }
380 : :
381 : : // -----------------------------------------------------------------------------
382 : :
383 : 219 : void SAL_CALL TableModel::setModified( sal_Bool bModified ) throw (PropertyVetoException, RuntimeException)
384 : : {
385 : : {
386 [ + - ]: 219 : ::SolarMutexGuard aGuard;
387 [ + - ]: 219 : mbModified = bModified;
388 : : }
389 [ + - ]: 219 : if( bModified )
390 : 219 : notifyModification();
391 : 219 : }
392 : :
393 : : // -----------------------------------------------------------------------------
394 : : // XModifyBroadcaster
395 : : // -----------------------------------------------------------------------------
396 : :
397 : 6 : void SAL_CALL TableModel::addModifyListener( const Reference< XModifyListener >& xListener ) throw (RuntimeException)
398 : : {
399 : 6 : rBHelper.addListener( XModifyListener::static_type() , xListener );
400 : 6 : }
401 : :
402 : : // -----------------------------------------------------------------------------
403 : :
404 : 0 : void SAL_CALL TableModel::removeModifyListener( const Reference< XModifyListener >& xListener ) throw (RuntimeException)
405 : : {
406 : 0 : rBHelper.removeListener( XModifyListener::static_type() , xListener );
407 : 0 : }
408 : :
409 : : // -----------------------------------------------------------------------------
410 : : // XColumnRowRange
411 : : // -----------------------------------------------------------------------------
412 : :
413 : 96 : Reference< XTableColumns > SAL_CALL TableModel::getColumns() throw (RuntimeException)
414 : : {
415 [ + - ]: 96 : ::SolarMutexGuard aGuard;
416 : :
417 [ + + ]: 96 : if( !mxTableColumns.is() )
418 [ + - ]: 6 : mxTableColumns.set( new TableColumns( this ) );
419 [ + - ][ + - ]: 96 : return mxTableColumns.get();
[ + - ]
420 : : }
421 : :
422 : : // -----------------------------------------------------------------------------
423 : :
424 : 108 : Reference< XTableRows > SAL_CALL TableModel::getRows() throw (RuntimeException)
425 : : {
426 [ + - ]: 108 : ::SolarMutexGuard aGuard;
427 : :
428 [ + + ]: 108 : if( !mxTableRows.is() )
429 [ + - ]: 6 : mxTableRows.set( new TableRows( this ) );
430 [ + - ][ + - ]: 108 : return mxTableRows.get();
[ + - ]
431 : : }
432 : :
433 : : // -----------------------------------------------------------------------------
434 : : // XCellRange
435 : : // -----------------------------------------------------------------------------
436 : :
437 : 3138 : Reference< XCell > SAL_CALL TableModel::getCellByPosition( sal_Int32 nColumn, sal_Int32 nRow ) throw ( IndexOutOfBoundsException, RuntimeException)
438 : : {
439 [ + - ]: 3138 : ::SolarMutexGuard aGuard;
440 : :
441 [ + - ]: 3138 : CellRef xCell( getCell( nColumn, nRow ) );
442 [ + - ]: 3138 : if( xCell.is() )
443 [ + - ][ + - ]: 6276 : return xCell.get();
444 : :
445 [ # # ][ + - ]: 3138 : throw IndexOutOfBoundsException();
446 : : }
447 : :
448 : : // -----------------------------------------------------------------------------
449 : :
450 : 0 : Reference< XCellRange > SAL_CALL TableModel::getCellRangeByPosition( sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom ) throw (IndexOutOfBoundsException, RuntimeException)
451 : : {
452 [ # # ]: 0 : ::SolarMutexGuard aGuard;
453 : :
454 [ # # ][ # # ]: 0 : if( (nLeft >= 0) && (nTop >= 0) && (nRight >= nLeft) && (nBottom >= nTop) && (nRight < getColumnCountImpl()) && (nBottom < getRowCountImpl() ) )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
455 : : {
456 : 0 : TableModelRef xModel( this );
457 [ # # ][ # # ]: 0 : return new CellRange( xModel, nLeft, nTop, nRight, nBottom );
[ # # ]
458 : : }
459 : :
460 [ # # ][ # # ]: 0 : throw IndexOutOfBoundsException();
461 : : }
462 : :
463 : : // -----------------------------------------------------------------------------
464 : :
465 : 0 : Reference< XCellRange > SAL_CALL TableModel::getCellRangeByName( const OUString& /*aRange*/ ) throw (RuntimeException)
466 : : {
467 : 0 : return Reference< XCellRange >();
468 : : }
469 : :
470 : : // -----------------------------------------------------------------------------
471 : : // XPropertySet
472 : : // -----------------------------------------------------------------------------
473 : :
474 : 0 : Reference< XPropertySetInfo > SAL_CALL TableModel::getPropertySetInfo( ) throw (RuntimeException)
475 : : {
476 : 0 : Reference< XPropertySetInfo > xInfo;
477 : 0 : return xInfo;
478 : : }
479 : :
480 : : // -----------------------------------------------------------------------------
481 : :
482 : 0 : void SAL_CALL TableModel::setPropertyValue( const ::rtl::OUString& /*aPropertyName*/, const Any& /*aValue*/ ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
483 : : {
484 : 0 : }
485 : :
486 : : // -----------------------------------------------------------------------------
487 : :
488 : 0 : Any SAL_CALL TableModel::getPropertyValue( const OUString& /*PropertyName*/ ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
489 : : {
490 : 0 : return Any();
491 : : }
492 : :
493 : : // -----------------------------------------------------------------------------
494 : :
495 : 0 : void SAL_CALL TableModel::addPropertyChangeListener( const OUString& /*aPropertyName*/, const Reference< XPropertyChangeListener >& /*xListener*/ ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
496 : : {
497 : 0 : }
498 : :
499 : : // -----------------------------------------------------------------------------
500 : :
501 : 0 : void SAL_CALL TableModel::removePropertyChangeListener( const OUString& /*aPropertyName*/, const Reference< XPropertyChangeListener >& /*xListener*/ ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
502 : : {
503 : 0 : }
504 : :
505 : : // -----------------------------------------------------------------------------
506 : :
507 : 0 : void SAL_CALL TableModel::addVetoableChangeListener( const OUString& /*aPropertyName*/, const Reference< XVetoableChangeListener >& /*xListener*/ ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
508 : : {
509 : 0 : }
510 : :
511 : : // -----------------------------------------------------------------------------
512 : :
513 : 0 : void SAL_CALL TableModel::removeVetoableChangeListener( const OUString& /*aPropertyName*/, const Reference< XVetoableChangeListener >& /*xListener*/ ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
514 : : {
515 : 0 : }
516 : :
517 : : // -----------------------------------------------------------------------------
518 : : // XFastPropertySet
519 : : // -----------------------------------------------------------------------------
520 : :
521 : 0 : void SAL_CALL TableModel::setFastPropertyValue( ::sal_Int32 /*nHandle*/, const Any& /*aValue*/ ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
522 : : {
523 : 0 : }
524 : :
525 : : // -----------------------------------------------------------------------------
526 : :
527 : 0 : Any SAL_CALL TableModel::getFastPropertyValue( ::sal_Int32 /*nHandle*/ ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException)
528 : : {
529 : 0 : Any aAny;
530 : 0 : return aAny;
531 : : }
532 : :
533 : : // -----------------------------------------------------------------------------
534 : : // internals
535 : : // -----------------------------------------------------------------------------
536 : :
537 : 3771 : sal_Int32 TableModel::getRowCountImpl() const
538 : : {
539 : 3771 : return static_cast< sal_Int32 >( maRows.size() );
540 : : }
541 : :
542 : : // -----------------------------------------------------------------------------
543 : :
544 : 4335 : sal_Int32 TableModel::getColumnCountImpl() const
545 : : {
546 : 4335 : return static_cast< sal_Int32 >( maColumns.size() );
547 : : }
548 : :
549 : : // -----------------------------------------------------------------------------
550 : :
551 : 6 : void TableModel::disposing()
552 : : {
553 [ + - ]: 6 : if( !maRows.empty() )
554 : : {
555 : 6 : RowVector::iterator aIter( maRows.begin() );
556 [ + - ][ + + ]: 36 : while( aIter != maRows.end() )
557 [ + - ][ + - ]: 30 : (*aIter++)->dispose();
558 [ + - ]: 6 : RowVector().swap(maRows);
559 : : }
560 : :
561 [ + - ]: 6 : if( !maColumns.empty() )
562 : : {
563 : 6 : ColumnVector::iterator aIter( maColumns.begin() );
564 [ + - ][ + + ]: 30 : while( aIter != maColumns.end() )
565 [ + - ][ + - ]: 24 : (*aIter++)->dispose();
566 [ + - ]: 6 : ColumnVector().swap(maColumns);
567 : : }
568 : :
569 [ + - ]: 6 : if( mxTableColumns.is() )
570 : : {
571 : 6 : mxTableColumns->dispose();
572 : 6 : mxTableColumns.clear();
573 : : }
574 : :
575 [ + - ]: 6 : if( mxTableRows.is() )
576 : : {
577 : 6 : mxTableRows->dispose();
578 : 6 : mxTableRows.clear();
579 : : }
580 : :
581 : 6 : mpTableObj = 0;
582 : 6 : }
583 : :
584 : : // -----------------------------------------------------------------------------
585 : : // XBroadcaster
586 : : // -----------------------------------------------------------------------------
587 : :
588 : 195 : void TableModel::lockBroadcasts() throw (RuntimeException)
589 : : {
590 [ + - ]: 195 : ::SolarMutexGuard aGuard;
591 [ + - ]: 195 : ++mnNotifyLock;
592 : 195 : }
593 : : // -----------------------------------------------------------------------------
594 : :
595 : 195 : void TableModel::unlockBroadcasts() throw (RuntimeException)
596 : : {
597 [ + - ]: 195 : ::SolarMutexGuard aGuard;
598 : 195 : --mnNotifyLock;
599 [ + + ]: 195 : if( mnNotifyLock <= 0 )
600 : : {
601 : 60 : mnNotifyLock = 0;
602 [ + + ]: 60 : if( mbNotifyPending )
603 [ + - ]: 24 : notifyModification();
604 [ + - ]: 195 : }
605 : 195 : }
606 : :
607 : : // -----------------------------------------------------------------------------
608 : 243 : void TableModel::notifyModification()
609 : : {
610 [ + - ]: 243 : ::osl::MutexGuard guard( m_aMutex );
611 [ + + ][ + - ]: 243 : if( (mnNotifyLock == 0) && mpTableObj && mpTableObj->GetModel() )
[ + - ][ + - ]
[ + + ]
612 : : {
613 : 24 : mbNotifyPending = false;
614 : :
615 [ + - ][ + - ]: 24 : ::cppu::OInterfaceContainerHelper * pModifyListeners = rBHelper.getContainer( XModifyListener::static_type() );
616 [ + - ]: 24 : if( pModifyListeners )
617 : : {
618 [ + - ]: 24 : EventObject aSource;
619 [ + - ]: 24 : aSource.Source = static_cast< ::cppu::OWeakObject* >(this);
620 [ + - ][ + - ]: 24 : pModifyListeners->notifyEach( &XModifyListener::modified, aSource);
621 : : }
622 : : }
623 : : else
624 : : {
625 : 219 : mbNotifyPending = true;
626 [ + - ]: 243 : }
627 : 243 : }
628 : :
629 : : // -----------------------------------------------------------------------------
630 : :
631 : 3249 : CellRef TableModel::getCell( sal_Int32 nCol, sal_Int32 nRow ) const
632 : : {
633 [ + - ][ + - ]: 3249 : if( ((nRow >= 0) && (nRow < getRowCountImpl())) && (nCol >= 0) && (nCol < getColumnCountImpl()) )
[ + - ][ + - ]
[ + - ]
634 : : {
635 : 3249 : return maRows[nRow]->maCells[nCol];
636 : : }
637 : : else
638 : : {
639 : 0 : CellRef xRet;
640 : 3249 : return xRet;
641 : : }
642 : : }
643 : :
644 : : // -----------------------------------------------------------------------------
645 : :
646 : 48 : CellRef TableModel::createCell()
647 : : {
648 : 48 : CellRef xCell;
649 [ + - ]: 48 : if( mpTableObj )
650 [ + - ]: 48 : mpTableObj->createCell( xCell );
651 : 48 : return xCell;
652 : : }
653 : :
654 : : // -----------------------------------------------------------------------------
655 : :
656 : 3 : void TableModel::insertColumns( sal_Int32 nIndex, sal_Int32 nCount )
657 : : {
658 [ + - ][ + - ]: 3 : if( nCount && mpTableObj )
659 : : {
660 : : try
661 : : {
662 [ + - ]: 3 : SdrModel* pModel = mpTableObj->GetModel();
663 : :
664 [ + - ]: 3 : TableModelNotifyGuard aGuard( this );
665 [ + - ]: 3 : nIndex = insert_range<ColumnVector,ColumnVector::iterator,TableColumnRef>( maColumns, nIndex, nCount );
666 : :
667 : 3 : sal_Int32 nRows = getRowCountImpl();
668 [ + + ]: 6 : while( nRows-- )
669 [ + - ]: 3 : maRows[nRows]->insertColumns( nIndex, nCount );
670 : :
671 [ + - ]: 3 : ColumnVector aNewColumns(nCount);
672 [ + + ]: 21 : for( sal_Int32 nOffset = 0; nOffset < nCount; ++nOffset )
673 : : {
674 [ + - ]: 18 : TableColumnRef xNewCol( new TableColumn( this, nIndex+nOffset ) );
675 : 18 : maColumns[nIndex+nOffset] = xNewCol;
676 : 18 : aNewColumns[nOffset] = xNewCol;
677 : 18 : }
678 : :
679 [ + - ][ + - ]: 3 : const bool bUndo = pModel && mpTableObj->IsInserted() && pModel->IsUndoEnabled();
[ + - ][ + - ]
[ - + ]
680 [ - + ]: 3 : if( bUndo )
681 : : {
682 [ # # ][ # # ]: 0 : pModel->BegUndo( ImpGetResStr(STR_TABLE_INSCOL) );
[ # # ]
683 [ # # ][ # # ]: 0 : pModel->AddUndo( pModel->GetSdrUndoFactory().CreateUndoGeoObject(*mpTableObj) );
[ # # ]
684 : :
685 : 0 : TableModelRef xThis( this );
686 : :
687 : 0 : nRows = getRowCountImpl();
688 [ # # ]: 0 : CellVector aNewCells( nCount * nRows );
689 : 0 : CellVector::iterator aCellIter( aNewCells.begin() );
690 : :
691 : 0 : nRows = getRowCountImpl();
692 [ # # ]: 0 : for( sal_Int32 nRow = 0; nRow < nRows; ++nRow )
693 : : {
694 [ # # ]: 0 : for( sal_Int32 nOffset = 0; nOffset < nCount; ++nOffset )
695 [ # # ][ # # ]: 0 : (*aCellIter++) = getCell( nIndex + nOffset, nRow );
[ # # ]
696 : : }
697 : :
698 [ # # ][ # # ]: 0 : pModel->AddUndo( new InsertColUndo( xThis, nIndex, aNewColumns, aNewCells ) );
[ # # ]
699 : : }
700 : :
701 : 3 : const sal_Int32 nRowCount = getRowCountImpl();
702 : : // check if cells merge over new columns
703 [ + + ]: 6 : for( sal_Int32 nCol = 0; nCol < nIndex; ++nCol )
704 : : {
705 [ + + ]: 6 : for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
706 : : {
707 [ + - ]: 3 : CellRef xCell( getCell( nCol, nRow ) );
708 [ + - ][ + - ]: 3 : sal_Int32 nColSpan = (xCell.is() && !xCell->isMerged()) ? xCell->getColumnSpan() : 1;
[ + - ][ + - ]
709 [ - + ][ # # ]: 3 : if( (nColSpan != 1) && ((nColSpan + nCol ) > nIndex) )
710 : : {
711 : : // cell merges over newly created columns, so add the new columns to the merged cell
712 [ # # ]: 0 : const sal_Int32 nRowSpan = xCell->getRowSpan();
713 : 0 : nColSpan += nCount;
714 [ # # ]: 0 : merge( nCol, nRow, nColSpan, nRowSpan );
715 : : }
716 : 3 : }
717 : : }
718 : :
719 [ - + ]: 3 : if( bUndo )
720 [ # # ]: 0 : pModel->EndUndo();
721 : :
722 [ + - ]: 3 : if( pModel )
723 [ + - ][ + - ]: 3 : pModel->SetChanged();
[ # # ]
724 : :
725 : : }
726 : 0 : catch( Exception& )
727 : : {
728 : : OSL_FAIL("sdr::table::TableModel::insertColumns(), exception caught!");
729 : : }
730 : 3 : updateColumns();
731 : 3 : setModified(sal_True);
732 : : }
733 : 3 : }
734 : :
735 : : // -----------------------------------------------------------------------------
736 : :
737 : 0 : void TableModel::removeColumns( sal_Int32 nIndex, sal_Int32 nCount )
738 : : {
739 : 0 : sal_Int32 nColCount = getColumnCountImpl();
740 : :
741 [ # # ][ # # ]: 0 : if( mpTableObj && nCount && (nIndex >= 0) && (nIndex < nColCount) )
[ # # ][ # # ]
742 : : {
743 : : try
744 : : {
745 [ # # ]: 0 : TableModelNotifyGuard aGuard( this );
746 : :
747 : : // clip removed columns to columns actually avalaible
748 [ # # ]: 0 : if( (nIndex + nCount) > nColCount )
749 : 0 : nCount = nColCount - nIndex;
750 : :
751 : 0 : sal_Int32 nRows = getRowCountImpl();
752 : :
753 [ # # ]: 0 : SdrModel* pModel = mpTableObj->GetModel();
754 : :
755 [ # # ][ # # ]: 0 : const bool bUndo = pModel && mpTableObj->IsInserted() && pModel->IsUndoEnabled();
[ # # ][ # # ]
[ # # ]
756 [ # # ]: 0 : if( bUndo )
757 : : {
758 [ # # ][ # # ]: 0 : pModel->BegUndo( ImpGetResStr(STR_UNDO_COL_DELETE) );
[ # # ]
759 [ # # ][ # # ]: 0 : pModel->AddUndo( pModel->GetSdrUndoFactory().CreateUndoGeoObject(*mpTableObj) );
[ # # ]
760 : :
761 : 0 : TableModelRef xThis( this );
762 [ # # ]: 0 : ColumnVector aRemovedCols( nCount );
763 : : sal_Int32 nOffset;
764 [ # # ]: 0 : for( nOffset = 0; nOffset < nCount; ++nOffset )
765 : : {
766 : 0 : aRemovedCols[nOffset] = maColumns[nIndex+nOffset];
767 : : }
768 : :
769 [ # # ]: 0 : CellVector aRemovedCells( nCount * nRows );
770 : 0 : CellVector::iterator aCellIter( aRemovedCells.begin() );
771 [ # # ]: 0 : for( sal_Int32 nRow = 0; nRow < nRows; ++nRow )
772 : : {
773 [ # # ]: 0 : for( nOffset = 0; nOffset < nCount; ++nOffset )
774 [ # # ][ # # ]: 0 : (*aCellIter++) = getCell( nIndex + nOffset, nRow );
[ # # ]
775 : : }
776 : :
777 [ # # ][ # # ]: 0 : pModel->AddUndo( new RemoveColUndo( xThis, nIndex, aRemovedCols, aRemovedCells ) );
[ # # ]
778 : : }
779 : :
780 : : // only rows before and inside the removed rows are considered
781 : 0 : nColCount = nIndex + nCount + 1;
782 : :
783 : 0 : const sal_Int32 nRowCount = getRowCountImpl();
784 : :
785 : : // first check merged cells before and inside the removed rows
786 [ # # ]: 0 : for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
787 : : {
788 [ # # ]: 0 : for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
789 : : {
790 [ # # ]: 0 : CellRef xCell( getCell( nCol, nRow ) );
791 [ # # ][ # # ]: 0 : sal_Int32 nColSpan = (xCell.is() && !xCell->isMerged()) ? xCell->getColumnSpan() : 1;
[ # # ][ # # ]
792 [ # # ]: 0 : if( nColSpan <= 1 )
793 : 0 : continue;
794 : :
795 [ # # ]: 0 : if( nCol >= nIndex )
796 : : {
797 : : // current cell is inside the removed columns
798 [ # # ]: 0 : if( (nCol + nColSpan) > ( nIndex + nCount ) )
799 : : {
800 : : // current cells merges with columns after the removed columns
801 : 0 : const sal_Int32 nRemove = nCount - nCol + nIndex;
802 : :
803 [ # # ]: 0 : CellRef xTargetCell( getCell( nIndex + nCount, nRow ) );
804 [ # # ]: 0 : if( xTargetCell.is() )
805 : : {
806 [ # # ]: 0 : if( bUndo )
807 [ # # ]: 0 : xTargetCell->AddUndo();
808 [ # # ][ # # ]: 0 : xTargetCell->merge( nColSpan - nRemove, xCell->getRowSpan() );
809 [ # # ]: 0 : xTargetCell->replaceContentAndFormating( xCell );
810 : 0 : }
811 : : }
812 : : }
813 [ # # ]: 0 : else if( nColSpan > (nIndex - nCol) )
814 : : {
815 : : // current cells spans inside the removed columns, so adjust
816 [ # # ]: 0 : const sal_Int32 nRemove = ::std::min( nCount, nCol + nColSpan - nIndex );
817 [ # # ]: 0 : if( bUndo )
818 [ # # ]: 0 : xCell->AddUndo();
819 [ # # ][ # # ]: 0 : xCell->merge( nColSpan - nRemove, xCell->getRowSpan() );
820 : : }
821 [ # # ]: 0 : }
822 : : }
823 : :
824 : : // now remove the columns
825 [ # # ]: 0 : remove_range<ColumnVector,ColumnVector::iterator>( maColumns, nIndex, nCount );
826 [ # # ]: 0 : while( nRows-- )
827 [ # # ]: 0 : maRows[nRows]->removeColumns( nIndex, nCount );
828 : :
829 [ # # ]: 0 : if( bUndo )
830 [ # # ]: 0 : pModel->EndUndo();
831 : :
832 [ # # ]: 0 : if( pModel )
833 [ # # ][ # # ]: 0 : pModel->SetChanged();
[ # # ]
834 : : }
835 : 0 : catch( Exception& )
836 : : {
837 : : OSL_FAIL("sdr::table::TableModel::removeColumns(), exception caught!");
838 : : }
839 : :
840 : 0 : updateColumns();
841 : 0 : setModified(sal_True);
842 : : }
843 : 0 : }
844 : :
845 : : // -----------------------------------------------------------------------------
846 : :
847 : 24 : void TableModel::insertRows( sal_Int32 nIndex, sal_Int32 nCount )
848 : : {
849 [ + - ][ + - ]: 24 : if( nCount && mpTableObj )
850 : : {
851 : 24 : SdrModel* pModel = mpTableObj->GetModel();
852 [ + - ][ - + ]: 24 : const bool bUndo = pModel && mpTableObj->IsInserted() && pModel->IsUndoEnabled();
[ + - ]
853 : : try
854 : : {
855 [ + - ]: 24 : TableModelNotifyGuard aGuard( this );
856 : :
857 [ + - ]: 24 : nIndex = insert_range<RowVector,RowVector::iterator,TableRowRef>( maRows, nIndex, nCount );
858 : :
859 [ + - ]: 24 : RowVector aNewRows(nCount);
860 : 24 : const sal_Int32 nColCount = getColumnCountImpl();
861 [ + + ]: 48 : for( sal_Int32 nOffset = 0; nOffset < nCount; ++nOffset )
862 : : {
863 [ + - ]: 24 : TableRowRef xNewRow( new TableRow( this, nIndex+nOffset, nColCount ) );
864 : 24 : maRows[nIndex+nOffset] = xNewRow;
865 : 24 : aNewRows[nOffset] = xNewRow;
866 : 24 : }
867 : :
868 [ - + ]: 24 : if( bUndo )
869 : : {
870 [ # # ][ # # ]: 0 : pModel->BegUndo( ImpGetResStr(STR_TABLE_INSROW) );
[ # # ]
871 [ # # ][ # # ]: 0 : pModel->AddUndo( pModel->GetSdrUndoFactory().CreateUndoGeoObject(*mpTableObj) );
[ # # ]
872 : 0 : TableModelRef xThis( this );
873 [ # # ][ # # ]: 0 : pModel->AddUndo( new InsertRowUndo( xThis, nIndex, aNewRows ) );
[ # # ]
874 : : }
875 : :
876 : : // check if cells merge over new columns
877 [ + + ]: 132 : for( sal_Int32 nRow = 0; nRow < nIndex; ++nRow )
878 : : {
879 [ + + ]: 216 : for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
880 : : {
881 [ + - ]: 108 : CellRef xCell( getCell( nCol, nRow ) );
882 [ + - ][ + - ]: 108 : sal_Int32 nRowSpan = (xCell.is() && !xCell->isMerged()) ? xCell->getRowSpan() : 1;
[ + - ][ + - ]
883 [ - + ][ # # ]: 108 : if( (nRowSpan > 1) && ((nRowSpan + nRow) > nIndex) )
884 : : {
885 : : // cell merges over newly created columns, so add the new columns to the merged cell
886 [ # # ]: 0 : const sal_Int32 nColSpan = xCell->getColumnSpan();
887 : 0 : nRowSpan += nCount;
888 [ # # ]: 0 : merge( nCol, nRow, nColSpan, nRowSpan );
889 : : }
890 : 108 : }
891 [ + - ][ # # ]: 24 : }
892 : : }
893 : 0 : catch( Exception& )
894 : : {
895 : : OSL_FAIL("sdr::table::TableModel::insertRows(), exception caught!");
896 : : }
897 [ - + ]: 24 : if( bUndo )
898 : 0 : pModel->EndUndo();
899 : :
900 [ + - ]: 24 : if( pModel )
901 : 24 : pModel->SetChanged();
902 : :
903 : 24 : updateRows();
904 : 24 : setModified(sal_True);
905 : : }
906 : 24 : }
907 : :
908 : : // -----------------------------------------------------------------------------
909 : :
910 : 0 : void TableModel::removeRows( sal_Int32 nIndex, sal_Int32 nCount )
911 : : {
912 : 0 : sal_Int32 nRowCount = getRowCountImpl();
913 : :
914 [ # # ][ # # ]: 0 : if( mpTableObj && nCount && (nIndex >= 0) && (nIndex < nRowCount) )
[ # # ][ # # ]
915 : : {
916 : 0 : SdrModel* pModel = mpTableObj->GetModel();
917 [ # # ][ # # ]: 0 : const bool bUndo = pModel && mpTableObj->IsInserted()&& pModel->IsUndoEnabled();
[ # # ]
918 : :
919 : : try
920 : : {
921 [ # # ]: 0 : TableModelNotifyGuard aGuard( this );
922 : :
923 : : // clip removed rows to rows actually avalaible
924 [ # # ]: 0 : if( (nIndex + nCount) > nRowCount )
925 : 0 : nCount = nRowCount - nIndex;
926 : :
927 [ # # ]: 0 : if( bUndo )
928 : : {
929 [ # # ][ # # ]: 0 : pModel->BegUndo( ImpGetResStr(STR_UNDO_ROW_DELETE) );
[ # # ]
930 [ # # ][ # # ]: 0 : pModel->AddUndo( pModel->GetSdrUndoFactory().CreateUndoGeoObject(*mpTableObj) );
[ # # ]
931 : :
932 : 0 : TableModelRef xThis( this );
933 : :
934 [ # # ]: 0 : RowVector aRemovedRows( nCount );
935 [ # # ]: 0 : for( sal_Int32 nOffset = 0; nOffset < nCount; ++nOffset )
936 : 0 : aRemovedRows[nOffset] = maRows[nIndex+nOffset];
937 : :
938 [ # # ][ # # ]: 0 : pModel->AddUndo( new RemoveRowUndo( xThis, nIndex, aRemovedRows ) );
[ # # ]
939 : : }
940 : :
941 : : // only rows before and inside the removed rows are considered
942 : 0 : nRowCount = nIndex + nCount + 1;
943 : :
944 : 0 : const sal_Int32 nColCount = getColumnCountImpl();
945 : :
946 : : // first check merged cells before and inside the removed rows
947 [ # # ]: 0 : for( sal_Int32 nRow = 0; nRow < nRowCount; ++nRow )
948 : : {
949 [ # # ]: 0 : for( sal_Int32 nCol = 0; nCol < nColCount; ++nCol )
950 : : {
951 [ # # ]: 0 : CellRef xCell( getCell( nCol, nRow ) );
952 [ # # ][ # # ]: 0 : sal_Int32 nRowSpan = (xCell.is() && !xCell->isMerged()) ? xCell->getRowSpan() : 1;
[ # # ][ # # ]
953 [ # # ]: 0 : if( nRowSpan <= 1 )
954 : 0 : continue;
955 : :
956 [ # # ]: 0 : if( nRow >= nIndex )
957 : : {
958 : : // current cell is inside the removed rows
959 [ # # ]: 0 : if( (nRow + nRowSpan) > (nIndex + nCount) )
960 : : {
961 : : // current cells merges with rows after the removed rows
962 : 0 : const sal_Int32 nRemove = nCount - nRow + nIndex;
963 : :
964 [ # # ]: 0 : CellRef xTargetCell( getCell( nCol, nIndex + nCount ) );
965 [ # # ]: 0 : if( xTargetCell.is() )
966 : : {
967 [ # # ]: 0 : if( bUndo )
968 [ # # ]: 0 : xTargetCell->AddUndo();
969 [ # # ][ # # ]: 0 : xTargetCell->merge( xCell->getColumnSpan(), nRowSpan - nRemove );
970 [ # # ]: 0 : xTargetCell->replaceContentAndFormating( xCell );
971 : 0 : }
972 : : }
973 : : }
974 [ # # ]: 0 : else if( nRowSpan > (nIndex - nRow) )
975 : : {
976 : : // current cells spans inside the removed rows, so adjust
977 [ # # ]: 0 : const sal_Int32 nRemove = ::std::min( nCount, nRow + nRowSpan - nIndex );
978 [ # # ]: 0 : if( bUndo )
979 [ # # ]: 0 : xCell->AddUndo();
980 [ # # ][ # # ]: 0 : xCell->merge( xCell->getColumnSpan(), nRowSpan - nRemove );
981 : : }
982 [ # # ]: 0 : }
983 : : }
984 : :
985 : : // now remove the rows
986 [ # # ]: 0 : remove_range<RowVector,RowVector::iterator>( maRows, nIndex, nCount );
987 : :
988 [ # # ]: 0 : if( bUndo )
989 [ # # ]: 0 : pModel->EndUndo();
990 : :
991 [ # # ]: 0 : if( pModel )
992 [ # # ][ # # ]: 0 : pModel->SetChanged();
[ # # ]
993 : : }
994 : 0 : catch( Exception& )
995 : : {
996 : : OSL_FAIL("sdr::table::TableModel::removeRows(), exception caught!");
997 : : }
998 : :
999 : 0 : updateRows();
1000 : 0 : setModified(sal_True);
1001 : : }
1002 : 0 : }
1003 : :
1004 : : // -----------------------------------------------------------------------------
1005 : :
1006 : 210 : TableRowRef TableModel::getRow( sal_Int32 nRow ) const throw (IndexOutOfBoundsException)
1007 : : {
1008 [ + - ][ + - ]: 210 : if( (nRow >= 0) && (nRow < getRowCountImpl()) )
[ + - ]
1009 : 210 : return maRows[nRow];
1010 : :
1011 [ # # ]: 0 : throw IndexOutOfBoundsException();
1012 : : }
1013 : :
1014 : : // -----------------------------------------------------------------------------
1015 : :
1016 : 186 : TableColumnRef TableModel::getColumn( sal_Int32 nColumn ) const throw (IndexOutOfBoundsException)
1017 : : {
1018 [ + - ][ + - ]: 186 : if( (nColumn >= 0) && (nColumn < getColumnCountImpl()) )
[ + - ]
1019 : 186 : return maColumns[nColumn];
1020 : :
1021 [ # # ]: 0 : throw IndexOutOfBoundsException();
1022 : : }
1023 : :
1024 : : // -----------------------------------------------------------------------------
1025 : :
1026 : : /** deletes rows and columns that are completly merged. Must be called between BegUndo/EndUndo! */
1027 : 0 : void TableModel::optimize()
1028 : : {
1029 [ # # ]: 0 : TableModelNotifyGuard aGuard( this );
1030 : :
1031 : 0 : bool bWasModified = false;
1032 : :
1033 [ # # ][ # # ]: 0 : if( !maRows.empty() && !maColumns.empty() )
[ # # ]
1034 : : {
1035 : 0 : sal_Int32 nCol = getColumnCountImpl() - 1;
1036 [ # # ]: 0 : while( nCol > 0 )
1037 : : {
1038 : 0 : bool bEmpty = true;
1039 [ # # ][ # # ]: 0 : for( sal_Int32 nRow = 0; (nRow < getRowCountImpl()) && bEmpty; nRow++ )
[ # # ]
1040 : : {
1041 [ # # ][ # # ]: 0 : Reference< XMergeableCell > xCell( getCellByPosition( nCol, nRow ), UNO_QUERY );
1042 [ # # ][ # # ]: 0 : if( xCell.is() && !xCell->isMerged() )
[ # # ][ # # ]
[ # # ]
1043 : 0 : bEmpty = false;
1044 : 0 : }
1045 : :
1046 [ # # ]: 0 : if( bEmpty )
1047 : : {
1048 [ # # ]: 0 : if( nCol > 0 ) try
1049 : : {
1050 [ # # ]: 0 : const OUString sWidth( RTL_CONSTASCII_USTRINGPARAM("Width") );
1051 : 0 : sal_Int32 nWidth1 = 0, nWidth2 = 0;
1052 [ # # ][ # # ]: 0 : Reference< XPropertySet > xSet1( static_cast< XCellRange* >( maColumns[nCol].get() ), UNO_QUERY_THROW );
1053 [ # # ][ # # ]: 0 : Reference< XPropertySet > xSet2( static_cast< XCellRange* >( maColumns[nCol-1].get() ), UNO_QUERY_THROW );
1054 [ # # ][ # # ]: 0 : xSet1->getPropertyValue( sWidth ) >>= nWidth1;
1055 [ # # ][ # # ]: 0 : xSet2->getPropertyValue( sWidth ) >>= nWidth2;
1056 : 0 : nWidth1 += nWidth2;
1057 [ # # ][ # # ]: 0 : xSet2->setPropertyValue( sWidth, Any( nWidth1 ) );
[ # # ][ # # ]
1058 : : }
1059 [ # # ]: 0 : catch( Exception& e )
1060 : : {
1061 : : (void)e;
1062 : : OSL_FAIL("svx::TableModel::optimize(), exception caught!");
1063 : : }
1064 : :
1065 [ # # ]: 0 : removeColumns( nCol, 1 );
1066 : 0 : bWasModified = true;
1067 : : }
1068 : :
1069 : 0 : nCol--;
1070 : : }
1071 : :
1072 : 0 : sal_Int32 nRow = getRowCountImpl() - 1;
1073 [ # # ]: 0 : while( nRow > 0 )
1074 : : {
1075 : 0 : bool bEmpty = true;
1076 [ # # ][ # # ]: 0 : for( nCol = 0; (nCol < getColumnCountImpl()) && bEmpty; nCol++ )
[ # # ]
1077 : : {
1078 [ # # ][ # # ]: 0 : Reference< XMergeableCell > xCell( getCellByPosition( nCol, nRow ), UNO_QUERY );
1079 [ # # ][ # # ]: 0 : if( xCell.is() && !xCell->isMerged() )
[ # # ][ # # ]
[ # # ]
1080 : 0 : bEmpty = false;
1081 : 0 : }
1082 : :
1083 [ # # ]: 0 : if( bEmpty )
1084 : : {
1085 [ # # ]: 0 : if( nRow > 0 ) try
1086 : : {
1087 [ # # ]: 0 : const OUString sHeight( RTL_CONSTASCII_USTRINGPARAM("Height") );
1088 : 0 : sal_Int32 nHeight1 = 0, nHeight2 = 0;
1089 [ # # ][ # # ]: 0 : Reference< XPropertySet > xSet1( static_cast< XCellRange* >( maRows[nRow].get() ), UNO_QUERY_THROW );
1090 [ # # ][ # # ]: 0 : Reference< XPropertySet > xSet2( static_cast< XCellRange* >( maRows[nRow-1].get() ), UNO_QUERY_THROW );
1091 [ # # ][ # # ]: 0 : xSet1->getPropertyValue( sHeight ) >>= nHeight1;
1092 [ # # ][ # # ]: 0 : xSet2->getPropertyValue( sHeight ) >>= nHeight2;
1093 : 0 : nHeight1 += nHeight2;
1094 [ # # ][ # # ]: 0 : xSet2->setPropertyValue( sHeight, Any( nHeight1 ) );
[ # # ][ # # ]
1095 : : }
1096 [ # # ]: 0 : catch( Exception& e )
1097 : : {
1098 : : (void)e;
1099 : : OSL_FAIL("svx::TableModel::optimize(), exception caught!");
1100 : : }
1101 : :
1102 [ # # ]: 0 : removeRows( nRow, 1 );
1103 : 0 : bWasModified = true;
1104 : : }
1105 : :
1106 : 0 : nRow--;
1107 : : }
1108 : : }
1109 [ # # ]: 0 : if( bWasModified )
1110 [ # # ][ # # ]: 0 : setModified(sal_True);
1111 : 0 : }
1112 : :
1113 : : // -----------------------------------------------------------------------------
1114 : :
1115 : 0 : void TableModel::merge( sal_Int32 nCol, sal_Int32 nRow, sal_Int32 nColSpan, sal_Int32 nRowSpan )
1116 : : {
1117 [ # # ]: 0 : SdrModel* pModel = mpTableObj->GetModel();
1118 : :
1119 [ # # ][ # # ]: 0 : const bool bUndo = pModel && mpTableObj->IsInserted() && pModel->IsUndoEnabled();
[ # # ][ # # ]
[ # # ]
1120 : :
1121 : 0 : const sal_Int32 nLastRow = nRow + nRowSpan;
1122 : 0 : const sal_Int32 nLastCol = nCol + nColSpan;
1123 : :
1124 [ # # ][ # # ]: 0 : if( (nLastRow > getRowCount()) || (nLastCol > getRowCount() ) )
[ # # ][ # # ]
1125 : : {
1126 : : OSL_FAIL("TableModel::merge(), merge beyound the table!");
1127 : : }
1128 : :
1129 : : // merge first cell
1130 [ # # ][ # # ]: 0 : CellRef xOriginCell( dynamic_cast< Cell* >( getCellByPosition( nCol, nRow ).get() ) );
[ # # ]
1131 [ # # ]: 0 : if( xOriginCell.is() )
1132 : : {
1133 [ # # ]: 0 : if( bUndo )
1134 [ # # ]: 0 : xOriginCell->AddUndo();
1135 [ # # ]: 0 : xOriginCell->merge( nColSpan, nRowSpan );
1136 : : }
1137 : :
1138 : 0 : sal_Int32 nTempCol = nCol + 1;
1139 : :
1140 : : // merge remaining cells
1141 [ # # ]: 0 : for( ; nRow < nLastRow; nRow++ )
1142 : : {
1143 [ # # ]: 0 : for( ; nTempCol < nLastCol; nTempCol++ )
1144 : : {
1145 [ # # ][ # # ]: 0 : CellRef xCell( dynamic_cast< Cell* >( getCellByPosition( nTempCol, nRow ).get() ) );
[ # # ]
1146 [ # # ][ # # ]: 0 : if( xCell.is() && !xCell->isMerged() )
[ # # ][ # # ]
1147 : : {
1148 [ # # ]: 0 : if( bUndo )
1149 [ # # ]: 0 : xCell->AddUndo();
1150 [ # # ]: 0 : xCell->setMerged();
1151 [ # # ]: 0 : xOriginCell->mergeContent( xCell );
1152 : : }
1153 : 0 : }
1154 : 0 : nTempCol = nCol;
1155 : 0 : }
1156 : 0 : }
1157 : :
1158 : :
1159 : : // -----------------------------------------------------------------------------
1160 : :
1161 : 24 : void TableModel::updateRows()
1162 : : {
1163 : 24 : sal_Int32 nRow = 0;
1164 : 24 : RowVector::iterator iter = maRows.begin();
1165 [ + - ][ + + ]: 156 : while( iter != maRows.end() )
1166 : : {
1167 [ + - ]: 132 : (*iter++)->mnRow = nRow++;
1168 : : }
1169 : 24 : }
1170 : :
1171 : : // -----------------------------------------------------------------------------
1172 : :
1173 : 3 : void TableModel::updateColumns()
1174 : : {
1175 : 3 : sal_Int32 nColumn = 0;
1176 : 3 : ColumnVector::iterator iter = maColumns.begin();
1177 [ + - ][ + + ]: 24 : while( iter != maColumns.end() )
1178 : : {
1179 [ + - ]: 21 : (*iter++)->mnColumn = nColumn++;
1180 : : }
1181 : 3 : }
1182 : :
1183 : : // -----------------------------------------------------------------------------
1184 : :
1185 : : } }
1186 : :
1187 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|