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 "svx/svdotable.hxx"
31 : : #include "cellcursor.hxx"
32 : : #include "tablelayouter.hxx"
33 : : #include "cell.hxx"
34 : : #include "svx/svdmodel.hxx"
35 : : #include "svx/svdstr.hrc"
36 : : #include "svx/svdglob.hxx"
37 : :
38 : : // -----------------------------------------------------------------------------
39 : :
40 : : using ::rtl::OUString;
41 : : using namespace ::com::sun::star::uno;
42 : : using namespace ::com::sun::star::lang;
43 : : using namespace ::com::sun::star::container;
44 : : using namespace ::com::sun::star::beans;
45 : : using namespace ::com::sun::star::table;
46 : :
47 : : // -----------------------------------------------------------------------------
48 : :
49 : : namespace sdr { namespace table {
50 : :
51 : : // -----------------------------------------------------------------------------
52 : : // CellCursor
53 : : // -----------------------------------------------------------------------------
54 : :
55 : 0 : CellCursor::CellCursor( const TableModelRef & xTable, sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom )
56 : 0 : : CellCursorBase( xTable, nLeft, nTop, nRight, nBottom )
57 : : {
58 : 0 : }
59 : :
60 : : // -----------------------------------------------------------------------------
61 : :
62 : 0 : CellCursor::~CellCursor()
63 : : {
64 [ # # ]: 0 : }
65 : :
66 : : // -----------------------------------------------------------------------------
67 : : // XCellCursor
68 : : // -----------------------------------------------------------------------------
69 : :
70 : 0 : Reference< XCell > SAL_CALL CellCursor::getCellByPosition( sal_Int32 nColumn, sal_Int32 nRow ) throw (IndexOutOfBoundsException, RuntimeException)
71 : : {
72 : 0 : return CellRange::getCellByPosition( nColumn, nRow );
73 : : }
74 : :
75 : : // -----------------------------------------------------------------------------
76 : :
77 : 0 : Reference< XCellRange > SAL_CALL CellCursor::getCellRangeByPosition( sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom ) throw (IndexOutOfBoundsException, RuntimeException)
78 : : {
79 : 0 : return CellRange::getCellRangeByPosition( nLeft, nTop, nRight, nBottom );
80 : : }
81 : :
82 : : // -----------------------------------------------------------------------------
83 : :
84 : 0 : Reference< XCellRange > SAL_CALL CellCursor::getCellRangeByName( const OUString& aRange ) throw (RuntimeException)
85 : : {
86 : 0 : return CellRange::getCellRangeByName( aRange );
87 : : }
88 : :
89 : : // -----------------------------------------------------------------------------
90 : : // XCellCursor
91 : : // -----------------------------------------------------------------------------
92 : :
93 : 0 : void SAL_CALL CellCursor::gotoStart( ) throw (RuntimeException)
94 : : {
95 : 0 : mnRight = mnLeft;
96 : 0 : mnBottom = mnTop;
97 : 0 : }
98 : :
99 : : // -----------------------------------------------------------------------------
100 : :
101 : 0 : void SAL_CALL CellCursor::gotoEnd( ) throw (RuntimeException)
102 : : {
103 : 0 : mnLeft = mnRight;
104 : 0 : mnTop = mnBottom;
105 : 0 : }
106 : :
107 : : // -----------------------------------------------------------------------------
108 : :
109 : 0 : void SAL_CALL CellCursor::gotoNext( ) throw (RuntimeException)
110 : : {
111 [ # # ]: 0 : if( mxTable.is() )
112 : : {
113 : 0 : mnRight++;
114 [ # # ]: 0 : if( mnRight >= mxTable->getColumnCount() )
115 : : {
116 : : // if we past the last column, try skip to the row line
117 : 0 : mnTop++;
118 [ # # ]: 0 : if( mnTop >= mxTable->getRowCount() )
119 : : {
120 : : // if we past the last row, do not move cursor at all
121 : 0 : mnTop--;
122 : 0 : mnRight--;
123 : : }
124 : : else
125 : : {
126 : : // restart at the first column on the next row
127 : 0 : mnRight = 0;
128 : : }
129 : : }
130 : : }
131 : :
132 : 0 : mnLeft = mnRight;
133 : 0 : mnTop = mnBottom;
134 : 0 : }
135 : :
136 : : // -----------------------------------------------------------------------------
137 : :
138 : 0 : void SAL_CALL CellCursor::gotoPrevious( ) throw (RuntimeException)
139 : : {
140 [ # # ]: 0 : if( mxTable.is() )
141 : : {
142 [ # # ]: 0 : if( mnLeft > 0 )
143 : : {
144 : 0 : --mnLeft;
145 : : }
146 [ # # ]: 0 : else if( mnTop > 0 )
147 : : {
148 : 0 : --mnTop;
149 : 0 : mnLeft = mxTable->getColumnCount() - 1;
150 : : }
151 : : }
152 : :
153 : 0 : mnRight = mnLeft;
154 : 0 : mnBottom = mnTop;
155 : 0 : }
156 : :
157 : : // -----------------------------------------------------------------------------
158 : :
159 : 0 : void SAL_CALL CellCursor::gotoOffset( ::sal_Int32 nColumnOffset, ::sal_Int32 nRowOffset ) throw (RuntimeException)
160 : : {
161 [ # # ]: 0 : if( mxTable.is() )
162 : : {
163 : 0 : const sal_Int32 nLeft = mnLeft + nColumnOffset;
164 [ # # ][ # # ]: 0 : if( (nLeft >= 0) && (nLeft < mxTable->getColumnCount() ) )
[ # # ]
165 : 0 : mnRight = mnLeft = nLeft;
166 : :
167 : 0 : const sal_Int32 nTop = mnTop + nRowOffset;
168 [ # # ][ # # ]: 0 : if( (nTop >= 0) && (nTop < mxTable->getRowCount()) )
[ # # ]
169 : 0 : mnTop = mnBottom = nTop;
170 : : }
171 : 0 : }
172 : :
173 : : // -----------------------------------------------------------------------------
174 : : // XMergeableCellCursor
175 : : // -----------------------------------------------------------------------------
176 : :
177 : : /** returns true and the merged cell positions if a merge is valid or false if a merge is
178 : : not valid for that range */
179 : 0 : bool CellCursor::GetMergedSelection( CellPos& rStart, CellPos& rEnd )
180 : : {
181 : 0 : rStart.mnCol = mnLeft; rStart.mnRow = mnTop;
182 : 0 : rEnd.mnCol = mnRight; rEnd.mnRow = mnBottom;
183 : :
184 : : // single cell merge is never valid
185 [ # # ][ # # ]: 0 : if( mxTable.is() && ((mnLeft != mnRight) || (mnTop != mnBottom)) ) try
[ # # ][ # # ]
186 : : {
187 [ # # ][ # # ]: 0 : CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( mnLeft, mnTop ).get() ) );
[ # # ]
188 : :
189 : : // check if first cell is merged
190 [ # # ][ # # ]: 0 : if( xCell.is() && xCell->isMerged() )
[ # # ][ # # ]
191 [ # # ]: 0 : findMergeOrigin( mxTable, mnLeft, mnTop, rStart.mnCol, rStart.mnRow );
192 : :
193 : : // check if last cell is merged
194 [ # # ][ # # ]: 0 : xCell.set( dynamic_cast< Cell* >( mxTable->getCellByPosition( mnRight, mnBottom ).get() ) );
[ # # ]
195 [ # # ]: 0 : if( xCell.is() )
196 : : {
197 [ # # ][ # # ]: 0 : if( xCell->isMerged() )
198 : : {
199 [ # # ]: 0 : findMergeOrigin( mxTable, mnRight, mnBottom, rEnd.mnCol, rEnd.mnRow );
200 : : // merge not possible if selection is only one cell and all its merges
201 [ # # ]: 0 : if( rEnd == rStart )
202 : 0 : return false;
203 [ # # ][ # # ]: 0 : xCell.set( dynamic_cast< Cell* >( mxTable->getCellByPosition( rEnd.mnCol, rEnd.mnRow ).get() ) );
[ # # ]
204 : : }
205 : : }
206 [ # # ]: 0 : if( xCell.is() )
207 : : {
208 [ # # ]: 0 : rEnd.mnCol += xCell->getColumnSpan()-1;
209 [ # # ]: 0 : rEnd.mnRow += xCell->getRowSpan()-1;
210 : : }
211 : :
212 : : // now check if everything is inside the given bounds
213 : : sal_Int32 nRow, nCol;
214 [ # # ]: 0 : for( nRow = rStart.mnRow; nRow <= rEnd.mnRow; nRow++ )
215 : : {
216 [ # # ]: 0 : for( nCol = rStart.mnCol; nCol <= rEnd.mnCol; nCol++ )
217 : : {
218 [ # # ][ # # ]: 0 : xCell.set( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
[ # # ]
219 [ # # ]: 0 : if( !xCell.is() )
220 : 0 : continue;
221 : :
222 [ # # ][ # # ]: 0 : if( xCell->isMerged() )
223 : : {
224 : : sal_Int32 nOriginCol, nOriginRow;
225 [ # # ][ # # ]: 0 : if( findMergeOrigin( mxTable, nCol, nRow, nOriginCol, nOriginRow ) )
226 : : {
227 [ # # ][ # # ]: 0 : if( (nOriginCol < rStart.mnCol) || (nOriginRow < rStart.mnRow) )
228 : 0 : return false;
229 : :
230 [ # # ][ # # ]: 0 : xCell.set( dynamic_cast< Cell* >( mxTable->getCellByPosition( nOriginCol, nOriginRow ).get() ) );
[ # # ]
231 [ # # ]: 0 : if( xCell.is() )
232 : : {
233 [ # # ]: 0 : nOriginCol += xCell->getColumnSpan()-1;
234 [ # # ]: 0 : nOriginRow += xCell->getRowSpan()-1;
235 : :
236 [ # # ][ # # ]: 0 : if( (nOriginCol > rEnd.mnCol) || (nOriginRow > rEnd.mnRow) )
237 : 0 : return false;
238 : : }
239 : : }
240 : : }
241 [ # # ][ # # ]: 0 : else if( ((nCol + xCell->getColumnSpan() - 1) > rEnd.mnCol) || ((nRow + xCell->getRowSpan() - 1 ) > rEnd.mnRow) )
[ # # ][ # # ]
[ # # ]
242 : : {
243 : 0 : return false;
244 : : }
245 : : }
246 : : }
247 [ # # ]: 0 : return true;
248 : : }
249 : 0 : catch( Exception& )
250 : : {
251 : : OSL_FAIL("sdr::table::SvmxTableController::GetMergedSelection(), exception caught!");
252 : : }
253 : 0 : return false;
254 : : }
255 : :
256 : : // -----------------------------------------------------------------------------
257 : :
258 : 0 : void SAL_CALL CellCursor::merge( ) throw (NoSupportException, RuntimeException)
259 : : {
260 : 0 : CellPos aStart, aEnd;
261 [ # # ][ # # ]: 0 : if( !GetMergedSelection( aStart, aEnd ) )
262 [ # # ]: 0 : throw NoSupportException();
263 : :
264 [ # # ][ # # ]: 0 : if( !mxTable.is() || (mxTable->getSdrTableObj() == 0) )
[ # # ]
265 [ # # ]: 0 : throw DisposedException();
266 : :
267 [ # # ]: 0 : SdrModel* pModel = mxTable->getSdrTableObj()->GetModel();
268 [ # # ][ # # ]: 0 : const bool bUndo = pModel && mxTable->getSdrTableObj()->IsInserted() && pModel->IsUndoEnabled();
[ # # ][ # # ]
[ # # ]
269 : :
270 [ # # ]: 0 : if( bUndo )
271 [ # # ][ # # ]: 0 : pModel->BegUndo( ImpGetResStr(STR_TABLE_MERGE) );
[ # # ][ # # ]
272 : :
273 : : try
274 : : {
275 [ # # ]: 0 : mxTable->merge( aStart.mnCol, aStart.mnRow, aEnd.mnCol - aStart.mnCol + 1, aEnd.mnRow - aStart.mnRow + 1 );
276 [ # # ]: 0 : mxTable->optimize();
277 [ # # ]: 0 : mxTable->setModified(sal_True);
278 : : }
279 [ # # ]: 0 : catch( Exception& )
280 : : {
281 : : OSL_FAIL("sdr::table::CellCursor::merge(), exception caught!");
282 : : }
283 : :
284 [ # # ]: 0 : if( bUndo )
285 [ # # ]: 0 : pModel->EndUndo();
286 : :
287 [ # # ]: 0 : if( pModel )
288 [ # # ]: 0 : pModel->SetChanged();
289 : 0 : }
290 : :
291 : : // -----------------------------------------------------------------------------
292 : :
293 : 0 : void CellCursor::split_column( sal_Int32 nCol, sal_Int32 nColumns, std::vector< sal_Int32 >& rLeftOvers )
294 : : {
295 [ # # ]: 0 : const sal_Int32 nRowCount = mxTable->getRowCount();
296 : :
297 : 0 : sal_Int32 nNewCols = 0, nRow;
298 : :
299 : : // first check how many columns we need to add
300 [ # # ]: 0 : for( nRow = mnTop; nRow <= mnBottom; ++nRow )
301 : : {
302 [ # # ][ # # ]: 0 : CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
[ # # ]
303 [ # # ][ # # ]: 0 : if( xCell.is() && !xCell->isMerged() )
[ # # ][ # # ]
304 [ # # ][ # # ]: 0 : nNewCols = std::max( nNewCols, nColumns - xCell->getColumnSpan() + 1 - rLeftOvers[nRow] );
[ # # ]
305 : 0 : }
306 : :
307 [ # # ]: 0 : if( nNewCols > 0 )
308 : : {
309 [ # # ]: 0 : const OUString sWidth( RTL_CONSTASCII_USTRINGPARAM("Width") );
310 [ # # ][ # # ]: 0 : Reference< XTableColumns > xCols( mxTable->getColumns(), UNO_QUERY_THROW );
311 [ # # ][ # # ]: 0 : Reference< XPropertySet > xRefColumn( xCols->getByIndex( nCol ), UNO_QUERY_THROW );
[ # # ]
312 : 0 : sal_Int32 nWidth = 0;
313 [ # # ][ # # ]: 0 : xRefColumn->getPropertyValue( sWidth ) >>= nWidth;
314 : 0 : const sal_Int32 nNewWidth = nWidth / (nNewCols + 1);
315 : :
316 : : // reference column gets new width + rounding errors
317 [ # # ][ # # ]: 0 : xRefColumn->setPropertyValue( sWidth, Any( nWidth - (nNewWidth * nNewCols) ) );
[ # # ]
318 : :
319 [ # # ][ # # ]: 0 : xCols->insertByIndex( nCol + 1, nNewCols );
320 : 0 : mnRight += nNewCols;
321 : :
322 : : // distribute new width
323 [ # # ]: 0 : for( sal_Int32 nNewCol = nCol + nNewCols; nNewCol > nCol; --nNewCol )
324 : : {
325 [ # # ][ # # ]: 0 : Reference< XPropertySet > xNewCol( xCols->getByIndex( nNewCol ), UNO_QUERY_THROW );
[ # # ]
326 [ # # ][ # # ]: 0 : xNewCol->setPropertyValue( sWidth, Any( nNewWidth ) );
[ # # ]
327 : 0 : }
328 : : }
329 : :
330 [ # # ]: 0 : for( nRow = 0; nRow < nRowCount; ++nRow )
331 : : {
332 [ # # ][ # # ]: 0 : CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
[ # # ]
333 [ # # ][ # # ]: 0 : if( !xCell.is() || xCell->isMerged() )
[ # # ][ # # ]
334 : : {
335 [ # # ]: 0 : if( nNewCols > 0 )
336 : : {
337 : : // merged cells are ignored, but newly added columns will be added to leftovers
338 [ # # ][ # # ]: 0 : xCell.set( dynamic_cast< Cell* >(mxTable->getCellByPosition( nCol+1, nRow ).get() ) );
[ # # ]
339 [ # # ][ # # ]: 0 : if( !xCell.is() || !xCell->isMerged() )
[ # # ][ # # ]
340 [ # # ]: 0 : rLeftOvers[nRow] += nNewCols;
341 : : }
342 : : }
343 : : else
344 : : {
345 [ # # ]: 0 : sal_Int32 nRowSpan = xCell->getRowSpan() - 1;
346 [ # # ]: 0 : sal_Int32 nColSpan = xCell->getColumnSpan() - 1;
347 : :
348 [ # # ][ # # ]: 0 : if( (nRow >= mnTop) && (nRow <= mnBottom) )
349 : : {
350 [ # # ]: 0 : sal_Int32 nCellsAvailable = 1 + nColSpan + rLeftOvers[nRow];
351 [ # # ]: 0 : if( nColSpan == 0 )
352 : 0 : nCellsAvailable += nNewCols;
353 : :
354 : : DBG_ASSERT( nCellsAvailable > nColumns, "sdr::table::CellCursor::split_column(), somethings wrong" );
355 : :
356 : 0 : sal_Int32 nSplitSpan = (nCellsAvailable / (nColumns + 1)) - 1;
357 : :
358 : 0 : sal_Int32 nSplitCol = nCol;
359 : 0 : sal_Int32 nSplits = nColumns + 1;
360 [ # # ]: 0 : while( nSplits-- )
361 : : {
362 : : // last split eats rounding cells
363 [ # # ]: 0 : if( nSplits == 0 )
364 : 0 : nSplitSpan = nCellsAvailable - ((nSplitSpan+1) * nColumns) - 1;
365 : :
366 [ # # ]: 0 : mxTable->merge( nSplitCol, nRow, nSplitSpan + 1, nRowSpan + 1);
367 [ # # ]: 0 : if( nSplits > 0 )
368 : 0 : nSplitCol += nSplitSpan + 1;
369 : : }
370 : :
371 [ # # ]: 0 : do
372 : : {
373 [ # # ]: 0 : rLeftOvers[nRow++] = 0;
374 : : }
375 : : while( nRowSpan-- );
376 : 0 : --nRow;
377 : : }
378 : : else
379 : : {
380 : : // cope with outside cells, merge if needed
381 [ # # ][ # # ]: 0 : if( nColSpan < (rLeftOvers[nRow] + nNewCols) )
382 [ # # ][ # # ]: 0 : mxTable->merge( nCol, nRow, (rLeftOvers[nRow] + nNewCols) + 1, nRowSpan + 1 );
383 : :
384 [ # # ]: 0 : do
385 : : {
386 [ # # ]: 0 : rLeftOvers[nRow++] = 0; // consumed
387 : : }
388 : : while( nRowSpan-- );
389 : 0 : --nRow;
390 : : }
391 : : }
392 : 0 : }
393 : 0 : }
394 : :
395 : : // -----------------------------------------------------------------------------
396 : :
397 : 0 : void CellCursor::split_horizontal( sal_Int32 nColumns )
398 : : {
399 [ # # ]: 0 : const sal_Int32 nRowCount = mxTable->getRowCount();
400 : :
401 [ # # ]: 0 : std::vector< sal_Int32 > aLeftOvers( nRowCount );
402 : :
403 [ # # ]: 0 : for( sal_Int32 nCol = mnRight; nCol >= mnLeft; --nCol )
404 [ # # ]: 0 : split_column( nCol, nColumns, aLeftOvers );
405 : 0 : }
406 : :
407 : : // -----------------------------------------------------------------------------
408 : :
409 : 0 : void CellCursor::split_row( sal_Int32 nRow, sal_Int32 nRows, std::vector< sal_Int32 >& rLeftOvers )
410 : : {
411 [ # # ]: 0 : const sal_Int32 nColCount = mxTable->getColumnCount();
412 : :
413 : 0 : sal_Int32 nNewRows = 0, nCol;
414 : :
415 : : // first check how many columns we need to add
416 [ # # ]: 0 : for( nCol = mnLeft; nCol <= mnRight; ++nCol )
417 : : {
418 [ # # ][ # # ]: 0 : CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
[ # # ]
419 [ # # ][ # # ]: 0 : if( xCell.is() && !xCell->isMerged() )
[ # # ][ # # ]
420 [ # # ][ # # ]: 0 : nNewRows = std::max( nNewRows, nRows - xCell->getRowSpan() + 1 - rLeftOvers[nCol] );
[ # # ]
421 : 0 : }
422 : :
423 [ # # ]: 0 : if( nNewRows > 0 )
424 : : {
425 [ # # ]: 0 : const OUString sHeight( RTL_CONSTASCII_USTRINGPARAM("Height") );
426 [ # # ][ # # ]: 0 : Reference< XTableRows > xRows( mxTable->getRows(), UNO_QUERY_THROW );
427 [ # # ][ # # ]: 0 : Reference< XPropertySet > xRefRow( xRows->getByIndex( nRow ), UNO_QUERY_THROW );
[ # # ]
428 : 0 : sal_Int32 nHeight = 0;
429 [ # # ][ # # ]: 0 : xRefRow->getPropertyValue( sHeight ) >>= nHeight;
430 : 0 : const sal_Int32 nNewHeight = nHeight / (nNewRows + 1);
431 : :
432 : : // reference row gets new height + rounding errors
433 [ # # ][ # # ]: 0 : xRefRow->setPropertyValue( sHeight, Any( nHeight - (nNewHeight * nNewRows) ) );
[ # # ]
434 : :
435 [ # # ][ # # ]: 0 : xRows->insertByIndex( nRow + 1, nNewRows );
436 : 0 : mnBottom += nNewRows;
437 : :
438 : : // distribute new width
439 [ # # ]: 0 : for( sal_Int32 nNewRow = nRow + nNewRows; nNewRow > nRow; --nNewRow )
440 : : {
441 [ # # ][ # # ]: 0 : Reference< XPropertySet > xNewRow( xRows->getByIndex( nNewRow ), UNO_QUERY_THROW );
[ # # ]
442 [ # # ][ # # ]: 0 : xNewRow->setPropertyValue( sHeight, Any( nNewHeight ) );
[ # # ]
443 : 0 : }
444 : : }
445 : :
446 [ # # ]: 0 : for( nCol = 0; nCol < nColCount; ++nCol )
447 : : {
448 [ # # ][ # # ]: 0 : CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
[ # # ]
449 [ # # ][ # # ]: 0 : if( !xCell.is() || xCell->isMerged() )
[ # # ][ # # ]
450 : : {
451 [ # # ]: 0 : if( nNewRows )
452 : : {
453 : : // merged cells are ignored, but newly added columns will be added to leftovers
454 [ # # ][ # # ]: 0 : xCell.set( dynamic_cast< Cell* >(mxTable->getCellByPosition( nCol, nRow+1 ).get() ) );
[ # # ]
455 [ # # ][ # # ]: 0 : if( !xCell.is() || !xCell->isMerged() )
[ # # ][ # # ]
456 [ # # ]: 0 : rLeftOvers[nCol] += nNewRows;
457 : : }
458 : : }
459 : : else
460 : : {
461 [ # # ]: 0 : sal_Int32 nRowSpan = xCell->getRowSpan() - 1;
462 [ # # ]: 0 : sal_Int32 nColSpan = xCell->getColumnSpan() - 1;
463 : :
464 [ # # ][ # # ]: 0 : if( (nCol >= mnLeft) && (nCol <= mnRight) )
465 : : {
466 [ # # ]: 0 : sal_Int32 nCellsAvailable = 1 + nRowSpan + rLeftOvers[nCol];
467 [ # # ]: 0 : if( nRowSpan == 0 )
468 : 0 : nCellsAvailable += nNewRows;
469 : :
470 : : DBG_ASSERT( nCellsAvailable > nRows, "sdr::table::CellCursor::split_row(), somethings wrong" );
471 : :
472 : 0 : sal_Int32 nSplitSpan = (nCellsAvailable / (nRows + 1)) - 1;
473 : :
474 : 0 : sal_Int32 nSplitRow = nRow;
475 : 0 : sal_Int32 nSplits = nRows + 1;
476 [ # # ]: 0 : while( nSplits-- )
477 : : {
478 : : // last split eats rounding cells
479 [ # # ]: 0 : if( nSplits == 0 )
480 : 0 : nSplitSpan = nCellsAvailable - ((nSplitSpan+1) * nRows) - 1;
481 : :
482 [ # # ]: 0 : mxTable->merge( nCol, nSplitRow, nColSpan + 1, nSplitSpan + 1 );
483 [ # # ]: 0 : if( nSplits > 0 )
484 : 0 : nSplitRow += nSplitSpan + 1;
485 : : }
486 : :
487 [ # # ]: 0 : do
488 : : {
489 [ # # ]: 0 : rLeftOvers[nCol++] = 0;
490 : : }
491 : : while( nColSpan-- );
492 : 0 : --nCol;
493 : : }
494 : : else
495 : : {
496 : : // cope with outside cells, merge if needed
497 [ # # ][ # # ]: 0 : if( nRowSpan < (rLeftOvers[nCol] + nNewRows) )
498 [ # # ][ # # ]: 0 : mxTable->merge( nCol, nRow, nColSpan + 1, (rLeftOvers[nCol] + nNewRows) + 1 );
499 : :
500 [ # # ]: 0 : do
501 : : {
502 [ # # ]: 0 : rLeftOvers[nCol++] = 0; // consumed
503 : : }
504 : : while( nColSpan-- );
505 : 0 : --nCol;
506 : : }
507 : : }
508 : 0 : }
509 : 0 : }
510 : :
511 : : // -----------------------------------------------------------------------------
512 : :
513 : 0 : void CellCursor::split_vertical( sal_Int32 nRows )
514 : : {
515 [ # # ]: 0 : const sal_Int32 nColCount = mxTable->getColumnCount();
516 : :
517 [ # # ]: 0 : std::vector< sal_Int32 > aLeftOvers( nColCount );
518 : :
519 [ # # ]: 0 : for( sal_Int32 nRow = mnBottom; nRow >= mnTop; --nRow )
520 [ # # ]: 0 : split_row( nRow, nRows, aLeftOvers );
521 : 0 : }
522 : :
523 : : // -----------------------------------------------------------------------------
524 : :
525 : 0 : void SAL_CALL CellCursor::split( sal_Int32 nColumns, sal_Int32 nRows ) throw (NoSupportException, IllegalArgumentException, RuntimeException)
526 : : {
527 [ # # ][ # # ]: 0 : if( (nColumns < 0) || (nRows < 0) )
528 [ # # ]: 0 : throw IllegalArgumentException();
529 : :
530 [ # # ][ # # ]: 0 : if( !mxTable.is() || (mxTable->getSdrTableObj() == 0) )
[ # # ]
531 [ # # ]: 0 : throw DisposedException();
532 : :
533 : 0 : SdrModel* pModel = mxTable->getSdrTableObj()->GetModel();
534 [ # # ][ # # ]: 0 : const bool bUndo = pModel && mxTable->getSdrTableObj()->IsInserted() && pModel->IsUndoEnabled();
[ # # ]
535 [ # # ]: 0 : if( bUndo )
536 [ # # ]: 0 : pModel->BegUndo( ImpGetResStr(STR_TABLE_SPLIT) );
537 : :
538 : : try
539 : : {
540 [ # # ]: 0 : if( nColumns > 0 )
541 [ # # ]: 0 : split_horizontal( nColumns );
542 : :
543 [ # # ]: 0 : if( nRows > 0 )
544 [ # # ]: 0 : split_vertical( nRows );
545 : :
546 [ # # ][ # # ]: 0 : if( nColumns > 0 ||nRows > 0 )
547 [ # # ]: 0 : mxTable->setModified(sal_True);
548 : : }
549 [ # # ]: 0 : catch( Exception& )
550 : : {
551 : : OSL_FAIL("sdr::table::CellCursor::split(), exception caught!");
552 [ # # ]: 0 : throw NoSupportException();
553 : : }
554 : :
555 [ # # ]: 0 : if( bUndo )
556 : 0 : pModel->EndUndo();
557 : :
558 [ # # ]: 0 : if( pModel )
559 : 0 : pModel->SetChanged();
560 : 0 : }
561 : :
562 : : // -----------------------------------------------------------------------------
563 : :
564 : 0 : sal_Bool SAL_CALL CellCursor::isMergeable( ) throw (RuntimeException)
565 : : {
566 : 0 : CellPos aStart, aEnd;
567 [ # # ][ # # ]: 0 : return GetMergedSelection( aStart, aEnd ) ? sal_True : sal_False;
568 : : }
569 : :
570 : : // -----------------------------------------------------------------------------
571 : :
572 : 0 : sal_Bool SAL_CALL CellCursor::isUnmergeable( ) throw (RuntimeException)
573 : : {
574 : : // this is true if there is at least one merged cell in the current range
575 [ # # ]: 0 : for( sal_Int32 nRow = mnTop; nRow <= mnBottom; nRow++ )
576 : : {
577 [ # # ]: 0 : for( sal_Int32 nCol = mnLeft; nCol <= mnRight; nCol++ )
578 : : {
579 [ # # ][ # # ]: 0 : CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
[ # # ]
580 [ # # ][ # # ]: 0 : if( xCell.is() && ( (xCell->getRowSpan() > 1) || (xCell->getColumnSpan() > 1) ) )
[ # # ][ # # ]
[ # # ][ # # ]
581 : 0 : return sal_True;
582 [ # # ]: 0 : }
583 : : }
584 : 0 : return sal_False;
585 : : }
586 : :
587 : : // -----------------------------------------------------------------------------
588 : :
589 : : } }
590 : :
591 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|