Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <algorithm>
21 :
22 : #include <svx/sdr/table/tablecontroller.hxx>
23 : #include <tablemodel.hxx>
24 :
25 : #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
26 : #include <com/sun/star/container/XIndexAccess.hpp>
27 :
28 : #include <com/sun/star/beans/XPropertySet.hpp>
29 : #include <com/sun/star/table/XMergeableCellRange.hpp>
30 : #include <com/sun/star/table/XMergeableCell.hpp>
31 :
32 : #include <sal/config.h>
33 :
34 : #include <vcl/svapp.hxx>
35 : #include <svl/whiter.hxx>
36 :
37 : #include <sfx2/request.hxx>
38 :
39 : #include <editeng/scripttypeitem.hxx>
40 : #include <svx/svdotable.hxx>
41 : #include <svx/sdr/overlay/overlayobjectcell.hxx>
42 : #include <svx/sdr/overlay/overlaymanager.hxx>
43 : #include <svx/svxids.hrc>
44 : #include <editeng/outlobj.hxx>
45 : #include <svx/svdoutl.hxx>
46 : #include <svx/svdpagv.hxx>
47 : #include <svx/svdetc.hxx>
48 : #include <editeng/editobj.hxx>
49 : #include "editeng/editstat.hxx"
50 : #include "editeng/unolingu.hxx"
51 : #include "svx/sdrpagewindow.hxx"
52 : #include <svx/selectioncontroller.hxx>
53 : #include <svx/svdmodel.hxx>
54 : #include "svx/sdrpaintwindow.hxx"
55 : #include <svx/svxdlg.hxx>
56 : #include <editeng/boxitem.hxx>
57 : #include "cell.hxx"
58 : #include <editeng/borderline.hxx>
59 : #include <editeng/colritem.hxx>
60 : #include "editeng/lineitem.hxx"
61 : #include "svx/svdstr.hrc"
62 : #include "svx/svdglob.hxx"
63 : #include "svx/svdpage.hxx"
64 : #include "tableundo.hxx"
65 : #include "tablelayouter.hxx"
66 : #include <vcl/msgbox.hxx>
67 :
68 : using ::editeng::SvxBorderLine;
69 : using namespace ::sdr::table;
70 : using namespace ::com::sun::star;
71 : using namespace ::com::sun::star::uno;
72 : using namespace ::com::sun::star::table;
73 : using namespace ::com::sun::star::beans;
74 : using namespace ::com::sun::star::container;
75 : using namespace ::com::sun::star::text;
76 : using namespace ::com::sun::star::style;
77 :
78 : namespace sdr { namespace table {
79 :
80 : // --------------------------------------------------------------------
81 : // class SvxTableControllerModifyListener
82 : // --------------------------------------------------------------------
83 :
84 0 : class SvxTableControllerModifyListener : public ::cppu::WeakImplHelper1< ::com::sun::star::util::XModifyListener >
85 : {
86 : public:
87 0 : SvxTableControllerModifyListener( SvxTableController* pController )
88 0 : : mpController( pController ) {}
89 :
90 : // XModifyListener
91 : virtual void SAL_CALL modified( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException);
92 :
93 : // XEventListener
94 : virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);
95 :
96 : SvxTableController* mpController;
97 : };
98 :
99 : // --------------------------------------------------------------------
100 : // XModifyListener
101 : // --------------------------------------------------------------------
102 :
103 0 : void SAL_CALL SvxTableControllerModifyListener::modified( const ::com::sun::star::lang::EventObject& ) throw (::com::sun::star::uno::RuntimeException)
104 : {
105 0 : if( mpController )
106 0 : mpController->onTableModified();
107 0 : }
108 :
109 : // --------------------------------------------------------------------
110 : // XEventListener
111 : // --------------------------------------------------------------------
112 :
113 0 : void SAL_CALL SvxTableControllerModifyListener::disposing( const ::com::sun::star::lang::EventObject& ) throw (::com::sun::star::uno::RuntimeException)
114 : {
115 0 : mpController = 0;
116 0 : }
117 :
118 : // --------------------------------------------------------------------
119 : // class SvxTableController
120 : // --------------------------------------------------------------------
121 :
122 0 : rtl::Reference< sdr::SelectionController > CreateTableController( SdrObjEditView* pView, const SdrObject* pObj, const rtl::Reference< sdr::SelectionController >& xRefController )
123 : {
124 0 : return SvxTableController::create( pView, pObj, xRefController );
125 : }
126 :
127 : // --------------------------------------------------------------------
128 :
129 0 : rtl::Reference< sdr::SelectionController > SvxTableController::create( SdrObjEditView* pView, const SdrObject* pObj, const rtl::Reference< sdr::SelectionController >& xRefController )
130 : {
131 0 : if( xRefController.is() )
132 : {
133 0 : SvxTableController* pController = dynamic_cast< SvxTableController* >( xRefController.get() );
134 0 : if( pController && (pController->mxTableObj.get() == pObj) && (pController->mpView == pView) )
135 0 : return xRefController;
136 : }
137 0 : return new SvxTableController( pView, pObj );
138 : }
139 :
140 : // --------------------------------------------------------------------
141 :
142 0 : SvxTableController::SvxTableController( SdrObjEditView* pView, const SdrObject* pObj )
143 : : mbCellSelectionMode(false)
144 : , mbLeftButtonDown(false)
145 : , mpSelectionOverlay(0)
146 : , mpView( dynamic_cast< SdrView* >( pView ) )
147 : , mxTableObj( dynamic_cast< SdrTableObj* >( const_cast< SdrObject* >( pObj ) ) )
148 : , mpModel( 0 )
149 0 : , mnUpdateEvent( 0 )
150 : {
151 0 : if( pObj )
152 0 : mpModel = pObj->GetModel();
153 :
154 0 : if( mxTableObj.is() )
155 : {
156 0 : static_cast< const SdrTableObj* >( pObj )->getActiveCellPos( maCursorFirstPos );
157 0 : maCursorLastPos = maCursorFirstPos;
158 :
159 0 : Reference< XTable > xTable( static_cast< const SdrTableObj* >( pObj )->getTable() );
160 0 : if( xTable.is() )
161 : {
162 0 : mxModifyListener = new SvxTableControllerModifyListener( this );
163 0 : xTable->addModifyListener( mxModifyListener );
164 :
165 0 : mxTable.set( dynamic_cast< TableModel* >( xTable.get() ) );
166 0 : }
167 : }
168 0 : }
169 :
170 : // --------------------------------------------------------------------
171 :
172 0 : SvxTableController::~SvxTableController()
173 : {
174 0 : if( mnUpdateEvent )
175 : {
176 0 : Application::RemoveUserEvent( mnUpdateEvent );
177 : }
178 :
179 0 : if( mxModifyListener.is() && mxTableObj.get() )
180 : {
181 0 : Reference< XTable > xTable( static_cast< SdrTableObj* >( mxTableObj.get() )->getTable() );
182 0 : if( xTable.is() )
183 : {
184 0 : xTable->removeModifyListener( mxModifyListener );
185 0 : mxModifyListener.clear();
186 0 : }
187 : }
188 0 : }
189 :
190 : // --------------------------------------------------------------------
191 :
192 : const sal_uInt16 ACTION_NONE = 0;
193 : const sal_uInt16 ACTION_GOTO_FIRST_CELL = 1;
194 : const sal_uInt16 ACTION_GOTO_FIRST_COLUMN = 2;
195 : const sal_uInt16 ACTION_GOTO_FIRST_ROW = 3;
196 : const sal_uInt16 ACTION_GOTO_LEFT_CELL = 4;
197 : const sal_uInt16 ACTION_GOTO_UP_CELL = 5;
198 : const sal_uInt16 ACTION_GOTO_RIGHT_CELL = 6;
199 : const sal_uInt16 ACTION_GOTO_DOWN_CELL = 7;
200 : const sal_uInt16 ACTION_GOTO_LAST_CELL = 8;
201 : const sal_uInt16 ACTION_GOTO_LAST_COLUMN = 9;
202 : const sal_uInt16 ACTION_GOTO_LAST_ROW = 10;
203 : const sal_uInt16 ACTION_EDIT_CELL = 11;
204 : const sal_uInt16 ACTION_STOP_TEXT_EDIT = 12;
205 : const sal_uInt16 ACTION_REMOVE_SELECTION = 13;
206 : const sal_uInt16 ACTION_START_SELECTION = 14;
207 : const sal_uInt16 ACTION_HANDLED_BY_VIEW = 15;
208 : const sal_uInt16 ACTION_TAB = 18;
209 :
210 0 : bool SvxTableController::onKeyInput(const KeyEvent& rKEvt, Window* pWindow )
211 : {
212 0 : if( !checkTableObject() )
213 0 : return false;
214 :
215 : // check if we are read only
216 0 : if( mpModel && mpModel->IsReadOnly())
217 : {
218 0 : switch( rKEvt.GetKeyCode().GetCode() )
219 : {
220 : case awt::Key::DOWN:
221 : case awt::Key::UP:
222 : case awt::Key::LEFT:
223 : case awt::Key::RIGHT:
224 : case awt::Key::TAB:
225 : case awt::Key::HOME:
226 : case awt::Key::END:
227 : case awt::Key::NUM2:
228 : case awt::Key::NUM4:
229 : case awt::Key::NUM6:
230 : case awt::Key::NUM8:
231 : case awt::Key::ESCAPE:
232 : case awt::Key::F2:
233 0 : break;
234 : default:
235 : // tell the view we eat the event, no further processing needed
236 0 : return true;
237 : }
238 : }
239 :
240 0 : sal_uInt16 nAction = getKeyboardAction( rKEvt, pWindow );
241 :
242 0 : return executeAction( nAction, ( rKEvt.GetKeyCode().IsShift() ) ? sal_True : sal_False, pWindow );
243 : }
244 :
245 : // --------------------------------------------------------------------
246 : // ::com::sun::star::awt::XMouseClickHandler:
247 : // --------------------------------------------------------------------
248 :
249 0 : bool SvxTableController::onMouseButtonDown(const MouseEvent& rMEvt, Window* pWindow )
250 : {
251 0 : if( !pWindow || !checkTableObject() )
252 0 : return false;
253 :
254 0 : SdrViewEvent aVEvt;
255 0 : if( !rMEvt.IsRight() && mpView->PickAnything(rMEvt,SDRMOUSEBUTTONDOWN, aVEvt) == SDRHIT_HANDLE )
256 0 : return false;
257 :
258 0 : TableHitKind eHit = static_cast< SdrTableObj* >(mxTableObj.get())->CheckTableHit( pWindow->PixelToLogic(rMEvt.GetPosPixel()), maMouseDownPos.mnCol, maMouseDownPos.mnRow, 0 );
259 :
260 0 : mbLeftButtonDown = (rMEvt.GetClicks() == 1) && rMEvt.IsLeft();
261 :
262 0 : if( eHit == SDRTABLEHIT_CELL )
263 : {
264 0 : StartSelection( maMouseDownPos );
265 0 : return true;
266 : }
267 :
268 0 : if( rMEvt.IsRight() && eHit != SDRTABLEHIT_NONE )
269 0 : return true; // right click will become context menu
270 :
271 : // for cell selektion with the mouse remember our first hit
272 0 : if( mbLeftButtonDown )
273 : {
274 0 : RemoveSelection();
275 :
276 0 : Point aPnt(rMEvt.GetPosPixel());
277 0 : if (pWindow!=NULL)
278 0 : aPnt=pWindow->PixelToLogic(aPnt);
279 :
280 0 : SdrHdl* pHdl = mpView->PickHandle(aPnt);
281 :
282 0 : if( pHdl )
283 : {
284 0 : mbLeftButtonDown = false;
285 : }
286 : else
287 : {
288 0 : ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
289 :
290 0 : if( !pWindow || !pTableObj || eHit == SDRTABLEHIT_NONE)
291 : {
292 0 : mbLeftButtonDown = false;
293 : }
294 : }
295 : }
296 :
297 0 : return false;
298 : }
299 :
300 : // --------------------------------------------------------------------
301 :
302 0 : bool SvxTableController::onMouseButtonUp(const MouseEvent& rMEvt, Window* /*pWin*/)
303 : {
304 0 : if( !checkTableObject() )
305 0 : return false;
306 :
307 0 : mbLeftButtonDown = false;
308 :
309 0 : if( rMEvt.GetClicks() == 2 )
310 0 : return true;
311 :
312 0 : return false;
313 : }
314 :
315 : // --------------------------------------------------------------------
316 :
317 0 : bool SvxTableController::onMouseMove(const MouseEvent& rMEvt, Window* pWindow )
318 : {
319 0 : if( !checkTableObject() )
320 0 : return false;
321 :
322 0 : if( rMEvt.IsLeft() )
323 : {
324 0 : int i = 0;
325 0 : i++;
326 : }
327 :
328 0 : SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
329 0 : CellPos aPos;
330 0 : if( mbLeftButtonDown && pTableObj && pTableObj->CheckTableHit( pWindow->PixelToLogic(rMEvt.GetPosPixel()), aPos.mnCol, aPos.mnRow, 0 ) != SDRTABLEHIT_NONE )
331 : {
332 0 : if(aPos != maMouseDownPos)
333 : {
334 0 : if( mbCellSelectionMode )
335 : {
336 0 : setSelectedCells( maMouseDownPos, aPos );
337 0 : return true;
338 : }
339 : else
340 : {
341 0 : StartSelection( maMouseDownPos );
342 : }
343 : }
344 0 : else if( mbCellSelectionMode )
345 : {
346 0 : UpdateSelection( aPos );
347 0 : return true;
348 : }
349 : }
350 0 : return false;
351 : }
352 :
353 : // --------------------------------------------------------------------
354 :
355 0 : void SvxTableController::onSelectionHasChanged()
356 : {
357 0 : bool bSelected = false;
358 :
359 0 : SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
360 0 : if( pTableObj && pTableObj->IsTextEditActive() )
361 : {
362 0 : pTableObj->getActiveCellPos( maCursorFirstPos );
363 0 : maCursorLastPos = maCursorFirstPos;
364 0 : mbCellSelectionMode = false;
365 : }
366 : else
367 : {
368 0 : const SdrMarkList& rMarkList= mpView->GetMarkedObjectList();
369 0 : if( rMarkList.GetMarkCount() == 1 )
370 0 : bSelected = mxTableObj.get() == rMarkList.GetMark(0)->GetMarkedSdrObj();
371 : /* fdo#46186 Selecting the table means selecting the entire cells */
372 0 : if(!hasSelectedCells())
373 : {
374 0 : maCursorFirstPos = pTableObj->getFirstCell();
375 0 : maCursorLastPos = pTableObj->getLastCell();
376 0 : mbCellSelectionMode=true;
377 : }
378 : }
379 :
380 0 : if( bSelected )
381 : {
382 0 : updateSelectionOverlay();
383 : }
384 : else
385 : {
386 0 : destroySelectionOverlay();
387 : }
388 0 : }
389 :
390 : // --------------------------------------------------------------------
391 :
392 0 : void SvxTableController::GetState( SfxItemSet& rSet )
393 : {
394 0 : if( !mxTable.is() || !mxTableObj.is() || !mxTableObj->GetModel() )
395 0 : return;
396 :
397 0 : SfxItemSet* pSet = 0;
398 :
399 0 : bool bVertDone = false;
400 :
401 : // Iterate over all requested items in the set.
402 0 : SfxWhichIter aIter( rSet );
403 0 : sal_uInt16 nWhich = aIter.FirstWhich();
404 0 : while (nWhich)
405 : {
406 0 : switch (nWhich)
407 : {
408 : case SID_TABLE_VERT_BOTTOM:
409 : case SID_TABLE_VERT_CENTER:
410 : case SID_TABLE_VERT_NONE:
411 : {
412 0 : if( !mxTable.is() || !mxTableObj->GetModel() )
413 : {
414 0 : rSet.DisableItem(nWhich);
415 : }
416 0 : else if(!bVertDone)
417 : {
418 0 : if( !pSet )
419 : {
420 0 : pSet = new SfxItemSet( mxTableObj->GetModel()->GetItemPool() );
421 0 : MergeAttrFromSelectedCells(*pSet, sal_False);
422 : }
423 :
424 0 : SdrTextVertAdjust eAdj = SDRTEXTVERTADJUST_BLOCK;
425 :
426 0 : if( pSet->GetItemState( SDRATTR_TEXT_VERTADJUST ) != SFX_ITEM_DONTCARE )
427 0 : eAdj = ((SdrTextVertAdjustItem&)(pSet->Get(SDRATTR_TEXT_VERTADJUST))).GetValue();
428 :
429 0 : rSet.Put(SfxBoolItem(SID_TABLE_VERT_BOTTOM, eAdj == SDRTEXTVERTADJUST_BOTTOM));
430 0 : rSet.Put(SfxBoolItem(SID_TABLE_VERT_CENTER, eAdj == SDRTEXTVERTADJUST_CENTER));
431 0 : rSet.Put(SfxBoolItem(SID_TABLE_VERT_NONE, eAdj == SDRTEXTVERTADJUST_TOP));
432 0 : bVertDone = true;
433 : }
434 0 : break;
435 : }
436 : case SID_TABLE_DELETE_ROW:
437 0 : if( !mxTable.is() || !hasSelectedCells() || (mxTable->getRowCount() <= 1) )
438 0 : rSet.DisableItem(SID_TABLE_DELETE_ROW);
439 0 : break;
440 : case SID_TABLE_DELETE_COL:
441 0 : if( !mxTable.is() || !hasSelectedCells() || (mxTable->getColumnCount() <= 1) )
442 0 : rSet.DisableItem(SID_TABLE_DELETE_COL);
443 0 : break;
444 : case SID_TABLE_MERGE_CELLS:
445 0 : if( !mxTable.is() || !hasSelectedCells() )
446 0 : rSet.DisableItem(SID_TABLE_MERGE_CELLS);
447 0 : break;
448 : case SID_TABLE_SPLIT_CELLS:
449 0 : if( !hasSelectedCells() || !mxTable.is() )
450 0 : rSet.DisableItem(SID_TABLE_SPLIT_CELLS);
451 0 : break;
452 :
453 : case SID_OPTIMIZE_TABLE:
454 : case SID_TABLE_DISTRIBUTE_COLUMNS:
455 : case SID_TABLE_DISTRIBUTE_ROWS:
456 : {
457 0 : bool bDistributeColumns = false;
458 0 : bool bDistributeRows = false;
459 0 : if( mxTable.is() )
460 : {
461 0 : CellPos aStart, aEnd;
462 0 : getSelectedCells( aStart, aEnd );
463 :
464 0 : bDistributeColumns = aStart.mnCol != aEnd.mnCol;
465 0 : bDistributeRows = aStart.mnRow != aEnd.mnRow;
466 : }
467 0 : if( !bDistributeColumns && !bDistributeRows )
468 0 : rSet.DisableItem(SID_OPTIMIZE_TABLE);
469 0 : if( !bDistributeColumns )
470 0 : rSet.DisableItem(SID_TABLE_DISTRIBUTE_COLUMNS);
471 0 : if( !bDistributeRows )
472 0 : rSet.DisableItem(SID_TABLE_DISTRIBUTE_ROWS);
473 0 : break;
474 : }
475 :
476 : case SID_AUTOFORMAT:
477 : case SID_TABLE_SORT_DIALOG:
478 : case SID_TABLE_AUTOSUM:
479 : // if( !mxTable.is() )
480 : // rSet.DisableItem( nWhich );
481 0 : break;
482 : default:
483 0 : break;
484 : }
485 0 : nWhich = aIter.NextWhich();
486 : }
487 0 : delete pSet;
488 : }
489 :
490 : // --------------------------------------------------------------------
491 :
492 0 : void SvxTableController::onInsert( sal_uInt16 nSId, const SfxItemSet* pArgs )
493 : {
494 0 : ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
495 0 : if( !pTableObj )
496 0 : return;
497 :
498 0 : if( mxTable.is() ) try
499 : {
500 : //
501 0 : bool bInsertAfter = true;
502 0 : sal_uInt16 nCount = 0;
503 0 : if( pArgs )
504 : {
505 0 : const SfxPoolItem* pItem = 0;
506 0 : pArgs->GetItemState(nSId, sal_False, &pItem);
507 0 : if (pItem)
508 : {
509 0 : nCount = ((const SfxInt16Item* )pItem)->GetValue();
510 0 : if(SFX_ITEM_SET == pArgs->GetItemState(SID_TABLE_PARAM_INSERT_AFTER, sal_True, &pItem))
511 0 : bInsertAfter = ((const SfxBoolItem* )pItem)->GetValue();
512 : }
513 : }
514 :
515 0 : CellPos aStart, aEnd;
516 0 : if( hasSelectedCells() )
517 : {
518 0 : getSelectedCells( aStart, aEnd );
519 : }
520 : else
521 : {
522 0 : if( bInsertAfter )
523 : {
524 0 : aStart.mnCol = mxTable->getColumnCount() - 1;
525 0 : aStart.mnRow = mxTable->getRowCount() - 1;
526 0 : aEnd = aStart;
527 : }
528 : }
529 :
530 0 : if( pTableObj->IsTextEditActive() )
531 0 : mpView->SdrEndTextEdit(sal_True);
532 :
533 0 : RemoveSelection();
534 :
535 0 : const OUString sSize( "Size" );
536 :
537 0 : const bool bUndo = mpModel && mpModel->IsUndoEnabled();
538 :
539 0 : switch( nSId )
540 : {
541 : case SID_TABLE_INSERT_COL:
542 : {
543 0 : TableModelNotifyGuard aGuard( mxTable.get() );
544 :
545 0 : if( bUndo )
546 : {
547 0 : mpModel->BegUndo( ImpGetResStr(STR_TABLE_INSCOL) );
548 0 : mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
549 : }
550 :
551 0 : Reference< XTableColumns > xCols( mxTable->getColumns() );
552 0 : const sal_Int32 nNewColumns = (nCount == 0) ? (aEnd.mnCol - aStart.mnCol + 1) : nCount;
553 0 : const sal_Int32 nNewStartColumn = aEnd.mnCol + (bInsertAfter ? 1 : 0);
554 0 : xCols->insertByIndex( nNewStartColumn, nNewColumns );
555 :
556 0 : for( sal_Int32 nOffset = 0; nOffset < nNewColumns; nOffset++ )
557 : {
558 : // Resolves fdo#61540
559 : // On Insert before, the reference column whose size is going to be
560 : // used for newly created column(s) is wrong. As the new columns are
561 : // inserted before the reference column, the reference column moved
562 : // to the new position by no., of new columns i.e (earlier+newcolumns).
563 0 : Reference< XPropertySet >(xCols->getByIndex(nNewStartColumn+nOffset), UNO_QUERY_THROW )->
564 : setPropertyValue( sSize,
565 0 : Reference< XPropertySet >(xCols->getByIndex( bInsertAfter?nNewStartColumn-1:nNewStartColumn+nNewColumns ), UNO_QUERY_THROW )->
566 0 : getPropertyValue( sSize ) );
567 : }
568 :
569 0 : if( bUndo )
570 0 : mpModel->EndUndo();
571 :
572 0 : aStart.mnCol = nNewStartColumn;
573 0 : aStart.mnRow = 0;
574 0 : aEnd.mnCol = aStart.mnCol + nNewColumns - 1;
575 0 : aEnd.mnRow = mxTable->getRowCount() - 1;
576 0 : break;
577 : }
578 :
579 : case SID_TABLE_INSERT_ROW:
580 : {
581 0 : TableModelNotifyGuard aGuard( mxTable.get() );
582 :
583 0 : if( bUndo )
584 : {
585 0 : mpModel->BegUndo( ImpGetResStr(STR_TABLE_INSROW ) );
586 0 : mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
587 : }
588 :
589 0 : Reference< XTableRows > xRows( mxTable->getRows() );
590 0 : const sal_Int32 nNewRows = (nCount == 0) ? (aEnd.mnRow - aStart.mnRow + 1) : nCount;
591 0 : const sal_Int32 nNewRowStart = aEnd.mnRow + (bInsertAfter ? 1 : 0);
592 0 : xRows->insertByIndex( nNewRowStart, nNewRows );
593 :
594 0 : for( sal_Int32 nOffset = 0; nOffset < nNewRows; nOffset++ )
595 : {
596 0 : Reference< XPropertySet >( xRows->getByIndex( aEnd.mnRow + nOffset + 1 ), UNO_QUERY_THROW )->
597 : setPropertyValue( sSize,
598 0 : Reference< XPropertySet >( xRows->getByIndex( aStart.mnRow + nOffset ), UNO_QUERY_THROW )->
599 0 : getPropertyValue( sSize ) );
600 : }
601 :
602 0 : if( bUndo )
603 0 : mpModel->EndUndo();
604 :
605 0 : aStart.mnCol = 0;
606 0 : aStart.mnRow = nNewRowStart;
607 0 : aEnd.mnCol = mxTable->getColumnCount() - 1;
608 0 : aEnd.mnRow = aStart.mnRow + nNewRows - 1;
609 0 : break;
610 : }
611 : }
612 :
613 0 : StartSelection( aStart );
614 0 : UpdateSelection( aEnd );
615 : }
616 0 : catch( Exception& )
617 : {
618 : OSL_FAIL("svx::SvxTableController::onInsert(), exception caught!");
619 : }
620 : }
621 :
622 : // --------------------------------------------------------------------
623 :
624 0 : void SvxTableController::onDelete( sal_uInt16 nSId )
625 : {
626 0 : ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
627 0 : if( !pTableObj )
628 0 : return;
629 :
630 0 : if( mxTable.is() && hasSelectedCells() )
631 : {
632 0 : CellPos aStart, aEnd;
633 0 : getSelectedCells( aStart, aEnd );
634 :
635 0 : if( pTableObj->IsTextEditActive() )
636 0 : mpView->SdrEndTextEdit(sal_True);
637 :
638 0 : RemoveSelection();
639 :
640 0 : bool bDeleteTable = false;
641 0 : switch( nSId )
642 : {
643 : case SID_TABLE_DELETE_COL:
644 : {
645 0 : const sal_Int32 nRemovedColumns = aEnd.mnCol - aStart.mnCol + 1;
646 0 : if( nRemovedColumns == mxTable->getColumnCount() )
647 : {
648 0 : bDeleteTable = true;
649 : }
650 : else
651 : {
652 0 : Reference< XTableColumns > xCols( mxTable->getColumns() );
653 0 : xCols->removeByIndex( aStart.mnCol, nRemovedColumns );
654 : }
655 0 : break;
656 : }
657 :
658 : case SID_TABLE_DELETE_ROW:
659 : {
660 0 : const sal_Int32 nRemovedRows = aEnd.mnRow - aStart.mnRow + 1;
661 0 : if( nRemovedRows == mxTable->getRowCount() )
662 : {
663 0 : bDeleteTable = true;
664 : }
665 : else
666 : {
667 0 : Reference< XTableRows > xRows( mxTable->getRows() );
668 0 : xRows->removeByIndex( aStart.mnRow, nRemovedRows );
669 : }
670 0 : break;
671 : }
672 : }
673 :
674 0 : if( bDeleteTable )
675 0 : mpView->DeleteMarkedObj();
676 : else
677 0 : UpdateTableShape();
678 : }
679 : }
680 :
681 : // --------------------------------------------------------------------
682 :
683 0 : void SvxTableController::onSelect( sal_uInt16 nSId )
684 : {
685 0 : if( mxTable.is() )
686 : {
687 0 : const sal_Int32 nRowCount = mxTable->getRowCount();
688 0 : const sal_Int32 nColCount = mxTable->getColumnCount();
689 0 : if( nRowCount && nColCount )
690 : {
691 0 : CellPos aStart, aEnd;
692 0 : getSelectedCells( aStart, aEnd );
693 :
694 0 : switch( nSId )
695 : {
696 : case SID_TABLE_SELECT_ALL:
697 0 : aEnd.mnCol = 0; aEnd.mnRow = 0;
698 0 : aStart.mnCol = nColCount - 1; aStart.mnRow = nRowCount - 1;
699 0 : break;
700 : case SID_TABLE_SELECT_COL:
701 0 : aEnd.mnRow = nRowCount - 1;
702 0 : aStart.mnRow = 0;
703 0 : break;
704 : case SID_TABLE_SELECT_ROW:
705 0 : aEnd.mnCol = nColCount - 1;
706 0 : aStart.mnCol = 0;
707 0 : break;
708 : }
709 :
710 0 : StartSelection( aEnd );
711 0 : gotoCell( aStart, true, 0 );
712 : }
713 : }
714 0 : }
715 :
716 : // --------------------------------------------------------------------
717 0 : void SvxTableController::onFormatTable( SfxRequest& rReq )
718 : {
719 0 : ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
720 0 : if( !pTableObj )
721 0 : return;
722 :
723 0 : const SfxItemSet* pArgs = rReq.GetArgs();
724 :
725 0 : if( !pArgs && pTableObj->GetModel() )
726 : {
727 0 : SfxItemSet aNewAttr( pTableObj->GetModel()->GetItemPool() );
728 :
729 : // merge drawing layer text distance items into SvxBoxItem used by the dialog
730 0 : SvxBoxItem aBoxItem( static_cast< const SvxBoxItem& >( aNewAttr.Get( SDRATTR_TABLE_BORDER ) ) );
731 0 : aBoxItem.SetDistance( sal::static_int_cast< sal_uInt16 >( ((SdrTextLeftDistItem&)(aNewAttr.Get(SDRATTR_TEXT_LEFTDIST))).GetValue()), BOX_LINE_LEFT );
732 0 : aBoxItem.SetDistance( sal::static_int_cast< sal_uInt16 >( ((SdrTextRightDistItem&)(aNewAttr.Get(SDRATTR_TEXT_RIGHTDIST))).GetValue()), BOX_LINE_RIGHT );
733 0 : aBoxItem.SetDistance( sal::static_int_cast< sal_uInt16 >( ((SdrTextUpperDistItem&)(aNewAttr.Get(SDRATTR_TEXT_UPPERDIST))).GetValue()), BOX_LINE_TOP );
734 0 : aBoxItem.SetDistance( sal::static_int_cast< sal_uInt16 >( ((SdrTextLowerDistItem&)(aNewAttr.Get(SDRATTR_TEXT_LOWERDIST))).GetValue()), BOX_LINE_BOTTOM );
735 :
736 0 : SvxBoxInfoItem aBoxInfoItem( static_cast< const SvxBoxInfoItem& >( aNewAttr.Get( SDRATTR_TABLE_BORDER_INNER ) ) );
737 :
738 0 : MergeAttrFromSelectedCells(aNewAttr, sal_False);
739 0 : FillCommonBorderAttrFromSelectedCells( aBoxItem, aBoxInfoItem );
740 0 : aNewAttr.Put( aBoxItem );
741 0 : aNewAttr.Put( aBoxInfoItem );
742 :
743 0 : SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
744 0 : std::auto_ptr< SfxAbstractTabDialog > pDlg( pFact ? pFact->CreateSvxFormatCellsDialog( NULL, &aNewAttr, pTableObj->GetModel(), pTableObj) : 0 );
745 : // Even Cancel Button is returning positive(101) value,
746 0 : if( pDlg.get() && ( pDlg->Execute() == RET_OK ) )
747 : {
748 0 : SfxItemSet aNewSet( aNewAttr );
749 0 : aNewSet.Put( *(pDlg->GetOutputItemSet ()) );
750 :
751 0 : SvxBoxItem aNewBoxItem( static_cast< const SvxBoxItem& >( aNewSet.Get( SDRATTR_TABLE_BORDER ) ) );
752 :
753 0 : if( aNewBoxItem.GetDistance( BOX_LINE_LEFT ) != aBoxItem.GetDistance( BOX_LINE_LEFT ) )
754 0 : aNewSet.Put(SdrTextLeftDistItem( aNewBoxItem.GetDistance( BOX_LINE_LEFT ) ) );
755 :
756 0 : if( aNewBoxItem.GetDistance( BOX_LINE_RIGHT ) != aBoxItem.GetDistance( BOX_LINE_RIGHT ) )
757 0 : aNewSet.Put(SdrTextRightDistItem( aNewBoxItem.GetDistance( BOX_LINE_RIGHT ) ) );
758 :
759 0 : if( aNewBoxItem.GetDistance( BOX_LINE_TOP ) != aBoxItem.GetDistance( BOX_LINE_TOP ) )
760 0 : aNewSet.Put(SdrTextUpperDistItem( aNewBoxItem.GetDistance( BOX_LINE_TOP ) ) );
761 :
762 0 : if( aNewBoxItem.GetDistance( BOX_LINE_BOTTOM ) != aBoxItem.GetDistance( BOX_LINE_BOTTOM ) )
763 0 : aNewSet.Put(SdrTextLowerDistItem( aNewBoxItem.GetDistance( BOX_LINE_BOTTOM ) ) );
764 :
765 0 : SetAttrToSelectedCells(aNewSet, sal_False);
766 0 : }
767 : }
768 : }
769 :
770 : // --------------------------------------------------------------------
771 :
772 0 : void SvxTableController::Execute( SfxRequest& rReq )
773 : {
774 0 : const sal_uInt16 nSId = rReq.GetSlot();
775 0 : switch( nSId )
776 : {
777 : case SID_TABLE_INSERT_ROW:
778 : case SID_TABLE_INSERT_COL:
779 0 : onInsert( nSId, rReq.GetArgs() );
780 0 : break;
781 : case SID_TABLE_DELETE_ROW:
782 : case SID_TABLE_DELETE_COL:
783 0 : onDelete( nSId );
784 0 : break;
785 : case SID_TABLE_SELECT_ALL:
786 : case SID_TABLE_SELECT_COL:
787 : case SID_TABLE_SELECT_ROW:
788 0 : onSelect( nSId );
789 0 : break;
790 : case SID_FORMAT_TABLE_DLG:
791 0 : onFormatTable( rReq );
792 0 : break;
793 :
794 : case SID_FRAME_LINESTYLE:
795 : case SID_FRAME_LINECOLOR:
796 : case SID_ATTR_BORDER:
797 : {
798 0 : const SfxItemSet* pArgs = rReq.GetArgs();
799 0 : if( pArgs )
800 0 : ApplyBorderAttr( *pArgs );
801 : }
802 0 : break;
803 :
804 : case SID_ATTR_FILL_STYLE:
805 : {
806 0 : const SfxItemSet* pArgs = rReq.GetArgs();
807 0 : if( pArgs )
808 0 : SetAttributes( *pArgs, false );
809 : }
810 0 : break;
811 :
812 : case SID_TABLE_MERGE_CELLS:
813 0 : MergeMarkedCells();
814 0 : break;
815 :
816 : case SID_TABLE_SPLIT_CELLS:
817 0 : SplitMarkedCells();
818 0 : break;
819 :
820 : case SID_TABLE_DISTRIBUTE_COLUMNS:
821 0 : DistributeColumns();
822 0 : break;
823 :
824 : case SID_TABLE_DISTRIBUTE_ROWS:
825 0 : DistributeRows();
826 0 : break;
827 :
828 : case SID_TABLE_VERT_BOTTOM:
829 : case SID_TABLE_VERT_CENTER:
830 : case SID_TABLE_VERT_NONE:
831 0 : SetVertical( nSId );
832 0 : break;
833 :
834 : case SID_AUTOFORMAT:
835 : case SID_TABLE_SORT_DIALOG:
836 : case SID_TABLE_AUTOSUM:
837 : default:
838 0 : break;
839 :
840 : case SID_TABLE_STYLE:
841 0 : SetTableStyle( rReq.GetArgs() );
842 0 : break;
843 :
844 : case SID_TABLE_STYLE_SETTINGS:
845 0 : SetTableStyleSettings( rReq.GetArgs() );
846 0 : break;
847 : }
848 0 : }
849 :
850 0 : void SvxTableController::SetTableStyle( const SfxItemSet* pArgs )
851 : {
852 0 : SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
853 0 : SdrModel* pModel = pTableObj ? pTableObj->GetModel() : 0;
854 :
855 0 : if( !pTableObj || !pModel || !pArgs || (SFX_ITEM_SET != pArgs->GetItemState(SID_TABLE_STYLE, sal_False)) )
856 0 : return;
857 :
858 0 : const SfxStringItem* pArg = dynamic_cast< const SfxStringItem* >( &pArgs->Get( SID_TABLE_STYLE ) );
859 0 : if( pArg && mxTable.is() ) try
860 : {
861 0 : Reference< XStyleFamiliesSupplier > xSFS( pModel->getUnoModel(), UNO_QUERY_THROW );
862 0 : Reference< XNameAccess > xFamilyNameAccess( xSFS->getStyleFamilies(), UNO_QUERY_THROW );
863 0 : const OUString sFamilyName( "table" );
864 0 : Reference< XNameAccess > xTableFamilyAccess( xFamilyNameAccess->getByName( sFamilyName ), UNO_QUERY_THROW );
865 :
866 0 : if( xTableFamilyAccess->hasByName( pArg->GetValue() ) )
867 : {
868 : // found table style with the same name
869 0 : Reference< XIndexAccess > xNewTableStyle( xTableFamilyAccess->getByName( pArg->GetValue() ), UNO_QUERY_THROW );
870 :
871 0 : const bool bUndo = pModel->IsUndoEnabled();
872 :
873 0 : if( bUndo )
874 : {
875 0 : pModel->BegUndo( ImpGetResStr(STR_TABLE_STYLE) );
876 0 : pModel->AddUndo( new TableStyleUndo( *pTableObj ) );
877 : }
878 :
879 0 : pTableObj->setTableStyle( xNewTableStyle );
880 :
881 0 : const sal_Int32 nRowCount = mxTable->getRowCount();
882 0 : const sal_Int32 nColCount = mxTable->getColumnCount();
883 0 : for( sal_Int32 nRow = 0; nRow < nRowCount; nRow++ )
884 : {
885 0 : for( sal_Int32 nCol = 0; nCol < nColCount; nCol++ ) try
886 : {
887 0 : CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
888 0 : if( xCell.is() )
889 : {
890 0 : SfxItemSet aSet( xCell->GetItemSet() );
891 0 : bool bChanges = false;
892 0 : const SfxItemSet& rStyleAttribs = xCell->GetStyleSheet()->GetItemSet();
893 :
894 0 : for ( sal_uInt16 nWhich = SDRATTR_START; nWhich <= SDRATTR_TABLE_LAST; nWhich++ )
895 : {
896 0 : if( (rStyleAttribs.GetItemState( nWhich ) == SFX_ITEM_ON) && (aSet.GetItemState( nWhich ) == SFX_ITEM_ON) )
897 : {
898 0 : aSet.ClearItem( nWhich );
899 0 : bChanges = true;
900 : }
901 : }
902 :
903 0 : if( bChanges )
904 : {
905 0 : if( bUndo )
906 0 : xCell->AddUndo();
907 :
908 0 : xCell->SetMergedItemSetAndBroadcast( aSet, sal_True );
909 0 : }
910 0 : }
911 : }
912 0 : catch( Exception& )
913 : {
914 : OSL_FAIL( "svx::SvxTableController::SetTableStyle(), exception caught!" );
915 : }
916 : }
917 :
918 0 : if( bUndo )
919 0 : pModel->EndUndo();
920 0 : }
921 : }
922 0 : catch( Exception& )
923 : {
924 : OSL_FAIL( "svx::SvxTableController::SetTableStyle(), exception caught!" );
925 : }
926 : }
927 :
928 0 : void SvxTableController::SetTableStyleSettings( const SfxItemSet* pArgs )
929 : {
930 0 : SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
931 0 : SdrModel* pModel = pTableObj ? pTableObj->GetModel() : 0;
932 :
933 0 : if( !pTableObj || !pModel )
934 0 : return;
935 :
936 0 : TableStyleSettings aSettings( pTableObj->getTableStyleSettings() );
937 :
938 0 : const SfxPoolItem *pPoolItem=NULL;
939 :
940 0 : if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USEFIRSTROWSTYLE, sal_False,&pPoolItem)) )
941 0 : aSettings.mbUseFirstRow = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
942 :
943 0 : if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USELASTROWSTYLE, sal_False,&pPoolItem)) )
944 0 : aSettings.mbUseLastRow = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
945 :
946 0 : if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USEBANDINGROWSTYLE, sal_False,&pPoolItem)) )
947 0 : aSettings.mbUseRowBanding = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
948 :
949 0 : if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USEFIRSTCOLUMNSTYLE, sal_False,&pPoolItem)) )
950 0 : aSettings.mbUseFirstColumn = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
951 :
952 0 : if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USELASTCOLUMNSTYLE, sal_False,&pPoolItem)) )
953 0 : aSettings.mbUseLastColumn = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
954 :
955 0 : if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USEBANDINGCOLUMNSTYLE, sal_False,&pPoolItem)) )
956 0 : aSettings.mbUseColumnBanding = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
957 :
958 0 : if( aSettings == pTableObj->getTableStyleSettings() )
959 0 : return;
960 :
961 0 : const bool bUndo = pModel->IsUndoEnabled();
962 :
963 0 : if( bUndo )
964 : {
965 0 : pModel->BegUndo( ImpGetResStr(STR_TABLE_STYLE_SETTINGS) );
966 0 : pModel->AddUndo( new TableStyleUndo( *pTableObj ) );
967 : }
968 :
969 0 : pTableObj->setTableStyleSettings( aSettings );
970 :
971 0 : if( bUndo )
972 0 : pModel->EndUndo();
973 : }
974 :
975 0 : void SvxTableController::SetVertical( sal_uInt16 nSId )
976 : {
977 0 : SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
978 0 : if( mxTable.is() && pTableObj )
979 : {
980 0 : TableModelNotifyGuard aGuard( mxTable.get() );
981 :
982 0 : CellPos aStart, aEnd;
983 0 : getSelectedCells( aStart, aEnd );
984 :
985 0 : SdrTextVertAdjust eAdj = SDRTEXTVERTADJUST_TOP;
986 :
987 0 : switch( nSId )
988 : {
989 : case SID_TABLE_VERT_BOTTOM:
990 0 : eAdj = SDRTEXTVERTADJUST_BOTTOM;
991 0 : break;
992 : case SID_TABLE_VERT_CENTER:
993 0 : eAdj = SDRTEXTVERTADJUST_CENTER;
994 0 : break;
995 : //case SID_TABLE_VERT_NONE:
996 : default:
997 0 : break;
998 : }
999 :
1000 0 : SdrTextVertAdjustItem aItem( eAdj );
1001 :
1002 0 : for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
1003 : {
1004 0 : for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
1005 : {
1006 0 : CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
1007 0 : if( xCell.is() )
1008 0 : xCell->SetMergedItem(aItem);
1009 0 : }
1010 : }
1011 :
1012 0 : UpdateTableShape();
1013 : }
1014 0 : }
1015 :
1016 0 : void SvxTableController::MergeMarkedCells()
1017 : {
1018 0 : CellPos aStart, aEnd;
1019 0 : getSelectedCells( aStart, aEnd );
1020 0 : SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1021 0 : if( pTableObj )
1022 : {
1023 0 : if( pTableObj->IsTextEditActive() )
1024 0 : mpView->SdrEndTextEdit(sal_True);
1025 :
1026 0 : TableModelNotifyGuard aGuard( mxTable.get() );
1027 0 : MergeRange( aStart.mnCol, aStart.mnRow, aEnd.mnCol, aEnd.mnRow );
1028 : }
1029 0 : }
1030 :
1031 0 : void SvxTableController::SplitMarkedCells()
1032 : {
1033 0 : if( mxTable.is() )
1034 : {
1035 0 : CellPos aStart, aEnd;
1036 0 : getSelectedCells( aStart, aEnd );
1037 :
1038 0 : SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
1039 0 : std::auto_ptr< SvxAbstractSplittTableDialog > xDlg( pFact ? pFact->CreateSvxSplittTableDialog( NULL, false, 99, 99 ) : 0 );
1040 0 : if( xDlg.get() && xDlg->Execute() )
1041 : {
1042 0 : const sal_Int32 nCount = xDlg->GetCount() - 1;
1043 0 : if( nCount < 1 )
1044 0 : return;
1045 :
1046 0 : getSelectedCells( aStart, aEnd );
1047 :
1048 0 : Reference< XMergeableCellRange > xRange( mxTable->createCursorByRange( mxTable->getCellRangeByPosition( aStart.mnCol, aStart.mnRow, aEnd.mnCol, aEnd.mnRow ) ), UNO_QUERY_THROW );
1049 :
1050 0 : const sal_Int32 nRowCount = mxTable->getRowCount();
1051 0 : const sal_Int32 nColCount = mxTable->getColumnCount();
1052 :
1053 :
1054 0 : SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
1055 0 : if( pTableObj )
1056 : {
1057 0 : if( pTableObj->IsTextEditActive() )
1058 0 : mpView->SdrEndTextEdit(sal_True);
1059 :
1060 0 : TableModelNotifyGuard aGuard( mxTable.get() );
1061 :
1062 0 : const bool bUndo = mpModel && mpModel->IsUndoEnabled();
1063 0 : if( bUndo )
1064 : {
1065 0 : mpModel->BegUndo( ImpGetResStr(STR_TABLE_SPLIT) );
1066 0 : mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
1067 : }
1068 :
1069 0 : if( xDlg->IsHorizontal() )
1070 : {
1071 0 : xRange->split( 0, nCount );
1072 : }
1073 : else
1074 : {
1075 0 : xRange->split( nCount, 0 );
1076 : }
1077 :
1078 0 : if( bUndo )
1079 0 : mpModel->EndUndo();
1080 : }
1081 0 : aEnd.mnRow += mxTable->getRowCount() - nRowCount;
1082 0 : aEnd.mnCol += mxTable->getColumnCount() - nColCount;
1083 :
1084 0 : setSelectedCells( aStart, aEnd );
1085 0 : }
1086 : }
1087 : }
1088 :
1089 0 : void SvxTableController::DistributeColumns()
1090 : {
1091 0 : SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
1092 0 : if( pTableObj )
1093 : {
1094 0 : const bool bUndo = mpModel && mpModel->IsUndoEnabled();
1095 0 : if( bUndo )
1096 : {
1097 0 : mpModel->BegUndo( ImpGetResStr(STR_TABLE_DISTRIBUTE_COLUMNS) );
1098 0 : mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
1099 : }
1100 :
1101 0 : CellPos aStart, aEnd;
1102 0 : getSelectedCells( aStart, aEnd );
1103 0 : pTableObj->DistributeColumns( aStart.mnCol, aEnd.mnCol );
1104 :
1105 0 : if( bUndo )
1106 0 : mpModel->EndUndo();
1107 : }
1108 0 : }
1109 :
1110 0 : void SvxTableController::DistributeRows()
1111 : {
1112 0 : SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
1113 0 : if( pTableObj )
1114 : {
1115 0 : const bool bUndo = mpModel && mpModel->IsUndoEnabled();
1116 0 : if( bUndo )
1117 : {
1118 0 : mpModel->BegUndo( ImpGetResStr(STR_TABLE_DISTRIBUTE_ROWS) );
1119 0 : mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
1120 : }
1121 :
1122 0 : CellPos aStart, aEnd;
1123 0 : getSelectedCells( aStart, aEnd );
1124 0 : pTableObj->DistributeRows( aStart.mnRow, aEnd.mnRow );
1125 :
1126 0 : if( bUndo )
1127 0 : mpModel->EndUndo();
1128 : }
1129 0 : }
1130 :
1131 0 : bool SvxTableController::DeleteMarked()
1132 : {
1133 0 : if( mbCellSelectionMode )
1134 : {
1135 0 : if( mxTable.is() )
1136 : {
1137 0 : CellPos aStart, aEnd;
1138 0 : getSelectedCells( aStart, aEnd );
1139 0 : for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
1140 : {
1141 0 : for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
1142 : {
1143 0 : CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
1144 0 : if( xCell.is() )
1145 0 : xCell->SetOutlinerParaObject( 0 );
1146 0 : }
1147 : }
1148 :
1149 0 : UpdateTableShape();
1150 0 : return true;
1151 : }
1152 : }
1153 :
1154 0 : return false;
1155 : }
1156 :
1157 0 : bool SvxTableController::GetStyleSheet( SfxStyleSheet*& rpStyleSheet ) const
1158 : {
1159 0 : if( hasSelectedCells() )
1160 : {
1161 0 : rpStyleSheet = 0;
1162 :
1163 0 : if( mxTable.is() )
1164 : {
1165 0 : SfxStyleSheet* pRet=0;
1166 0 : bool b1st=true;
1167 :
1168 0 : CellPos aStart, aEnd;
1169 0 : const_cast<SvxTableController&>(*this).getSelectedCells( aStart, aEnd );
1170 :
1171 0 : for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
1172 : {
1173 0 : for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
1174 : {
1175 0 : CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
1176 0 : if( xCell.is() )
1177 : {
1178 0 : SfxStyleSheet* pSS=xCell->GetStyleSheet();
1179 0 : if(b1st)
1180 : {
1181 0 : pRet=pSS;
1182 : }
1183 0 : else if(pRet != pSS)
1184 : {
1185 0 : return true;
1186 : }
1187 0 : b1st=false;
1188 : }
1189 0 : }
1190 : }
1191 0 : rpStyleSheet = pRet;
1192 0 : return true;
1193 : }
1194 : }
1195 0 : return false;
1196 : }
1197 :
1198 0 : bool SvxTableController::SetStyleSheet( SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr )
1199 : {
1200 0 : if( hasSelectedCells() && (!pStyleSheet || pStyleSheet->GetFamily() == SFX_STYLE_FAMILY_FRAME) )
1201 : {
1202 0 : if( mxTable.is() )
1203 : {
1204 0 : CellPos aStart, aEnd;
1205 0 : getSelectedCells( aStart, aEnd );
1206 :
1207 0 : for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
1208 : {
1209 0 : for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
1210 : {
1211 0 : CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
1212 0 : if( xCell.is() )
1213 0 : xCell->SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
1214 0 : }
1215 : }
1216 :
1217 0 : UpdateTableShape();
1218 0 : return true;
1219 : }
1220 : }
1221 0 : return false;
1222 : }
1223 :
1224 : // --------------------------------------------------------------------
1225 : // internals
1226 : // --------------------------------------------------------------------
1227 :
1228 0 : bool SvxTableController::checkTableObject()
1229 : {
1230 0 : return mxTableObj.is();
1231 : }
1232 :
1233 : // --------------------------------------------------------------------
1234 :
1235 0 : sal_uInt16 SvxTableController::getKeyboardAction( const KeyEvent& rKEvt, Window* /*pWindow*/ )
1236 : {
1237 0 : const bool bMod1 = rKEvt.GetKeyCode().IsMod1(); // ctrl
1238 0 : const bool bMod2 = rKEvt.GetKeyCode().IsMod2() != 0; // Alt
1239 :
1240 0 : const bool bTextEdit = mpView->IsTextEdit();
1241 :
1242 0 : sal_uInt16 nAction = ACTION_HANDLED_BY_VIEW;
1243 :
1244 0 : ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1245 0 : if( !pTableObj )
1246 0 : return nAction;
1247 :
1248 : // handle special keys
1249 0 : const sal_Int16 nCode = rKEvt.GetKeyCode().GetCode();
1250 0 : switch( nCode )
1251 : {
1252 : case awt::Key::ESCAPE: // handle escape
1253 : {
1254 0 : if( bTextEdit )
1255 : {
1256 : // escape during text edit ends text edit
1257 0 : nAction = ACTION_STOP_TEXT_EDIT;
1258 : }
1259 0 : if( mbCellSelectionMode )
1260 : {
1261 : // escape with selected cells removes selection
1262 0 : nAction = ACTION_REMOVE_SELECTION;
1263 : }
1264 0 : break;
1265 : }
1266 : case awt::Key::RETURN: // handle return
1267 : {
1268 0 : if( !bMod1 && !bMod2 && !bTextEdit )
1269 : {
1270 : // when not already editing, return starts text edit
1271 0 : setSelectionStart( pTableObj->getFirstCell() );
1272 0 : nAction = ACTION_EDIT_CELL;
1273 : }
1274 0 : break;
1275 : }
1276 : case awt::Key::F2: // f2 toggles text edit
1277 : {
1278 0 : if( bMod1 || bMod2 ) // f2 with modifiers is handled by the view
1279 : {
1280 : }
1281 0 : else if( bTextEdit )
1282 : {
1283 : // f2 during text edit stops text edit
1284 0 : nAction = ACTION_STOP_TEXT_EDIT;
1285 : }
1286 0 : else if( mbCellSelectionMode )
1287 : {
1288 : // f2 with selected cells removes selection
1289 0 : nAction = ACTION_REMOVE_SELECTION;
1290 : }
1291 : else
1292 : {
1293 : // f2 with no selection and no text edit starts text edit
1294 0 : setSelectionStart( pTableObj->getFirstCell() );
1295 0 : nAction = ACTION_EDIT_CELL;
1296 : }
1297 0 : break;
1298 : }
1299 : case awt::Key::HOME:
1300 : case awt::Key::NUM7:
1301 : {
1302 0 : if( (bMod1 || bMod2) && (bTextEdit || mbCellSelectionMode) )
1303 : {
1304 0 : if( bMod1 && !bMod2 )
1305 : {
1306 : // ctrl + home jumps to first cell
1307 0 : nAction = ACTION_GOTO_FIRST_CELL;
1308 : }
1309 0 : else if( !bMod1 && bMod2 )
1310 : {
1311 : // alt + home jumps to first column
1312 0 : nAction = ACTION_GOTO_FIRST_COLUMN;
1313 : }
1314 : }
1315 0 : break;
1316 : }
1317 : case awt::Key::END:
1318 : case awt::Key::NUM1:
1319 : {
1320 0 : if( (bMod1 || bMod2) && (bTextEdit || mbCellSelectionMode) )
1321 : {
1322 0 : if( bMod1 && !bMod2 )
1323 : {
1324 : // ctrl + end jumps to last cell
1325 0 : nAction = ACTION_GOTO_LAST_CELL;
1326 : }
1327 0 : else if( !bMod1 && bMod2 )
1328 : {
1329 : // alt + home jumps to last column
1330 0 : nAction = ACTION_GOTO_LAST_COLUMN;
1331 : }
1332 : }
1333 0 : break;
1334 : }
1335 :
1336 : case awt::Key::TAB:
1337 : {
1338 0 : if( bTextEdit || mbCellSelectionMode )
1339 0 : nAction = ACTION_TAB;
1340 0 : break;
1341 : }
1342 :
1343 : case awt::Key::UP:
1344 : case awt::Key::NUM8:
1345 : case awt::Key::DOWN:
1346 : case awt::Key::NUM2:
1347 : case awt::Key::LEFT:
1348 : case awt::Key::NUM4:
1349 : case awt::Key::RIGHT:
1350 : case awt::Key::NUM6:
1351 : {
1352 0 : bool bTextMove = false;
1353 :
1354 0 : if( !bMod1 && bMod2 )
1355 : {
1356 0 : if( (nCode == awt::Key::UP) || (nCode == awt::Key::NUM8) )
1357 : {
1358 0 : nAction = ACTION_GOTO_LEFT_CELL;
1359 : }
1360 0 : else if( (nCode == awt::Key::DOWN) || (nCode == awt::Key::NUM2) )
1361 : {
1362 0 : nAction = ACTION_GOTO_RIGHT_CELL;
1363 : }
1364 0 : break;
1365 : }
1366 :
1367 0 : if( !bTextMove )
1368 : {
1369 0 : OutlinerView* pOLV = mpView->GetTextEditOutlinerView();
1370 0 : if( pOLV )
1371 : {
1372 0 : RemoveSelection();
1373 : // during text edit, check if we navigate out of the cell
1374 0 : ESelection aOldSelection = pOLV->GetSelection();
1375 0 : pOLV->PostKeyEvent(rKEvt);
1376 0 : bTextMove = pOLV && ( aOldSelection.IsEqual(pOLV->GetSelection()) );
1377 0 : if( !bTextMove )
1378 : {
1379 0 : nAction = ACTION_NONE;
1380 : }
1381 : }
1382 : }
1383 :
1384 0 : if( mbCellSelectionMode || bTextMove )
1385 : {
1386 : // no text edit, navigate in cells if selection active
1387 0 : switch( nCode )
1388 : {
1389 : case awt::Key::LEFT:
1390 : case awt::Key::NUM4:
1391 0 : nAction = ACTION_GOTO_LEFT_CELL;
1392 0 : break;
1393 : case awt::Key::RIGHT:
1394 : case awt::Key::NUM6:
1395 0 : nAction = ACTION_GOTO_RIGHT_CELL;
1396 0 : break;
1397 : case awt::Key::DOWN:
1398 : case awt::Key::NUM2:
1399 0 : nAction = ACTION_GOTO_DOWN_CELL;
1400 0 : break;
1401 : case awt::Key::UP:
1402 : case awt::Key::NUM8:
1403 0 : nAction = ACTION_GOTO_UP_CELL;
1404 0 : break;
1405 : }
1406 : }
1407 0 : break;
1408 : }
1409 : case awt::Key::PAGEUP:
1410 0 : if( bMod2 )
1411 0 : nAction = ACTION_GOTO_FIRST_ROW;
1412 0 : break;
1413 :
1414 : case awt::Key::PAGEDOWN:
1415 0 : if( bMod2 )
1416 0 : nAction = ACTION_GOTO_LAST_ROW;
1417 0 : break;
1418 : }
1419 0 : return nAction;
1420 : }
1421 :
1422 0 : bool SvxTableController::executeAction( sal_uInt16 nAction, bool bSelect, Window* pWindow )
1423 : {
1424 0 : ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1425 0 : if( !pTableObj )
1426 0 : return false;
1427 :
1428 0 : switch( nAction )
1429 : {
1430 : case ACTION_GOTO_FIRST_CELL:
1431 : {
1432 0 : gotoCell( pTableObj->getFirstCell(), bSelect, pWindow, nAction );
1433 0 : break;
1434 : }
1435 :
1436 : case ACTION_GOTO_LEFT_CELL:
1437 : {
1438 0 : gotoCell( pTableObj->getLeftCell( getSelectionEnd(), !bSelect ), bSelect, pWindow, nAction );
1439 0 : break;
1440 : }
1441 :
1442 : case ACTION_GOTO_RIGHT_CELL:
1443 : {
1444 0 : gotoCell( pTableObj->getRightCell( getSelectionEnd(), !bSelect ), bSelect, pWindow, nAction);
1445 0 : break;
1446 : }
1447 :
1448 : case ACTION_GOTO_LAST_CELL:
1449 : {
1450 0 : gotoCell( pTableObj->getLastCell(), bSelect, pWindow, nAction );
1451 0 : break;
1452 : }
1453 :
1454 : case ACTION_GOTO_FIRST_COLUMN:
1455 : {
1456 0 : CellPos aPos( pTableObj->getFirstCell().mnCol, getSelectionEnd().mnRow );
1457 0 : gotoCell( aPos, bSelect, pWindow, nAction );
1458 0 : break;
1459 : }
1460 :
1461 : case ACTION_GOTO_LAST_COLUMN:
1462 : {
1463 0 : CellPos aPos( pTableObj->getLastCell().mnCol, getSelectionEnd().mnRow );
1464 0 : gotoCell( aPos, bSelect, pWindow, nAction );
1465 0 : break;
1466 : }
1467 :
1468 : case ACTION_GOTO_FIRST_ROW:
1469 : {
1470 0 : CellPos aPos( getSelectionEnd().mnCol, pTableObj->getFirstCell().mnRow );
1471 0 : gotoCell( aPos, bSelect, pWindow, nAction );
1472 0 : break;
1473 : }
1474 :
1475 : case ACTION_GOTO_UP_CELL:
1476 : {
1477 0 : gotoCell( pTableObj->getUpCell(getSelectionEnd(), !bSelect), bSelect, pWindow, nAction );
1478 0 : break;
1479 : }
1480 :
1481 : case ACTION_GOTO_DOWN_CELL:
1482 : {
1483 0 : gotoCell( pTableObj->getDownCell(getSelectionEnd(), !bSelect), bSelect, pWindow, nAction );
1484 0 : break;
1485 : }
1486 :
1487 : case ACTION_GOTO_LAST_ROW:
1488 : {
1489 0 : CellPos aPos( getSelectionEnd().mnCol, pTableObj->getLastCell().mnRow );
1490 0 : gotoCell( aPos, bSelect, pWindow, nAction );
1491 0 : break;
1492 : }
1493 :
1494 : case ACTION_EDIT_CELL:
1495 0 : EditCell( getSelectionStart(), pWindow, 0, nAction );
1496 0 : break;
1497 :
1498 : case ACTION_STOP_TEXT_EDIT:
1499 0 : StopTextEdit();
1500 0 : break;
1501 :
1502 : case ACTION_REMOVE_SELECTION:
1503 0 : RemoveSelection();
1504 0 : break;
1505 :
1506 : case ACTION_START_SELECTION:
1507 0 : StartSelection( getSelectionStart() );
1508 0 : break;
1509 :
1510 : case ACTION_TAB:
1511 : {
1512 0 : if( bSelect )
1513 0 : gotoCell( pTableObj->getPreviousCell( getSelectionEnd(), true ), false, pWindow, nAction );
1514 : else
1515 : {
1516 0 : CellPos aSelectionEnd( getSelectionEnd() );
1517 0 : CellPos aNextCell( pTableObj->getNextCell( aSelectionEnd, true ) );
1518 0 : if( aSelectionEnd == aNextCell )
1519 : {
1520 0 : onInsert( SID_TABLE_INSERT_ROW, 0 );
1521 0 : aNextCell = pTableObj->getNextCell( aSelectionEnd, true );
1522 : }
1523 0 : gotoCell( aNextCell, false, pWindow, nAction );
1524 : }
1525 0 : break;
1526 : }
1527 : }
1528 :
1529 0 : return nAction != ACTION_HANDLED_BY_VIEW;
1530 : }
1531 :
1532 : // --------------------------------------------------------------------
1533 :
1534 0 : void SvxTableController::gotoCell( const CellPos& rPos, bool bSelect, Window* pWindow, sal_uInt16 nAction )
1535 : {
1536 0 : if( mxTableObj.is() && static_cast<SdrTableObj*>(mxTableObj.get())->IsTextEditActive() )
1537 0 : mpView->SdrEndTextEdit(sal_True);
1538 :
1539 0 : if( bSelect )
1540 : {
1541 0 : maCursorLastPos = rPos;
1542 0 : if( mxTableObj.is() )
1543 0 : static_cast< SdrTableObj* >( mxTableObj.get() )->setActiveCell( rPos );
1544 :
1545 0 : if( !mbCellSelectionMode )
1546 : {
1547 0 : setSelectedCells( maCursorFirstPos, rPos );
1548 : }
1549 : else
1550 : {
1551 0 : UpdateSelection( rPos );
1552 : }
1553 : }
1554 : else
1555 : {
1556 0 : RemoveSelection();
1557 0 : EditCell( rPos, pWindow, 0, nAction );
1558 : }
1559 0 : }
1560 :
1561 : // --------------------------------------------------------------------
1562 :
1563 0 : const CellPos& SvxTableController::getSelectionStart()
1564 : {
1565 0 : checkCell( maCursorFirstPos );
1566 0 : return maCursorFirstPos;
1567 : }
1568 :
1569 : // --------------------------------------------------------------------
1570 :
1571 0 : void SvxTableController::setSelectionStart( const CellPos& rPos )
1572 : {
1573 0 : maCursorFirstPos = rPos;
1574 0 : }
1575 :
1576 : // --------------------------------------------------------------------
1577 :
1578 0 : const CellPos& SvxTableController::getSelectionEnd()
1579 : {
1580 0 : checkCell( maCursorLastPos );
1581 0 : return maCursorLastPos;
1582 : }
1583 :
1584 : // --------------------------------------------------------------------
1585 :
1586 0 : void SvxTableController::MergeRange( sal_Int32 nFirstCol, sal_Int32 nFirstRow, sal_Int32 nLastCol, sal_Int32 nLastRow )
1587 : {
1588 0 : if( mxTable.is() ) try
1589 : {
1590 0 : Reference< XMergeableCellRange > xRange( mxTable->createCursorByRange( mxTable->getCellRangeByPosition( nFirstCol, nFirstRow,nLastCol, nLastRow ) ), UNO_QUERY_THROW );
1591 0 : if( xRange->isMergeable() )
1592 : {
1593 0 : const bool bUndo = mpModel && mpModel->IsUndoEnabled();
1594 0 : if( bUndo )
1595 : {
1596 0 : mpModel->BegUndo( ImpGetResStr(STR_TABLE_MERGE) );
1597 0 : mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*mxTableObj.get()) );
1598 : }
1599 :
1600 0 : xRange->merge();
1601 :
1602 0 : if( bUndo )
1603 0 : mpModel->EndUndo();
1604 0 : }
1605 : }
1606 0 : catch( Exception& )
1607 : {
1608 : DBG_ASSERT( false, "sdr::table::SvxTableController::MergeRange(), exception caught!" );
1609 : }
1610 0 : }
1611 :
1612 :
1613 :
1614 : // --------------------------------------------------------------------
1615 :
1616 0 : void SvxTableController::checkCell( CellPos& rPos )
1617 : {
1618 0 : if( mxTable.is() ) try
1619 : {
1620 0 : if( rPos.mnCol >= mxTable->getColumnCount() )
1621 0 : rPos.mnCol = mxTable->getColumnCount()-1;
1622 :
1623 0 : if( rPos.mnRow >= mxTable->getRowCount() )
1624 0 : rPos.mnRow = mxTable->getRowCount()-1;
1625 : }
1626 0 : catch( Exception& )
1627 : {
1628 : OSL_FAIL("sdr::table::SvxTableController::checkCell(), exception caught!" );
1629 : }
1630 0 : }
1631 :
1632 : // --------------------------------------------------------------------
1633 :
1634 0 : void SvxTableController::findMergeOrigin( CellPos& rPos )
1635 : {
1636 0 : if( mxTable.is() ) try
1637 : {
1638 0 : Reference< XMergeableCell > xCell( mxTable->getCellByPosition( rPos.mnCol, rPos.mnRow ), UNO_QUERY_THROW );
1639 0 : if( xCell.is() && xCell->isMerged() )
1640 : {
1641 0 : ::findMergeOrigin( mxTable, rPos.mnCol, rPos.mnRow, rPos.mnCol, rPos.mnRow );
1642 0 : }
1643 : }
1644 0 : catch( Exception& )
1645 : {
1646 : OSL_FAIL("sdr::table::SvxTableController::findMergeOrigin(), exception caught!" );
1647 : }
1648 0 : }
1649 :
1650 : // --------------------------------------------------------------------
1651 :
1652 0 : void SvxTableController::EditCell( const CellPos& rPos, ::Window* pWindow, const awt::MouseEvent* pMouseEvent /*= 0*/, sal_uInt16 nAction /*= ACTION_NONE */ )
1653 : {
1654 0 : SdrPageView* pPV = mpView->GetSdrPageView();
1655 :
1656 0 : ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1657 0 : if( pTableObj && pTableObj->GetPage() == pPV->GetPage() )
1658 : {
1659 0 : bool bEmptyOutliner = false;
1660 :
1661 0 : if(!pTableObj->GetOutlinerParaObject() && mpView->GetTextEditOutliner())
1662 : {
1663 0 : ::Outliner* pOutl = mpView->GetTextEditOutliner();
1664 0 : sal_Int32 nParaAnz = pOutl->GetParagraphCount();
1665 0 : Paragraph* p1stPara = pOutl->GetParagraph( 0 );
1666 :
1667 0 : if(nParaAnz==1 && p1stPara)
1668 : {
1669 : // Bei nur einem Pararaph
1670 0 : if (pOutl->GetText(p1stPara).Len() == 0)
1671 : {
1672 0 : bEmptyOutliner = true;
1673 : }
1674 : }
1675 : }
1676 :
1677 0 : CellPos aPos( rPos );
1678 0 : findMergeOrigin( aPos );
1679 :
1680 0 : if( pTableObj != mpView->GetTextEditObject() || bEmptyOutliner || !pTableObj->IsTextEditActive( aPos ) )
1681 : {
1682 0 : if( pTableObj->IsTextEditActive() )
1683 0 : mpView->SdrEndTextEdit(sal_True);
1684 :
1685 0 : pTableObj->setActiveCell( aPos );
1686 :
1687 : // create new outliner, owner will be the SdrObjEditView
1688 0 : SdrOutliner* pOutl = SdrMakeOutliner( OUTLINERMODE_OUTLINEOBJECT, mpModel );
1689 0 : if( pTableObj->IsVerticalWriting() )
1690 0 : pOutl->SetVertical( sal_True );
1691 :
1692 0 : if(mpView->SdrBeginTextEdit(pTableObj, pPV, pWindow, sal_True, pOutl))
1693 : {
1694 0 : maCursorLastPos = maCursorFirstPos = rPos;
1695 :
1696 0 : OutlinerView* pOLV = mpView->GetTextEditOutlinerView();
1697 :
1698 0 : bool bNoSel = true;
1699 :
1700 0 : if( pMouseEvent )
1701 : {
1702 0 : ::MouseEvent aMEvt( *pMouseEvent );
1703 :
1704 0 : SdrViewEvent aVEvt;
1705 0 : SdrHitKind eHit = mpView->PickAnything(aMEvt, SDRMOUSEBUTTONDOWN, aVEvt);
1706 :
1707 0 : if (eHit == SDRHIT_TEXTEDIT)
1708 : {
1709 : // Text getroffen
1710 0 : pOLV->MouseButtonDown(aMEvt);
1711 0 : pOLV->MouseMove(aMEvt);
1712 0 : pOLV->MouseButtonUp(aMEvt);
1713 : // pOLV->MouseButtonDown(aMEvt);
1714 0 : bNoSel = false;
1715 : }
1716 : else
1717 : {
1718 0 : nAction = ACTION_GOTO_LEFT_CELL;
1719 0 : }
1720 : }
1721 :
1722 0 : if( bNoSel )
1723 : {
1724 : // Move cursor to end of text
1725 0 : ESelection aNewSelection;
1726 :
1727 0 : const WritingMode eMode = pTableObj->GetWritingMode();
1728 0 : if( ((nAction == ACTION_GOTO_LEFT_CELL) || (nAction == ACTION_GOTO_RIGHT_CELL)) && (eMode != WritingMode_TB_RL) )
1729 : {
1730 0 : const bool bLast = ((nAction == ACTION_GOTO_LEFT_CELL) && (eMode == WritingMode_LR_TB)) ||
1731 0 : ((nAction == ACTION_GOTO_RIGHT_CELL) && (eMode == WritingMode_RL_TB));
1732 :
1733 0 : if( bLast )
1734 0 : aNewSelection = ESelection(EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND, EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND);
1735 : }
1736 0 : pOLV->SetSelection(aNewSelection);
1737 : }
1738 : }
1739 : }
1740 : }
1741 0 : }
1742 :
1743 : // --------------------------------------------------------------------
1744 :
1745 0 : bool SvxTableController::StopTextEdit()
1746 : {
1747 0 : if(mpView->IsTextEdit())
1748 : {
1749 0 : mpView->SdrEndTextEdit();
1750 0 : mpView->SetCurrentObj(OBJ_TABLE);
1751 0 : mpView->SetEditMode(SDREDITMODE_EDIT);
1752 0 : return true;
1753 : }
1754 : else
1755 : {
1756 0 : return false;
1757 : }
1758 : }
1759 :
1760 : // --------------------------------------------------------------------
1761 :
1762 0 : void SvxTableController::getSelectedCells( CellPos& rFirst, CellPos& rLast )
1763 : {
1764 0 : if( mbCellSelectionMode )
1765 : {
1766 0 : checkCell( maCursorFirstPos );
1767 0 : checkCell( maCursorLastPos );
1768 :
1769 0 : rFirst.mnCol = std::min( maCursorFirstPos.mnCol, maCursorLastPos.mnCol );
1770 0 : rFirst.mnRow = std::min( maCursorFirstPos.mnRow, maCursorLastPos.mnRow );
1771 0 : rLast.mnCol = std::max( maCursorFirstPos.mnCol, maCursorLastPos.mnCol );
1772 0 : rLast.mnRow = std::max( maCursorFirstPos.mnRow, maCursorLastPos.mnRow );
1773 :
1774 0 : bool bExt = false;
1775 0 : if( mxTable.is() ) do
1776 : {
1777 0 : bExt = false;
1778 0 : for( sal_Int32 nRow = rFirst.mnRow; nRow <= rLast.mnRow && !bExt; nRow++ )
1779 : {
1780 0 : for( sal_Int32 nCol = rFirst.mnCol; nCol <= rLast.mnCol && !bExt; nCol++ )
1781 : {
1782 0 : Reference< XMergeableCell > xCell( mxTable->getCellByPosition( nCol, nRow ), UNO_QUERY );
1783 0 : if( !xCell.is() )
1784 0 : continue;
1785 :
1786 0 : if( xCell->isMerged() )
1787 : {
1788 0 : CellPos aPos( nCol, nRow );
1789 0 : findMergeOrigin( aPos );
1790 0 : if( (aPos.mnCol < rFirst.mnCol) || (aPos.mnRow < rFirst.mnRow) )
1791 : {
1792 0 : rFirst.mnCol = std::min( rFirst.mnCol, aPos.mnCol );
1793 0 : rFirst.mnRow = std::min( rFirst.mnRow, aPos.mnRow );
1794 0 : bExt = true;
1795 : }
1796 : }
1797 : else
1798 : {
1799 0 : if( ((nCol + xCell->getColumnSpan() - 1) > rLast.mnCol) || (nRow + xCell->getRowSpan() - 1 ) > rLast.mnRow )
1800 : {
1801 0 : rLast.mnCol = std::max( rLast.mnCol, nCol + xCell->getColumnSpan() - 1 );
1802 0 : rLast.mnRow = std::max( rLast.mnRow, nRow + xCell->getRowSpan() - 1 );
1803 0 : bExt = true;
1804 : }
1805 : }
1806 0 : }
1807 : }
1808 : }
1809 : while(bExt);
1810 : }
1811 0 : else if( mpView && mpView->IsTextEdit() )
1812 : {
1813 0 : rFirst = getSelectionStart();
1814 0 : findMergeOrigin( rFirst );
1815 0 : rLast = rFirst;
1816 :
1817 0 : if( mxTable.is() )
1818 : {
1819 0 : Reference< XMergeableCell > xCell( mxTable->getCellByPosition( rLast.mnCol, rLast.mnRow ), UNO_QUERY );
1820 0 : if( xCell.is() )
1821 : {
1822 0 : rLast.mnCol += xCell->getColumnSpan() - 1;
1823 0 : rLast.mnRow += xCell->getRowSpan() - 1;
1824 0 : }
1825 : }
1826 : }
1827 : else
1828 : {
1829 0 : rFirst.mnCol = 0;
1830 0 : rFirst.mnRow = 0;
1831 0 : if( mxTable.is() )
1832 : {
1833 0 : rLast.mnRow = mxTable->getRowCount()-1;
1834 0 : rLast.mnCol = mxTable->getColumnCount()-1;
1835 : }
1836 : else
1837 : {
1838 0 : rLast.mnRow = 0;
1839 0 : rLast.mnCol = 0;
1840 : }
1841 : }
1842 0 : }
1843 :
1844 : // --------------------------------------------------------------------
1845 :
1846 0 : void SvxTableController::StartSelection( const CellPos& rPos )
1847 : {
1848 0 : StopTextEdit();
1849 0 : mbCellSelectionMode = true;
1850 0 : maCursorLastPos = maCursorFirstPos = rPos;
1851 0 : mpView->MarkListHasChanged();
1852 0 : }
1853 :
1854 : // --------------------------------------------------------------------
1855 :
1856 0 : void SvxTableController::setSelectedCells( const CellPos& rStart, const CellPos& rEnd )
1857 : {
1858 0 : StopTextEdit();
1859 0 : mbCellSelectionMode = true;
1860 0 : maCursorFirstPos = rStart;
1861 0 : UpdateSelection( rEnd );
1862 0 : }
1863 :
1864 : // --------------------------------------------------------------------
1865 :
1866 0 : void SvxTableController::UpdateSelection( const CellPos& rPos )
1867 : {
1868 0 : maCursorLastPos = rPos;
1869 0 : mpView->MarkListHasChanged();
1870 0 : }
1871 :
1872 : // --------------------------------------------------------------------
1873 :
1874 0 : void SvxTableController::clearSelection()
1875 : {
1876 0 : RemoveSelection();
1877 0 : }
1878 :
1879 : // --------------------------------------------------------------------
1880 :
1881 0 : void SvxTableController::selectAll()
1882 : {
1883 0 : if( mxTable.is() )
1884 : {
1885 0 : CellPos aPos1, aPos2( mxTable->getColumnCount()-1, mxTable->getRowCount()-1 );
1886 0 : if( (aPos2.mnCol >= 0) && (aPos2.mnRow >= 0) )
1887 : {
1888 0 : setSelectedCells( aPos1, aPos2 );
1889 : }
1890 : }
1891 0 : }
1892 :
1893 : // --------------------------------------------------------------------
1894 :
1895 0 : void SvxTableController::RemoveSelection()
1896 : {
1897 0 : if( mbCellSelectionMode )
1898 : {
1899 0 : mbCellSelectionMode = false;
1900 0 : mpView->MarkListHasChanged();
1901 : }
1902 0 : }
1903 :
1904 : // --------------------------------------------------------------------
1905 :
1906 0 : void SvxTableController::onTableModified()
1907 : {
1908 0 : if( mnUpdateEvent == 0 )
1909 0 : mnUpdateEvent = Application::PostUserEvent( LINK( this, SvxTableController, UpdateHdl ) );
1910 0 : }
1911 : // --------------------------------------------------------------------
1912 :
1913 0 : void SvxTableController::updateSelectionOverlay()
1914 : {
1915 0 : destroySelectionOverlay();
1916 0 : if( mbCellSelectionMode )
1917 : {
1918 0 : ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1919 0 : if( pTableObj )
1920 : {
1921 0 : sdr::overlay::OverlayObjectCell::RangeVector aRanges;
1922 :
1923 0 : Rectangle aRect;
1924 0 : CellPos aStart,aEnd;
1925 0 : getSelectedCells( aStart, aEnd );
1926 0 : pTableObj->getCellBounds( aStart, aRect );
1927 :
1928 0 : basegfx::B2DRange a2DRange( basegfx::B2DPoint(aRect.Left(), aRect.Top()) );
1929 0 : a2DRange.expand( basegfx::B2DPoint(aRect.Right(), aRect.Bottom()) );
1930 :
1931 0 : findMergeOrigin( aEnd );
1932 0 : pTableObj->getCellBounds( aEnd, aRect );
1933 0 : a2DRange.expand( basegfx::B2DPoint(aRect.Left(), aRect.Top()) );
1934 0 : a2DRange.expand( basegfx::B2DPoint(aRect.Right(), aRect.Bottom()) );
1935 0 : aRanges.push_back( a2DRange );
1936 :
1937 0 : ::Color aHighlight( COL_BLUE );
1938 0 : OutputDevice* pOutDev = mpView->GetFirstOutputDevice();
1939 0 : if( pOutDev )
1940 0 : aHighlight = pOutDev->GetSettings().GetStyleSettings().GetHighlightColor();
1941 :
1942 0 : const sal_uInt32 nCount = mpView->PaintWindowCount();
1943 0 : for( sal_uInt32 nIndex = 0; nIndex < nCount; nIndex++ )
1944 : {
1945 0 : SdrPaintWindow* pPaintWindow = mpView->GetPaintWindow(nIndex);
1946 0 : if( pPaintWindow )
1947 : {
1948 0 : rtl::Reference < ::sdr::overlay::OverlayManager > xOverlayManager = pPaintWindow->GetOverlayManager();
1949 0 : if( xOverlayManager.is() )
1950 : {
1951 : // sdr::overlay::CellOverlayType eType = sdr::overlay::CELL_OVERLAY_INVERT;
1952 0 : sdr::overlay::CellOverlayType eType = sdr::overlay::CELL_OVERLAY_TRANSPARENT;
1953 :
1954 0 : sdr::overlay::OverlayObjectCell* pOverlay = new sdr::overlay::OverlayObjectCell( eType, aHighlight, aRanges );
1955 :
1956 0 : xOverlayManager->add(*pOverlay);
1957 0 : mpSelectionOverlay = new ::sdr::overlay::OverlayObjectList;
1958 0 : mpSelectionOverlay->append(*pOverlay);
1959 0 : }
1960 : }
1961 0 : }
1962 : }
1963 : }
1964 0 : }
1965 :
1966 : // --------------------------------------------------------------------
1967 :
1968 0 : void SvxTableController::destroySelectionOverlay()
1969 : {
1970 0 : if( mpSelectionOverlay )
1971 : {
1972 0 : delete mpSelectionOverlay;
1973 0 : mpSelectionOverlay = 0;
1974 : }
1975 0 : }
1976 :
1977 : // --------------------------------------------------------------------
1978 :
1979 0 : void SvxTableController::MergeAttrFromSelectedCells(SfxItemSet& rAttr, bool bOnlyHardAttr) const
1980 : {
1981 0 : if( mxTable.is() )
1982 : {
1983 0 : CellPos aStart, aEnd;
1984 0 : const_cast<SvxTableController&>(*this).getSelectedCells( aStart, aEnd );
1985 :
1986 0 : for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
1987 : {
1988 0 : for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
1989 : {
1990 0 : CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
1991 0 : if( xCell.is() && !xCell->isMerged() )
1992 : {
1993 0 : const SfxItemSet& rSet = xCell->GetItemSet();
1994 0 : SfxWhichIter aIter(rSet);
1995 0 : sal_uInt16 nWhich(aIter.FirstWhich());
1996 0 : while(nWhich)
1997 : {
1998 0 : if(!bOnlyHardAttr)
1999 : {
2000 0 : if(SFX_ITEM_DONTCARE == rSet.GetItemState(nWhich, sal_False))
2001 0 : rAttr.InvalidateItem(nWhich);
2002 : else
2003 0 : rAttr.MergeValue(rSet.Get(nWhich), sal_True);
2004 : }
2005 0 : else if(SFX_ITEM_SET == rSet.GetItemState(nWhich, sal_False))
2006 : {
2007 0 : const SfxPoolItem& rItem = rSet.Get(nWhich);
2008 0 : rAttr.MergeValue(rItem, sal_True);
2009 : }
2010 :
2011 0 : nWhich = aIter.NextWhich();
2012 0 : }
2013 : }
2014 0 : }
2015 : }
2016 : }
2017 0 : }
2018 :
2019 : // --------------------------------------------------------------------
2020 :
2021 : const sal_uInt16 CELL_BEFORE = 0x0001;
2022 : const sal_uInt16 CELL_LEFT = 0x0002;
2023 : const sal_uInt16 CELL_RIGHT = 0x0004;
2024 : const sal_uInt16 CELL_AFTER = 0x0008;
2025 :
2026 : const sal_uInt16 CELL_UPPER = 0x0010;
2027 : const sal_uInt16 CELL_TOP = 0x0020;
2028 : const sal_uInt16 CELL_BOTTOM = 0x0040;
2029 : const sal_uInt16 CELL_LOWER = 0x0080;
2030 :
2031 : // --------------------------------------------------------------------
2032 :
2033 0 : static void ImplSetLinePreserveColor( SvxBoxItem& rNewFrame, const SvxBorderLine* pNew, sal_uInt16 nLine )
2034 : {
2035 0 : if( pNew )
2036 : {
2037 0 : const SvxBorderLine* pOld = rNewFrame.GetLine(nLine);
2038 0 : if( pOld )
2039 : {
2040 0 : SvxBorderLine aNewLine( *pNew );
2041 0 : aNewLine.SetColor( pOld->GetColor() );
2042 0 : rNewFrame.SetLine( &aNewLine, nLine );
2043 0 : return;
2044 : }
2045 : }
2046 0 : rNewFrame.SetLine( pNew, nLine );
2047 : }
2048 :
2049 : // --------------------------------------------------------------------
2050 :
2051 0 : static void ImplApplyBoxItem( sal_uInt16 nCellFlags, const SvxBoxItem* pBoxItem, const SvxBoxInfoItem* pBoxInfoItem, SvxBoxItem& rNewFrame )
2052 : {
2053 0 : if( (nCellFlags & (CELL_BEFORE|CELL_AFTER|CELL_UPPER|CELL_LOWER)) != 0 )
2054 : {
2055 : // current cell is outside the selection
2056 :
2057 0 : if( (nCellFlags & ( CELL_BEFORE|CELL_AFTER)) == 0 ) // check if its not nw or ne corner
2058 : {
2059 0 : if( nCellFlags & CELL_UPPER )
2060 : {
2061 0 : if( pBoxInfoItem->IsValid(VALID_TOP) )
2062 0 : rNewFrame.SetLine(0, BOX_LINE_BOTTOM );
2063 : }
2064 0 : else if( nCellFlags & CELL_LOWER )
2065 : {
2066 0 : if( pBoxInfoItem->IsValid(VALID_BOTTOM) )
2067 0 : rNewFrame.SetLine( 0, BOX_LINE_TOP );
2068 : }
2069 : }
2070 0 : else if( (nCellFlags & ( CELL_UPPER|CELL_LOWER)) == 0 ) // check if its not sw or se corner
2071 : {
2072 0 : if( nCellFlags & CELL_BEFORE )
2073 : {
2074 0 : if( pBoxInfoItem->IsValid(VALID_LEFT) )
2075 0 : rNewFrame.SetLine( 0, BOX_LINE_RIGHT );
2076 : }
2077 0 : else if( nCellFlags & CELL_AFTER )
2078 : {
2079 0 : if( pBoxInfoItem->IsValid(VALID_RIGHT) )
2080 0 : rNewFrame.SetLine( 0, BOX_LINE_LEFT );
2081 : }
2082 : }
2083 : }
2084 : else
2085 : {
2086 : // current cell is inside the selection
2087 :
2088 0 : if( (nCellFlags & CELL_LEFT) ? pBoxInfoItem->IsValid(VALID_LEFT) : pBoxInfoItem->IsValid(VALID_VERT) )
2089 0 : rNewFrame.SetLine( (nCellFlags & CELL_LEFT) ? pBoxItem->GetLeft() : pBoxInfoItem->GetVert(), BOX_LINE_LEFT );
2090 :
2091 0 : if( (nCellFlags & CELL_RIGHT) ? pBoxInfoItem->IsValid(VALID_RIGHT) : pBoxInfoItem->IsValid(VALID_VERT) )
2092 0 : rNewFrame.SetLine( (nCellFlags & CELL_RIGHT) ? pBoxItem->GetRight() : pBoxInfoItem->GetVert(), BOX_LINE_RIGHT );
2093 :
2094 0 : if( (nCellFlags & CELL_TOP) ? pBoxInfoItem->IsValid(VALID_TOP) : pBoxInfoItem->IsValid(VALID_HORI) )
2095 0 : rNewFrame.SetLine( (nCellFlags & CELL_TOP) ? pBoxItem->GetTop() : pBoxInfoItem->GetHori(), BOX_LINE_TOP );
2096 :
2097 0 : if( (nCellFlags & CELL_BOTTOM) ? pBoxInfoItem->IsValid(VALID_BOTTOM) : pBoxInfoItem->IsValid(VALID_HORI) )
2098 0 : rNewFrame.SetLine( (nCellFlags & CELL_BOTTOM) ? pBoxItem->GetBottom() : pBoxInfoItem->GetHori(), BOX_LINE_BOTTOM );
2099 :
2100 : // apply distance to borders
2101 0 : if( pBoxInfoItem->IsValid( VALID_DISTANCE ) )
2102 0 : for( sal_uInt16 nLine = 0; nLine < 4; ++nLine )
2103 0 : rNewFrame.SetDistance( pBoxItem->GetDistance( nLine ), nLine );
2104 : }
2105 0 : }
2106 :
2107 : // --------------------------------------------------------------------
2108 :
2109 0 : static void ImplSetLineColor( SvxBoxItem& rNewFrame, sal_uInt16 nLine, const Color& rColor )
2110 : {
2111 0 : const SvxBorderLine* pSourceLine = rNewFrame.GetLine( nLine );
2112 0 : if( pSourceLine )
2113 : {
2114 0 : SvxBorderLine aLine( *pSourceLine );
2115 0 : aLine.SetColor( rColor );
2116 0 : rNewFrame.SetLine( &aLine, nLine );
2117 : }
2118 0 : }
2119 :
2120 : // --------------------------------------------------------------------
2121 :
2122 0 : static void ImplApplyLineColorItem( sal_uInt16 nCellFlags, const SvxColorItem* pLineColorItem, SvxBoxItem& rNewFrame )
2123 : {
2124 0 : const Color aColor( pLineColorItem->GetValue() );
2125 :
2126 0 : if( (nCellFlags & (CELL_LOWER|CELL_BEFORE|CELL_AFTER)) == 0 )
2127 0 : ImplSetLineColor( rNewFrame, BOX_LINE_BOTTOM, aColor );
2128 :
2129 0 : if( (nCellFlags & (CELL_UPPER|CELL_BEFORE|CELL_AFTER)) == 0 )
2130 0 : ImplSetLineColor( rNewFrame, BOX_LINE_TOP, aColor );
2131 :
2132 0 : if( (nCellFlags & (CELL_UPPER|CELL_LOWER|CELL_AFTER)) == 0 )
2133 0 : ImplSetLineColor( rNewFrame, BOX_LINE_RIGHT, aColor );
2134 :
2135 0 : if( (nCellFlags & (CELL_UPPER|CELL_LOWER|CELL_BEFORE)) == 0 )
2136 0 : ImplSetLineColor( rNewFrame, BOX_LINE_LEFT, aColor );
2137 0 : }
2138 :
2139 : // --------------------------------------------------------------------
2140 :
2141 0 : static void ImplApplyBorderLineItem( sal_uInt16 nCellFlags, const SvxBorderLine* pBorderLineItem, SvxBoxItem& rNewFrame )
2142 : {
2143 0 : if( (nCellFlags & ( CELL_BEFORE|CELL_AFTER|CELL_UPPER|CELL_LOWER)) != 0 )
2144 : {
2145 0 : if( (nCellFlags & ( CELL_BEFORE|CELL_AFTER)) == 0 ) // check if its not nw or ne corner
2146 : {
2147 0 : if( nCellFlags & CELL_UPPER )
2148 : {
2149 0 : if( rNewFrame.GetBottom() )
2150 0 : ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_BOTTOM );
2151 : }
2152 0 : else if( nCellFlags & CELL_LOWER )
2153 : {
2154 0 : if( rNewFrame.GetTop() )
2155 0 : ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_TOP );
2156 : }
2157 : }
2158 0 : else if( (nCellFlags & ( CELL_UPPER|CELL_LOWER)) == 0 ) // check if its not sw or se corner
2159 : {
2160 0 : if( nCellFlags & CELL_BEFORE )
2161 : {
2162 0 : if( rNewFrame.GetRight() )
2163 0 : ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_RIGHT );
2164 : }
2165 0 : else if( nCellFlags & CELL_AFTER )
2166 : {
2167 0 : if( rNewFrame.GetLeft() )
2168 0 : ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_LEFT );
2169 : }
2170 : }
2171 : }
2172 : else
2173 : {
2174 0 : if( rNewFrame.GetBottom() )
2175 0 : ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_BOTTOM );
2176 0 : if( rNewFrame.GetTop() )
2177 0 : ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_TOP );
2178 0 : if( rNewFrame.GetRight() )
2179 0 : ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_RIGHT );
2180 0 : if( rNewFrame.GetLeft() )
2181 0 : ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_LEFT );
2182 : }
2183 0 : }
2184 :
2185 : // --------------------------------------------------------------------
2186 :
2187 0 : void SvxTableController::ApplyBorderAttr( const SfxItemSet& rAttr )
2188 : {
2189 0 : if( mxTable.is() )
2190 : {
2191 0 : const sal_Int32 nRowCount = mxTable->getRowCount();
2192 0 : const sal_Int32 nColCount = mxTable->getColumnCount();
2193 0 : if( nRowCount && nColCount )
2194 : {
2195 0 : const SvxBoxItem* pBoxItem = 0;
2196 0 : if(SFX_ITEM_SET == rAttr.GetItemState(SDRATTR_TABLE_BORDER, sal_False) )
2197 0 : pBoxItem = dynamic_cast< const SvxBoxItem* >( &rAttr.Get( SDRATTR_TABLE_BORDER ) );
2198 :
2199 0 : const SvxBoxInfoItem* pBoxInfoItem = 0;
2200 0 : if(SFX_ITEM_SET == rAttr.GetItemState(SDRATTR_TABLE_BORDER_INNER, sal_False) )
2201 0 : pBoxInfoItem = dynamic_cast< const SvxBoxInfoItem* >( &rAttr.Get( SDRATTR_TABLE_BORDER_INNER ) );
2202 :
2203 0 : const SvxColorItem* pLineColorItem = 0;
2204 0 : if(SFX_ITEM_SET == rAttr.GetItemState(SID_FRAME_LINECOLOR, sal_False) )
2205 0 : pLineColorItem = dynamic_cast< const SvxColorItem* >( &rAttr.Get( SID_FRAME_LINECOLOR ) );
2206 :
2207 0 : const SvxBorderLine* pBorderLineItem = 0;
2208 0 : if(SFX_ITEM_SET == rAttr.GetItemState(SID_FRAME_LINESTYLE, sal_False) )
2209 0 : pBorderLineItem = ((const SvxLineItem&)rAttr.Get( SID_FRAME_LINESTYLE )).GetLine();
2210 :
2211 0 : if( pBoxInfoItem && !pBoxItem )
2212 : {
2213 0 : const static SvxBoxItem gaEmptyBoxItem( SDRATTR_TABLE_BORDER );
2214 0 : pBoxItem = &gaEmptyBoxItem;
2215 : }
2216 0 : else if( pBoxItem && !pBoxInfoItem )
2217 : {
2218 0 : const static SvxBoxInfoItem gaEmptyBoxInfoItem( SDRATTR_TABLE_BORDER_INNER );
2219 0 : pBoxInfoItem = &gaEmptyBoxInfoItem;
2220 : }
2221 :
2222 0 : CellPos aStart, aEnd;
2223 0 : getSelectedCells( aStart, aEnd );
2224 :
2225 0 : const sal_Int32 nLastRow = std::min( aEnd.mnRow + 2, nRowCount );
2226 0 : const sal_Int32 nLastCol = std::min( aEnd.mnCol + 2, nColCount );
2227 :
2228 0 : for( sal_Int32 nRow = std::max( aStart.mnRow - 1, (sal_Int32)0 ); nRow < nLastRow; nRow++ )
2229 : {
2230 0 : sal_uInt16 nRowFlags = 0;
2231 0 : nRowFlags |= (nRow == aStart.mnRow) ? CELL_TOP : 0;
2232 0 : nRowFlags |= (nRow == aEnd.mnRow) ? CELL_BOTTOM : 0;
2233 0 : nRowFlags |= (nRow < aStart.mnRow) ? CELL_UPPER : 0;
2234 0 : nRowFlags |= (nRow > aEnd.mnRow) ? CELL_LOWER : 0;
2235 :
2236 0 : for( sal_Int32 nCol = std::max( aStart.mnCol - 1, (sal_Int32)0 ); nCol < nLastCol; nCol++ )
2237 : {
2238 0 : CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
2239 0 : if( !xCell.is() )
2240 0 : continue;
2241 :
2242 0 : const SfxItemSet& rSet = xCell->GetItemSet();
2243 0 : const SvxBoxItem* pOldOuter = (const SvxBoxItem*) &rSet.Get( SDRATTR_TABLE_BORDER );
2244 :
2245 0 : SvxBoxItem aNewFrame( *pOldOuter );
2246 :
2247 0 : sal_uInt16 nCellFlags = nRowFlags;
2248 0 : nCellFlags |= (nCol == aStart.mnCol) ? CELL_LEFT : 0;
2249 0 : nCellFlags |= (nCol == aEnd.mnCol) ? CELL_RIGHT : 0;
2250 0 : nCellFlags |= (nCol < aStart.mnCol) ? CELL_BEFORE : 0;
2251 0 : nCellFlags |= (nCol > aEnd.mnCol) ? CELL_AFTER : 0;
2252 :
2253 0 : if( pBoxItem && pBoxInfoItem )
2254 0 : ImplApplyBoxItem( nCellFlags, pBoxItem, pBoxInfoItem, aNewFrame );
2255 :
2256 0 : if( pLineColorItem )
2257 0 : ImplApplyLineColorItem( nCellFlags, pLineColorItem, aNewFrame );
2258 :
2259 0 : if( pBorderLineItem )
2260 0 : ImplApplyBorderLineItem( nCellFlags, pBorderLineItem, aNewFrame );
2261 :
2262 0 : if (aNewFrame != *pOldOuter)
2263 : {
2264 0 : SfxItemSet aAttr(*rSet.GetPool(), rSet.GetRanges());
2265 0 : aAttr.Put(aNewFrame);
2266 0 : xCell->SetMergedItemSetAndBroadcast( aAttr, false );
2267 : }
2268 0 : }
2269 : }
2270 : }
2271 : }
2272 0 : }
2273 :
2274 : // --------------------------------------------------------------------
2275 :
2276 0 : void SvxTableController::UpdateTableShape()
2277 : {
2278 0 : SdrObject* pTableObj = mxTableObj.get();
2279 0 : if( pTableObj )
2280 : {
2281 0 : pTableObj->ActionChanged();
2282 0 : pTableObj->BroadcastObjectChange();
2283 : }
2284 0 : updateSelectionOverlay();
2285 0 : }
2286 :
2287 :
2288 : // --------------------------------------------------------------------
2289 :
2290 0 : void SvxTableController::SetAttrToSelectedCells(const SfxItemSet& rAttr, bool bReplaceAll)
2291 : {
2292 0 : if( mxTable.is() )
2293 : {
2294 0 : const bool bUndo = mpModel && mpModel->IsUndoEnabled();
2295 :
2296 0 : if( bUndo )
2297 0 : mpModel->BegUndo( ImpGetResStr(STR_TABLE_NUMFORMAT) );
2298 :
2299 0 : CellPos aStart, aEnd;
2300 0 : getSelectedCells( aStart, aEnd );
2301 :
2302 0 : SfxItemSet aAttr(*rAttr.GetPool(), rAttr.GetRanges());
2303 0 : aAttr.Put(rAttr, sal_True);
2304 :
2305 0 : const bool bFrame = (rAttr.GetItemState( SDRATTR_TABLE_BORDER ) == SFX_ITEM_SET) || (rAttr.GetItemState( SDRATTR_TABLE_BORDER_INNER ) == SFX_ITEM_SET);
2306 :
2307 0 : if( bFrame )
2308 : {
2309 0 : aAttr.ClearItem( SDRATTR_TABLE_BORDER );
2310 0 : aAttr.ClearItem( SDRATTR_TABLE_BORDER_INNER );
2311 : }
2312 :
2313 0 : for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
2314 : {
2315 0 : for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
2316 : {
2317 0 : CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
2318 0 : if( xCell.is() )
2319 : {
2320 0 : if( bUndo )
2321 0 : xCell->AddUndo();
2322 0 : xCell->SetMergedItemSetAndBroadcast(aAttr, bReplaceAll);
2323 : }
2324 0 : }
2325 : }
2326 :
2327 0 : if( bFrame )
2328 : {
2329 0 : ApplyBorderAttr( rAttr );
2330 : }
2331 :
2332 0 : UpdateTableShape();
2333 :
2334 0 : if( bUndo )
2335 0 : mpModel->EndUndo();
2336 :
2337 : }
2338 0 : }
2339 :
2340 : // --------------------------------------------------------------------
2341 :
2342 0 : bool SvxTableController::GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr) const
2343 : {
2344 0 : if( mxTableObj.is() && hasSelectedCells() )
2345 : {
2346 0 : MergeAttrFromSelectedCells( rTargetSet, bOnlyHardAttr );
2347 :
2348 0 : if( mpView->IsTextEdit() )
2349 : {
2350 0 : if( mxTableObj->GetOutlinerParaObject() )
2351 0 : rTargetSet.Put( SvxScriptTypeItem( mxTableObj->GetOutlinerParaObject()->GetTextObject().GetScriptType() ) );
2352 :
2353 0 : OutlinerView* pTextEditOutlinerView = mpView->GetTextEditOutlinerView();
2354 0 : if(pTextEditOutlinerView)
2355 : {
2356 : // FALSE= InvalidItems nicht al Default, sondern als "Loecher" betrachten
2357 0 : rTargetSet.Put(pTextEditOutlinerView->GetAttribs(), sal_False);
2358 0 : rTargetSet.Put( SvxScriptTypeItem( pTextEditOutlinerView->GetSelectedScriptType() ) );
2359 : }
2360 : }
2361 :
2362 0 : return true;
2363 : }
2364 : else
2365 : {
2366 0 : return false;
2367 : }
2368 : }
2369 :
2370 : // --------------------------------------------------------------------
2371 :
2372 0 : bool SvxTableController::SetAttributes(const SfxItemSet& rSet, bool bReplaceAll)
2373 : {
2374 0 : if( mbCellSelectionMode || mpView->IsTextEdit() )
2375 : {
2376 0 : SetAttrToSelectedCells( rSet, bReplaceAll );
2377 0 : return true;
2378 : }
2379 0 : return false;
2380 : }
2381 :
2382 : // --------------------------------------------------------------------
2383 :
2384 0 : bool SvxTableController::GetMarkedObjModel( SdrPage* pNewPage )
2385 : {
2386 0 : if( mxTableObj.is() && mbCellSelectionMode && pNewPage ) try
2387 : {
2388 0 : ::sdr::table::SdrTableObj& rTableObj = *static_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
2389 :
2390 0 : CellPos aStart, aEnd;
2391 0 : getSelectedCells( aStart, aEnd );
2392 :
2393 0 : SdrTableObj* pNewTableObj = rTableObj.CloneRange( aStart, aEnd );
2394 :
2395 0 : pNewTableObj->SetPage( pNewPage );
2396 0 : pNewTableObj->SetModel( pNewPage->GetModel() );
2397 :
2398 0 : SdrInsertReason aReason(SDRREASON_VIEWCALL);
2399 0 : pNewPage->InsertObject(pNewTableObj,CONTAINER_APPEND,&aReason);
2400 :
2401 0 : return true;
2402 : }
2403 0 : catch( Exception& )
2404 : {
2405 : OSL_FAIL( "svx::SvxTableController::GetMarkedObjModel(), exception caught!" );
2406 : }
2407 0 : return false;
2408 : }
2409 :
2410 : // --------------------------------------------------------------------
2411 :
2412 0 : bool SvxTableController::PasteObjModel( const SdrModel& rModel )
2413 : {
2414 0 : if( mxTableObj.is() && mpView && (rModel.GetPageCount() >= 1) )
2415 : {
2416 0 : const SdrPage* pPastePage = rModel.GetPage(0);
2417 0 : if( pPastePage && pPastePage->GetObjCount() == 1 )
2418 : {
2419 0 : SdrTableObj* pPasteTableObj = dynamic_cast< SdrTableObj* >( pPastePage->GetObj(0) );
2420 0 : if( pPasteTableObj )
2421 : {
2422 0 : return PasteObject( pPasteTableObj );
2423 : }
2424 : }
2425 : }
2426 :
2427 0 : return false;
2428 : }
2429 :
2430 : // --------------------------------------------------------------------
2431 :
2432 0 : bool SvxTableController::PasteObject( SdrTableObj* pPasteTableObj )
2433 : {
2434 0 : if( !pPasteTableObj )
2435 0 : return false;
2436 :
2437 0 : Reference< XTable > xPasteTable( pPasteTableObj->getTable() );
2438 0 : if( !xPasteTable.is() )
2439 0 : return false;
2440 :
2441 0 : if( !mxTable.is() )
2442 0 : return false;
2443 :
2444 0 : sal_Int32 nPasteColumns = xPasteTable->getColumnCount();
2445 0 : sal_Int32 nPasteRows = xPasteTable->getRowCount();
2446 :
2447 0 : CellPos aStart, aEnd;
2448 0 : getSelectedCells( aStart, aEnd );
2449 :
2450 0 : if( mpView->IsTextEdit() )
2451 0 : mpView->SdrEndTextEdit(sal_True);
2452 :
2453 0 : sal_Int32 nColumns = mxTable->getColumnCount();
2454 0 : sal_Int32 nRows = mxTable->getRowCount();
2455 :
2456 0 : const sal_Int32 nMissing = nPasteRows - ( nRows - aStart.mnRow );
2457 0 : if( nMissing > 0 )
2458 : {
2459 0 : Reference< XTableRows > xRows( mxTable->getRows() );
2460 0 : xRows->insertByIndex( nRows, nMissing );
2461 0 : nRows = mxTable->getRowCount();
2462 : }
2463 :
2464 0 : nPasteRows = std::min( nPasteRows, nRows - aStart.mnRow );
2465 0 : nPasteColumns = std::min( nPasteColumns, nColumns - aStart.mnCol );
2466 :
2467 : // copy cell contents
2468 0 : for( sal_Int32 nRow = 0; nRow < nPasteRows; ++nRow )
2469 : {
2470 0 : for( sal_Int32 nCol = 0; nCol < nPasteColumns; ++nCol )
2471 : {
2472 0 : CellRef xTargetCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( aStart.mnCol + nCol, aStart.mnRow + nRow ).get() ) );
2473 0 : if( xTargetCell.is() && !xTargetCell->isMerged() )
2474 : {
2475 0 : xTargetCell->AddUndo();
2476 0 : xTargetCell->cloneFrom( dynamic_cast< Cell* >( xPasteTable->getCellByPosition( nCol, nRow ).get() ) );
2477 0 : nCol += xTargetCell->getColumnSpan() - 1;
2478 : }
2479 0 : }
2480 : }
2481 :
2482 0 : UpdateTableShape();
2483 :
2484 0 : return true;
2485 : }
2486 :
2487 0 : bool SvxTableController::TakeFormatPaintBrush( boost::shared_ptr< SfxItemSet >& /*rFormatSet*/ )
2488 : {
2489 : // SdrView::TakeFormatPaintBrush() is enough
2490 0 : return false;
2491 : }
2492 :
2493 0 : bool SvxTableController::ApplyFormatPaintBrush( SfxItemSet& rFormatSet, bool bNoCharacterFormats, bool bNoParagraphFormats )
2494 : {
2495 0 : if( mbCellSelectionMode )
2496 : {
2497 0 : SdrTextObj* pTableObj = dynamic_cast<SdrTextObj*>( mxTableObj.get() );
2498 0 : if( !pTableObj )
2499 0 : return false;
2500 :
2501 0 : const bool bUndo = mpModel && mpModel->IsUndoEnabled();
2502 :
2503 0 : if( bUndo )
2504 0 : mpModel->BegUndo( ImpGetResStr(STR_TABLE_NUMFORMAT) );
2505 :
2506 0 : CellPos aStart, aEnd;
2507 0 : getSelectedCells( aStart, aEnd );
2508 :
2509 0 : SfxItemSet aAttr(*rFormatSet.GetPool(), rFormatSet.GetRanges());
2510 0 : aAttr.Put(rFormatSet, sal_True);
2511 :
2512 0 : const bool bFrame = (rFormatSet.GetItemState( SDRATTR_TABLE_BORDER ) == SFX_ITEM_SET) || (rFormatSet.GetItemState( SDRATTR_TABLE_BORDER_INNER ) == SFX_ITEM_SET);
2513 :
2514 0 : if( bFrame )
2515 : {
2516 0 : aAttr.ClearItem( SDRATTR_TABLE_BORDER );
2517 0 : aAttr.ClearItem( SDRATTR_TABLE_BORDER_INNER );
2518 : }
2519 :
2520 0 : const sal_uInt16* pRanges = rFormatSet.GetRanges();
2521 0 : bool bTextOnly = true;
2522 :
2523 0 : while( *pRanges )
2524 : {
2525 0 : if( (*pRanges != EE_PARA_START) && (*pRanges != EE_CHAR_START) )
2526 : {
2527 0 : bTextOnly = false;
2528 0 : break;
2529 : }
2530 0 : pRanges += 2;
2531 : }
2532 :
2533 0 : const bool bReplaceAll = false;
2534 0 : for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
2535 : {
2536 0 : for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
2537 : {
2538 0 : CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
2539 0 : if( xCell.is() )
2540 : {
2541 0 : if( bUndo )
2542 0 : xCell->AddUndo();
2543 0 : if( !bTextOnly )
2544 0 : xCell->SetMergedItemSetAndBroadcast(aAttr, bReplaceAll);
2545 :
2546 0 : SdrText* pText = static_cast< SdrText* >( xCell.get() );
2547 0 : mpView->ApplyFormatPaintBrushToText( rFormatSet, *pTableObj, pText, bNoCharacterFormats, bNoParagraphFormats );
2548 : }
2549 0 : }
2550 : }
2551 :
2552 0 : if( bFrame )
2553 : {
2554 0 : ApplyBorderAttr( rFormatSet );
2555 : }
2556 :
2557 0 : UpdateTableShape();
2558 :
2559 0 : if( bUndo )
2560 0 : mpModel->EndUndo();
2561 :
2562 0 : return true;
2563 :
2564 : }
2565 0 : return false;
2566 : }
2567 :
2568 :
2569 : // --------------------------------------------------------------------
2570 :
2571 0 : IMPL_LINK_NOARG(SvxTableController, UpdateHdl)
2572 : {
2573 0 : mnUpdateEvent = 0;
2574 :
2575 0 : if( mbCellSelectionMode )
2576 : {
2577 0 : CellPos aStart( maCursorFirstPos );
2578 0 : CellPos aEnd( maCursorLastPos );
2579 0 : checkCell(aStart);
2580 0 : checkCell(aEnd);
2581 0 : if( aStart != maCursorFirstPos || aEnd != maCursorLastPos )
2582 : {
2583 0 : setSelectedCells( aStart, aEnd );
2584 : }
2585 : }
2586 0 : updateSelectionOverlay();
2587 :
2588 0 : return 0;
2589 : }
2590 :
2591 : namespace
2592 : {
2593 :
2594 : struct LinesState
2595 : {
2596 0 : LinesState(SvxBoxItem& rBoxItem_, SvxBoxInfoItem& rBoxInfoItem_)
2597 : : rBoxItem(rBoxItem_)
2598 : , rBoxInfoItem(rBoxInfoItem_)
2599 0 : , bDistanceIndeterminate(false)
2600 : {
2601 0 : std::fill_n(aBorderSet, 4, false);
2602 0 : std::fill_n(aInnerLineSet, 2, false);
2603 0 : std::fill_n(aBorderIndeterminate, 4, false);
2604 0 : std::fill_n(aInnerLineIndeterminate, 2, false);
2605 0 : std::fill_n(aDistanceSet, 4, false);
2606 0 : std::fill_n(aDistance, 4, 0);
2607 0 : }
2608 :
2609 : SvxBoxItem& rBoxItem;
2610 : SvxBoxInfoItem& rBoxInfoItem;
2611 : bool aBorderSet[4];
2612 : bool aInnerLineSet[2];
2613 : bool aBorderIndeterminate[4];
2614 : bool aInnerLineIndeterminate[2];
2615 : bool aDistanceSet[4];
2616 : sal_uInt16 aDistance[4];
2617 : bool bDistanceIndeterminate;
2618 : };
2619 :
2620 : class BoxItemWrapper
2621 : {
2622 : public:
2623 : BoxItemWrapper(SvxBoxItem& rBoxItem, SvxBoxInfoItem& rBoxInfoItem, sal_uInt16 nBorderLine, sal_uInt16 nInnerLine, bool bBorder);
2624 :
2625 : const SvxBorderLine* getLine() const;
2626 : void setLine(const SvxBorderLine* pLine);
2627 :
2628 : private:
2629 : SvxBoxItem& m_rBoxItem;
2630 : SvxBoxInfoItem& m_rBoxInfoItem;
2631 : const sal_uInt16 m_nLine;
2632 : const bool m_bBorder;
2633 : };
2634 :
2635 0 : BoxItemWrapper::BoxItemWrapper(
2636 : SvxBoxItem& rBoxItem, SvxBoxInfoItem& rBoxInfoItem,
2637 : const sal_uInt16 nBorderLine, const sal_uInt16 nInnerLine, const bool bBorder)
2638 : : m_rBoxItem(rBoxItem)
2639 : , m_rBoxInfoItem(rBoxInfoItem)
2640 : , m_nLine(bBorder ? nBorderLine : nInnerLine)
2641 0 : , m_bBorder(bBorder)
2642 : {
2643 : assert(bBorder ? (m_nLine <= BOX_LINE_RIGHT) : (m_nLine <= BOXINFO_LINE_VERT));
2644 0 : }
2645 :
2646 0 : const SvxBorderLine* BoxItemWrapper::getLine() const
2647 : {
2648 0 : if (m_bBorder)
2649 0 : return m_rBoxItem.GetLine(m_nLine);
2650 : else
2651 0 : return (m_nLine == BOXINFO_LINE_HORI) ? m_rBoxInfoItem.GetHori() : m_rBoxInfoItem.GetVert();
2652 : }
2653 :
2654 0 : void BoxItemWrapper::setLine(const SvxBorderLine* pLine)
2655 : {
2656 0 : if (m_bBorder)
2657 0 : m_rBoxItem.SetLine(pLine, m_nLine);
2658 : else
2659 0 : m_rBoxInfoItem.SetLine(pLine, m_nLine);
2660 0 : }
2661 :
2662 0 : void lcl_MergeBorderLine(
2663 : LinesState& rLinesState, const SvxBorderLine* const pLine, const sal_uInt16 nLine,
2664 : const sal_uInt8 nValidFlag, const bool bBorder = true)
2665 : {
2666 0 : const sal_uInt16 nInnerLine(bBorder ? 0 : ((nValidFlag & VALID_HORI) ? BOXINFO_LINE_HORI : BOXINFO_LINE_VERT));
2667 0 : BoxItemWrapper aBoxItem(rLinesState.rBoxItem, rLinesState.rBoxInfoItem, nLine, nInnerLine, bBorder);
2668 0 : bool& rbSet(bBorder ? rLinesState.aBorderSet[nLine] : rLinesState.aInnerLineSet[nInnerLine]);
2669 0 : bool& rbIndeterminate(bBorder ? rLinesState.aBorderIndeterminate[nLine] : rLinesState.aInnerLineIndeterminate[nInnerLine]);
2670 :
2671 0 : if (rbSet)
2672 : {
2673 0 : if (!rbIndeterminate)
2674 : {
2675 0 : const SvxBorderLine* const pMergedLine(aBoxItem.getLine());
2676 0 : if ((pLine && !pMergedLine) || (!pLine && pMergedLine) || (pLine && (*pLine != *pMergedLine)))
2677 : {
2678 0 : aBoxItem.setLine(0);
2679 0 : rbIndeterminate = true;
2680 : }
2681 : }
2682 : }
2683 : else
2684 : {
2685 0 : aBoxItem.setLine(pLine);
2686 0 : rbSet = true;
2687 : }
2688 0 : }
2689 :
2690 0 : void lcl_MergeBorderOrInnerLine(
2691 : LinesState& rLinesState, const SvxBorderLine* const pLine, const sal_uInt16 nLine,
2692 : const sal_uInt8 nValidFlag, const bool bBorder)
2693 : {
2694 0 : if (bBorder)
2695 0 : lcl_MergeBorderLine(rLinesState, pLine, nLine, nValidFlag);
2696 : else
2697 : {
2698 0 : const bool bVertical = (nLine == BOX_LINE_LEFT) || (nLine == BOX_LINE_RIGHT);
2699 0 : lcl_MergeBorderLine(rLinesState, pLine, nLine, bVertical ? VALID_VERT : VALID_HORI, false);
2700 : }
2701 0 : }
2702 :
2703 0 : void lcl_MergeDistance(
2704 : LinesState& rLinesState, const sal_uInt16 nIndex, const sal_uInt16 nDistance)
2705 : {
2706 0 : if (rLinesState.aDistanceSet[nIndex])
2707 : {
2708 0 : if (!rLinesState.bDistanceIndeterminate)
2709 0 : rLinesState.bDistanceIndeterminate = nDistance != rLinesState.aDistance[nIndex];
2710 : }
2711 : else
2712 : {
2713 0 : rLinesState.aDistance[nIndex] = nDistance;
2714 0 : rLinesState.aDistanceSet[nIndex] = true;
2715 : }
2716 0 : }
2717 :
2718 0 : void lcl_MergeCommonBorderAttr(LinesState& rLinesState, const SvxBoxItem& rCellBoxItem, const sal_Int32 nCellFlags)
2719 : {
2720 0 : if( (nCellFlags & (CELL_BEFORE|CELL_AFTER|CELL_UPPER|CELL_LOWER)) != 0 )
2721 : {
2722 : // current cell is outside the selection
2723 :
2724 0 : if( (nCellFlags & ( CELL_BEFORE|CELL_AFTER)) == 0 ) // check if its not nw or ne corner
2725 : {
2726 0 : if( nCellFlags & CELL_UPPER )
2727 0 : lcl_MergeBorderLine(rLinesState, rCellBoxItem.GetBottom(), BOX_LINE_TOP, VALID_TOP);
2728 0 : else if( nCellFlags & CELL_LOWER )
2729 0 : lcl_MergeBorderLine(rLinesState, rCellBoxItem.GetTop(), BOX_LINE_BOTTOM, VALID_BOTTOM);
2730 : }
2731 0 : else if( (nCellFlags & ( CELL_UPPER|CELL_LOWER)) == 0 ) // check if its not sw or se corner
2732 : {
2733 0 : if( nCellFlags & CELL_BEFORE )
2734 0 : lcl_MergeBorderLine(rLinesState, rCellBoxItem.GetRight(), BOX_LINE_LEFT, VALID_LEFT);
2735 0 : else if( nCellFlags & CELL_AFTER )
2736 0 : lcl_MergeBorderLine(rLinesState, rCellBoxItem.GetLeft(), BOX_LINE_RIGHT, VALID_RIGHT);
2737 : }
2738 :
2739 : // NOTE: inner distances for cells outside the selected range
2740 : // are not relevant -> we ignore them.
2741 : }
2742 : else
2743 : {
2744 : // current cell is inside the selection
2745 :
2746 0 : lcl_MergeBorderOrInnerLine(rLinesState, rCellBoxItem.GetTop(), BOX_LINE_TOP, VALID_TOP, nCellFlags & CELL_TOP);
2747 0 : lcl_MergeBorderOrInnerLine(rLinesState, rCellBoxItem.GetBottom(), BOX_LINE_BOTTOM, VALID_BOTTOM, nCellFlags & CELL_BOTTOM);
2748 0 : lcl_MergeBorderOrInnerLine(rLinesState, rCellBoxItem.GetLeft(), BOX_LINE_LEFT, VALID_LEFT, nCellFlags & CELL_LEFT);
2749 0 : lcl_MergeBorderOrInnerLine(rLinesState, rCellBoxItem.GetRight(), BOX_LINE_RIGHT, VALID_RIGHT, nCellFlags & CELL_RIGHT);
2750 :
2751 0 : lcl_MergeDistance(rLinesState, BOX_LINE_TOP, rCellBoxItem.GetDistance(BOX_LINE_TOP));
2752 0 : lcl_MergeDistance(rLinesState, BOX_LINE_BOTTOM, rCellBoxItem.GetDistance(BOX_LINE_BOTTOM));
2753 0 : lcl_MergeDistance(rLinesState, BOX_LINE_LEFT, rCellBoxItem.GetDistance(BOX_LINE_LEFT));
2754 0 : lcl_MergeDistance(rLinesState, BOX_LINE_RIGHT, rCellBoxItem.GetDistance(BOX_LINE_RIGHT));
2755 : }
2756 0 : }
2757 :
2758 : }
2759 :
2760 0 : void SvxTableController::FillCommonBorderAttrFromSelectedCells( SvxBoxItem& rBoxItem, SvxBoxInfoItem& rBoxInfoItem ) const
2761 : {
2762 0 : if( mxTable.is() )
2763 : {
2764 0 : const sal_Int32 nRowCount = mxTable->getRowCount();
2765 0 : const sal_Int32 nColCount = mxTable->getColumnCount();
2766 0 : if( nRowCount && nColCount )
2767 : {
2768 0 : CellPos aStart, aEnd;
2769 0 : const_cast< SvxTableController* >( this )->getSelectedCells( aStart, aEnd );
2770 :
2771 : // We are adding one more row/column around the block of selected cells.
2772 : // We will be checking the adjoining border of these too.
2773 0 : const sal_Int32 nLastRow = std::min( aEnd.mnRow + 2, nRowCount );
2774 0 : const sal_Int32 nLastCol = std::min( aEnd.mnCol + 2, nColCount );
2775 :
2776 0 : rBoxInfoItem.SetValid( sal_uInt8( ~0 ), sal_False );
2777 0 : LinesState aLinesState( rBoxItem, rBoxInfoItem );
2778 :
2779 : /* Here we go through all the selected cells (enhanced by
2780 : * the adjoining row/column on each side) and determine the
2781 : * lines for presentation. The algorithm is simple:
2782 : * 1. if a border or inner line is set (or unset) in all
2783 : * cells to the same value, it will be used.
2784 : * 2. if a border or inner line is set only in some cells,
2785 : * it will be set to indeterminate state (SetValid() on
2786 : * rBoxInfoItem).
2787 : */
2788 0 : for( sal_Int32 nRow = std::max( aStart.mnRow - 1, (sal_Int32)0 ); nRow < nLastRow; nRow++ )
2789 : {
2790 0 : sal_uInt16 nRowFlags = 0;
2791 0 : nRowFlags |= (nRow == aStart.mnRow) ? CELL_TOP : 0;
2792 0 : nRowFlags |= (nRow == aEnd.mnRow) ? CELL_BOTTOM : 0;
2793 0 : nRowFlags |= (nRow < aStart.mnRow) ? CELL_UPPER : 0;
2794 0 : nRowFlags |= (nRow > aEnd.mnRow) ? CELL_LOWER : 0;
2795 :
2796 0 : for( sal_Int32 nCol = std::max( aStart.mnCol - 1, (sal_Int32)0 ); nCol < nLastCol; nCol++ )
2797 : {
2798 0 : CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
2799 0 : if( !xCell.is() )
2800 0 : continue;
2801 :
2802 0 : sal_uInt16 nCellFlags = nRowFlags;
2803 0 : nCellFlags |= (nCol == aStart.mnCol) ? CELL_LEFT : 0;
2804 0 : nCellFlags |= (nCol == aEnd.mnCol) ? CELL_RIGHT : 0;
2805 0 : nCellFlags |= (nCol < aStart.mnCol) ? CELL_BEFORE : 0;
2806 0 : nCellFlags |= (nCol > aEnd.mnCol) ? CELL_AFTER : 0;
2807 :
2808 0 : const SfxItemSet& rSet = xCell->GetItemSet();
2809 0 : const SvxBoxItem& rCellBoxItem = static_cast< const SvxBoxItem& >( rSet.Get(SDRATTR_TABLE_BORDER ) );
2810 0 : lcl_MergeCommonBorderAttr( aLinesState, rCellBoxItem, nCellFlags );
2811 0 : }
2812 : }
2813 :
2814 0 : if (!aLinesState.aBorderIndeterminate[BOX_LINE_TOP])
2815 0 : aLinesState.rBoxInfoItem.SetValid(VALID_TOP);
2816 0 : if (!aLinesState.aBorderIndeterminate[BOX_LINE_BOTTOM])
2817 0 : aLinesState.rBoxInfoItem.SetValid(VALID_BOTTOM);
2818 0 : if (!aLinesState.aBorderIndeterminate[BOX_LINE_LEFT])
2819 0 : aLinesState.rBoxInfoItem.SetValid(VALID_LEFT);
2820 0 : if (!aLinesState.aBorderIndeterminate[BOX_LINE_RIGHT])
2821 0 : aLinesState.rBoxInfoItem.SetValid(VALID_RIGHT);
2822 0 : if (!aLinesState.aInnerLineIndeterminate[BOXINFO_LINE_HORI])
2823 0 : aLinesState.rBoxInfoItem.SetValid(VALID_HORI);
2824 0 : if (!aLinesState.aInnerLineIndeterminate[BOXINFO_LINE_VERT])
2825 0 : aLinesState.rBoxInfoItem.SetValid(VALID_VERT);
2826 :
2827 0 : if (!aLinesState.bDistanceIndeterminate)
2828 : {
2829 0 : if (aLinesState.aDistanceSet[BOX_LINE_TOP])
2830 0 : aLinesState.rBoxItem.SetDistance(aLinesState.aDistance[BOX_LINE_TOP], BOX_LINE_TOP);
2831 0 : if (aLinesState.aDistanceSet[BOX_LINE_BOTTOM])
2832 0 : aLinesState.rBoxItem.SetDistance(aLinesState.aDistance[BOX_LINE_BOTTOM], BOX_LINE_BOTTOM);
2833 0 : if (aLinesState.aDistanceSet[BOX_LINE_LEFT])
2834 0 : aLinesState.rBoxItem.SetDistance(aLinesState.aDistance[BOX_LINE_LEFT], BOX_LINE_LEFT);
2835 0 : if (aLinesState.aDistanceSet[BOX_LINE_RIGHT])
2836 0 : aLinesState.rBoxItem.SetDistance(aLinesState.aDistance[BOX_LINE_RIGHT], BOX_LINE_RIGHT);
2837 0 : aLinesState.rBoxInfoItem.SetValid(VALID_DISTANCE);
2838 : }
2839 : }
2840 : }
2841 0 : }
2842 :
2843 258 : } }
2844 :
2845 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|