Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / svx / source / table / tablecontroller.cxx
blobf3ca36ff81cad88be1e6d1b2b900bac9ab4522ec
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include "tablecontroller.hxx"
32 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
33 #include <com/sun/star/container/XIndexAccess.hpp>
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/table/XMergeableCellRange.hpp>
37 #include <com/sun/star/table/XMergeableCell.hpp>
39 #include <sal/config.h>
41 #include <vcl/svapp.hxx>
42 #include <svl/whiter.hxx>
44 #include <sfx2/request.hxx>
46 #include <editeng/scripttypeitem.hxx>
47 #include <svx/svdotable.hxx>
48 #include <svx/sdr/overlay/overlayobjectcell.hxx>
49 #include <svx/sdr/overlay/overlaymanager.hxx>
50 #include <svx/svxids.hrc>
51 #include <editeng/outlobj.hxx>
52 #include <svx/svdoutl.hxx>
53 #include <svx/svdpagv.hxx>
54 #include <svx/svdetc.hxx>
55 #include <editeng/editobj.hxx>
56 #include "editeng/editstat.hxx"
57 #include "editeng/unolingu.hxx"
58 #include "svx/sdrpagewindow.hxx"
59 #include <svx/selectioncontroller.hxx>
60 #include <svx/svdmodel.hxx>
61 #include "svx/sdrpaintwindow.hxx"
62 #include <svx/svxdlg.hxx>
63 #include <editeng/boxitem.hxx>
64 #include "cell.hxx"
65 #include <editeng/borderline.hxx>
66 #include <editeng/colritem.hxx>
67 #include "editeng/bolnitem.hxx"
68 #include "svx/svdstr.hrc"
69 #include "svx/svdglob.hxx"
70 #include "svx/svdpage.hxx"
71 #include "tableundo.hxx"
72 #include "tablelayouter.hxx"
74 using ::editeng::SvxBorderLine;
75 using ::rtl::OUString;
76 using namespace ::sdr::table;
77 using namespace ::com::sun::star;
78 using namespace ::com::sun::star::uno;
79 using namespace ::com::sun::star::table;
80 using namespace ::com::sun::star::beans;
81 using namespace ::com::sun::star::container;
82 using namespace ::com::sun::star::text;
83 using namespace ::com::sun::star::style;
85 namespace sdr { namespace table {
87 // --------------------------------------------------------------------
88 // class SvxTableControllerModifyListener
89 // --------------------------------------------------------------------
91 class SvxTableControllerModifyListener : public ::cppu::WeakImplHelper1< ::com::sun::star::util::XModifyListener >
93 public:
94 SvxTableControllerModifyListener( SvxTableController* pController )
95 : mpController( pController ) {}
97 // XModifyListener
98 virtual void SAL_CALL modified( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException);
100 // XEventListener
101 virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);
103 SvxTableController* mpController;
106 // --------------------------------------------------------------------
107 // XModifyListener
108 // --------------------------------------------------------------------
110 void SAL_CALL SvxTableControllerModifyListener::modified( const ::com::sun::star::lang::EventObject& ) throw (::com::sun::star::uno::RuntimeException)
112 if( mpController )
113 mpController->onTableModified();
116 // --------------------------------------------------------------------
117 // XEventListener
118 // --------------------------------------------------------------------
120 void SAL_CALL SvxTableControllerModifyListener::disposing( const ::com::sun::star::lang::EventObject& ) throw (::com::sun::star::uno::RuntimeException)
122 mpController = 0;
125 // --------------------------------------------------------------------
126 // class SvxTableController
127 // --------------------------------------------------------------------
129 rtl::Reference< sdr::SelectionController > CreateTableController( SdrObjEditView* pView, const SdrObject* pObj, const rtl::Reference< sdr::SelectionController >& xRefController )
131 return SvxTableController::create( pView, pObj, xRefController );
134 // --------------------------------------------------------------------
136 rtl::Reference< sdr::SelectionController > SvxTableController::create( SdrObjEditView* pView, const SdrObject* pObj, const rtl::Reference< sdr::SelectionController >& xRefController )
138 if( xRefController.is() )
140 SvxTableController* pController = dynamic_cast< SvxTableController* >( xRefController.get() );
141 if( pController && (pController->mxTableObj.get() == pObj) && (pController->mpView == pView) )
142 return xRefController;
144 return new SvxTableController( pView, pObj );
147 // --------------------------------------------------------------------
149 SvxTableController::SvxTableController( SdrObjEditView* pView, const SdrObject* pObj )
150 : mbCellSelectionMode(false)
151 , mbLeftButtonDown(false)
152 , mpSelectionOverlay(0)
153 , mpView( dynamic_cast< SdrView* >( pView ) )
154 , mxTableObj( dynamic_cast< SdrTableObj* >( const_cast< SdrObject* >( pObj ) ) )
155 , mpModel( 0 )
156 , mnUpdateEvent( 0 )
158 if( pObj )
159 mpModel = pObj->GetModel();
161 if( mxTableObj.is() )
163 static_cast< const SdrTableObj* >( pObj )->getActiveCellPos( maCursorFirstPos );
164 maCursorLastPos = maCursorFirstPos;
166 Reference< XTable > xTable( static_cast< const SdrTableObj* >( pObj )->getTable() );
167 if( xTable.is() )
169 mxModifyListener = new SvxTableControllerModifyListener( this );
170 xTable->addModifyListener( mxModifyListener );
172 mxTable.set( dynamic_cast< TableModel* >( xTable.get() ) );
177 // --------------------------------------------------------------------
179 SvxTableController::~SvxTableController()
181 if( mnUpdateEvent )
183 Application::RemoveUserEvent( mnUpdateEvent );
186 if( mxModifyListener.is() && mxTableObj.get() )
188 Reference< XTable > xTable( static_cast< SdrTableObj* >( mxTableObj.get() )->getTable() );
189 if( xTable.is() )
191 xTable->removeModifyListener( mxModifyListener );
192 mxModifyListener.clear();
197 // --------------------------------------------------------------------
199 const sal_uInt16 ACTION_NONE = 0;
200 const sal_uInt16 ACTION_GOTO_FIRST_CELL = 1;
201 const sal_uInt16 ACTION_GOTO_FIRST_COLUMN = 2;
202 const sal_uInt16 ACTION_GOTO_FIRST_ROW = 3;
203 const sal_uInt16 ACTION_GOTO_LEFT_CELL = 4;
204 const sal_uInt16 ACTION_GOTO_UP_CELL = 5;
205 const sal_uInt16 ACTION_GOTO_RIGHT_CELL = 6;
206 const sal_uInt16 ACTION_GOTO_DOWN_CELL = 7;
207 const sal_uInt16 ACTION_GOTO_LAST_CELL = 8;
208 const sal_uInt16 ACTION_GOTO_LAST_COLUMN = 9;
209 const sal_uInt16 ACTION_GOTO_LAST_ROW = 10;
210 const sal_uInt16 ACTION_EDIT_CELL = 11;
211 const sal_uInt16 ACTION_STOP_TEXT_EDIT = 12;
212 const sal_uInt16 ACTION_REMOVE_SELECTION = 13;
213 const sal_uInt16 ACTION_START_SELECTION = 14;
214 const sal_uInt16 ACTION_HANDLED_BY_VIEW = 15;
215 const sal_uInt16 ACTION_TAB = 18;
217 bool SvxTableController::onKeyInput(const KeyEvent& rKEvt, Window* pWindow )
219 if( !checkTableObject() )
220 return false;
222 // check if we are read only
223 if( mpModel && mpModel->IsReadOnly())
225 switch( rKEvt.GetKeyCode().GetCode() )
227 case awt::Key::DOWN:
228 case awt::Key::UP:
229 case awt::Key::LEFT:
230 case awt::Key::RIGHT:
231 case awt::Key::TAB:
232 case awt::Key::HOME:
233 case awt::Key::END:
234 case awt::Key::NUM2:
235 case awt::Key::NUM4:
236 case awt::Key::NUM6:
237 case awt::Key::NUM8:
238 case awt::Key::ESCAPE:
239 case awt::Key::F2:
240 break;
241 default:
242 // tell the view we eat the event, no further processing needed
243 return true;
247 sal_uInt16 nAction = getKeyboardAction( rKEvt, pWindow );
249 return executeAction( nAction, ( rKEvt.GetKeyCode().IsShift() ) ? sal_True : sal_False, pWindow );
252 // --------------------------------------------------------------------
253 // ::com::sun::star::awt::XMouseClickHandler:
254 // --------------------------------------------------------------------
256 bool SvxTableController::onMouseButtonDown(const MouseEvent& rMEvt, Window* pWindow )
258 if( !pWindow || !checkTableObject() )
259 return false;
261 SdrViewEvent aVEvt;
262 if( !rMEvt.IsRight() && mpView->PickAnything(rMEvt,SDRMOUSEBUTTONDOWN, aVEvt) == SDRHIT_HANDLE )
263 return false;
265 TableHitKind eHit = static_cast< SdrTableObj* >(mxTableObj.get())->CheckTableHit( pWindow->PixelToLogic(rMEvt.GetPosPixel()), maMouseDownPos.mnCol, maMouseDownPos.mnRow, 0 );
267 mbLeftButtonDown = (rMEvt.GetClicks() == 1) && rMEvt.IsLeft();
269 if( eHit == SDRTABLEHIT_CELL )
271 StartSelection( maMouseDownPos );
272 return true;
275 if( rMEvt.IsRight() && eHit != SDRTABLEHIT_NONE )
276 return true; // right click will become context menu
278 // for cell selektion with the mouse remember our first hit
279 if( mbLeftButtonDown )
281 RemoveSelection();
283 Point aPnt(rMEvt.GetPosPixel());
284 if (pWindow!=NULL)
285 aPnt=pWindow->PixelToLogic(aPnt);
287 SdrHdl* pHdl = mpView->PickHandle(aPnt);
289 if( pHdl )
291 mbLeftButtonDown = false;
293 else
295 ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
297 if( !pWindow || !pTableObj || eHit == SDRTABLEHIT_NONE)
299 mbLeftButtonDown = false;
304 return false;
307 // --------------------------------------------------------------------
309 bool SvxTableController::onMouseButtonUp(const MouseEvent& rMEvt, Window* /*pWin*/)
311 if( !checkTableObject() )
312 return false;
314 mbLeftButtonDown = false;
316 if( rMEvt.GetClicks() == 2 )
317 return true;
319 return false;
322 // --------------------------------------------------------------------
324 bool SvxTableController::onMouseMove(const MouseEvent& rMEvt, Window* pWindow )
326 if( !checkTableObject() )
327 return false;
329 if( rMEvt.IsLeft() )
331 int i = 0;
332 i++;
335 SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
336 CellPos aPos;
337 if( mbLeftButtonDown && pTableObj && pTableObj->CheckTableHit( pWindow->PixelToLogic(rMEvt.GetPosPixel()), aPos.mnCol, aPos.mnRow, 0 ) != SDRTABLEHIT_NONE )
339 if(aPos != maMouseDownPos)
341 if( mbCellSelectionMode )
343 setSelectedCells( maMouseDownPos, aPos );
344 return true;
346 else
348 StartSelection( maMouseDownPos );
351 else if( mbCellSelectionMode )
353 UpdateSelection( aPos );
354 return true;
357 return false;
360 // --------------------------------------------------------------------
362 void SvxTableController::onSelectionHasChanged()
364 bool bSelected = false;
366 SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
367 if( pTableObj && pTableObj->IsTextEditActive() )
369 pTableObj->getActiveCellPos( maCursorFirstPos );
370 maCursorLastPos = maCursorFirstPos;
371 mbCellSelectionMode = false;
373 else
375 const SdrMarkList& rMarkList= mpView->GetMarkedObjectList();
376 if( rMarkList.GetMarkCount() == 1 )
377 bSelected = mxTableObj.get() == rMarkList.GetMark(0)->GetMarkedSdrObj();
380 if( bSelected )
382 updateSelectionOverlay();
384 else
386 destroySelectionOverlay();
390 // --------------------------------------------------------------------
392 void SvxTableController::GetState( SfxItemSet& rSet )
394 if( !mxTable.is() || !mxTableObj.is() || !mxTableObj->GetModel() )
395 return;
397 SfxItemSet* pSet = 0;
399 bool bVertDone = false;
401 // Iterate over all requested items in the set.
402 SfxWhichIter aIter( rSet );
403 sal_uInt16 nWhich = aIter.FirstWhich();
404 while (nWhich)
406 switch (nWhich)
408 case SID_TABLE_VERT_BOTTOM:
409 case SID_TABLE_VERT_CENTER:
410 case SID_TABLE_VERT_NONE:
412 if( !mxTable.is() || !mxTableObj->GetModel() )
414 rSet.DisableItem(nWhich);
416 else if(!bVertDone)
418 if( !pSet )
420 pSet = new SfxItemSet( mxTableObj->GetModel()->GetItemPool() );
421 MergeAttrFromSelectedCells(*pSet, sal_False);
424 SdrTextVertAdjust eAdj = SDRTEXTVERTADJUST_BLOCK;
426 if( pSet->GetItemState( SDRATTR_TEXT_VERTADJUST ) != SFX_ITEM_DONTCARE )
427 eAdj = ((SdrTextVertAdjustItem&)(pSet->Get(SDRATTR_TEXT_VERTADJUST))).GetValue();
429 rSet.Put(SfxBoolItem(SID_TABLE_VERT_BOTTOM, eAdj == SDRTEXTVERTADJUST_BOTTOM));
430 rSet.Put(SfxBoolItem(SID_TABLE_VERT_CENTER, eAdj == SDRTEXTVERTADJUST_CENTER));
431 rSet.Put(SfxBoolItem(SID_TABLE_VERT_NONE, eAdj == SDRTEXTVERTADJUST_TOP));
432 bVertDone = true;
434 break;
436 case SID_TABLE_DELETE_ROW:
437 if( !mxTable.is() || !hasSelectedCells() || (mxTable->getRowCount() <= 1) )
438 rSet.DisableItem(SID_TABLE_DELETE_ROW);
439 break;
440 case SID_TABLE_DELETE_COL:
441 if( !mxTable.is() || !hasSelectedCells() || (mxTable->getColumnCount() <= 1) )
442 rSet.DisableItem(SID_TABLE_DELETE_COL);
443 break;
444 case SID_TABLE_MERGE_CELLS:
445 if( !mxTable.is() || !hasSelectedCells() )
446 rSet.DisableItem(SID_TABLE_MERGE_CELLS);
447 break;
448 case SID_TABLE_SPLIT_CELLS:
449 if( !hasSelectedCells() || !mxTable.is() )
450 rSet.DisableItem(SID_TABLE_SPLIT_CELLS);
451 break;
453 case SID_OPTIMIZE_TABLE:
454 case SID_TABLE_DISTRIBUTE_COLUMNS:
455 case SID_TABLE_DISTRIBUTE_ROWS:
457 bool bDistributeColumns = false;
458 bool bDistributeRows = false;
459 if( mxTable.is() )
461 CellPos aStart, aEnd;
462 getSelectedCells( aStart, aEnd );
464 bDistributeColumns = aStart.mnCol != aEnd.mnCol;
465 bDistributeRows = aStart.mnRow != aEnd.mnRow;
467 if( !bDistributeColumns && !bDistributeRows )
468 rSet.DisableItem(SID_OPTIMIZE_TABLE);
469 if( !bDistributeColumns )
470 rSet.DisableItem(SID_TABLE_DISTRIBUTE_COLUMNS);
471 if( !bDistributeRows )
472 rSet.DisableItem(SID_TABLE_DISTRIBUTE_ROWS);
473 break;
476 case SID_AUTOFORMAT:
477 case SID_TABLE_SORT_DIALOG:
478 case SID_TABLE_AUTOSUM:
479 // if( !mxTable.is() )
480 // rSet.DisableItem( nWhich );
481 break;
482 default:
483 break;
485 nWhich = aIter.NextWhich();
487 if( pSet )
488 delete pSet;
491 // --------------------------------------------------------------------
493 void SvxTableController::onInsert( sal_uInt16 nSId, const SfxItemSet* pArgs )
495 ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
496 if( !pTableObj )
497 return;
499 if( mxTable.is() ) try
502 bool bInsertAfter = true;
503 sal_uInt16 nCount = 0;
504 if( pArgs )
506 const SfxPoolItem* pItem = 0;
507 pArgs->GetItemState(nSId, sal_False, &pItem);
508 if (pItem)
510 nCount = ((const SfxInt16Item* )pItem)->GetValue();
511 if(SFX_ITEM_SET == pArgs->GetItemState(SID_TABLE_PARAM_INSERT_AFTER, sal_True, &pItem))
512 bInsertAfter = ((const SfxBoolItem* )pItem)->GetValue();
516 CellPos aStart, aEnd;
517 if( hasSelectedCells() )
519 getSelectedCells( aStart, aEnd );
521 else
523 if( bInsertAfter )
525 aStart.mnCol = mxTable->getColumnCount() - 1;
526 aStart.mnRow = mxTable->getRowCount() - 1;
527 aEnd = aStart;
531 if( pTableObj->IsTextEditActive() )
532 mpView->SdrEndTextEdit(sal_True);
534 RemoveSelection();
536 const OUString sSize( RTL_CONSTASCII_USTRINGPARAM( "Size" ) );
538 const bool bUndo = mpModel && mpModel->IsUndoEnabled();
540 switch( nSId )
542 case SID_TABLE_INSERT_COL:
544 TableModelNotifyGuard aGuard( mxTable.get() );
546 if( bUndo )
548 mpModel->BegUndo( ImpGetResStr(STR_TABLE_INSCOL) );
549 mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
552 Reference< XTableColumns > xCols( mxTable->getColumns() );
553 const sal_Int32 nNewColumns = (nCount == 0) ? (aEnd.mnCol - aStart.mnCol + 1) : nCount;
554 const sal_Int32 nNewStartColumn = aEnd.mnCol + (bInsertAfter ? 1 : 0);
555 xCols->insertByIndex( nNewStartColumn, nNewColumns );
557 for( sal_Int32 nOffset = 0; nOffset < nNewColumns; nOffset++ )
559 Reference< XPropertySet >( xCols->getByIndex( aEnd.mnCol + nOffset + 1 ), UNO_QUERY_THROW )->
560 setPropertyValue( sSize,
561 Reference< XPropertySet >( xCols->getByIndex( aStart.mnCol + nOffset ), UNO_QUERY_THROW )->
562 getPropertyValue( sSize ) );
565 if( bUndo )
566 mpModel->EndUndo();
568 aStart.mnCol = nNewStartColumn;
569 aStart.mnRow = 0;
570 aEnd.mnCol = aStart.mnCol + nNewColumns - 1;
571 aEnd.mnRow = mxTable->getRowCount() - 1;
572 break;
575 case SID_TABLE_INSERT_ROW:
577 TableModelNotifyGuard aGuard( mxTable.get() );
579 if( bUndo )
581 mpModel->BegUndo( ImpGetResStr(STR_TABLE_INSROW ) );
582 mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
585 Reference< XTableRows > xRows( mxTable->getRows() );
586 const sal_Int32 nNewRows = (nCount == 0) ? (aEnd.mnRow - aStart.mnRow + 1) : nCount;
587 const sal_Int32 nNewRowStart = aEnd.mnRow + (bInsertAfter ? 1 : 0);
588 xRows->insertByIndex( nNewRowStart, nNewRows );
590 for( sal_Int32 nOffset = 0; nOffset < nNewRows; nOffset++ )
592 Reference< XPropertySet >( xRows->getByIndex( aEnd.mnRow + nOffset + 1 ), UNO_QUERY_THROW )->
593 setPropertyValue( sSize,
594 Reference< XPropertySet >( xRows->getByIndex( aStart.mnRow + nOffset ), UNO_QUERY_THROW )->
595 getPropertyValue( sSize ) );
598 if( bUndo )
599 mpModel->EndUndo();
601 aStart.mnCol = 0;
602 aStart.mnRow = nNewRowStart;
603 aEnd.mnCol = mxTable->getColumnCount() - 1;
604 aEnd.mnRow = aStart.mnRow + nNewRows - 1;
605 break;
609 StartSelection( aStart );
610 UpdateSelection( aEnd );
612 catch( Exception& )
614 OSL_FAIL("svx::SvxTableController::onInsert(), exception caught!");
618 // --------------------------------------------------------------------
620 void SvxTableController::onDelete( sal_uInt16 nSId )
622 ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
623 if( !pTableObj )
624 return;
626 if( mxTable.is() && hasSelectedCells() )
628 CellPos aStart, aEnd;
629 getSelectedCells( aStart, aEnd );
631 if( pTableObj->IsTextEditActive() )
632 mpView->SdrEndTextEdit(sal_True);
634 RemoveSelection();
636 bool bDeleteTable = false;
637 switch( nSId )
639 case SID_TABLE_DELETE_COL:
641 const sal_Int32 nRemovedColumns = aEnd.mnCol - aStart.mnCol + 1;
642 if( nRemovedColumns == mxTable->getColumnCount() )
644 bDeleteTable = true;
646 else
648 Reference< XTableColumns > xCols( mxTable->getColumns() );
649 xCols->removeByIndex( aStart.mnCol, nRemovedColumns );
651 break;
654 case SID_TABLE_DELETE_ROW:
656 const sal_Int32 nRemovedRows = aEnd.mnRow - aStart.mnRow + 1;
657 if( nRemovedRows == mxTable->getRowCount() )
659 bDeleteTable = true;
661 else
663 Reference< XTableRows > xRows( mxTable->getRows() );
664 xRows->removeByIndex( aStart.mnRow, nRemovedRows );
666 break;
670 if( bDeleteTable )
671 mpView->DeleteMarkedObj();
672 else
673 UpdateTableShape();
677 // --------------------------------------------------------------------
679 void SvxTableController::onSelect( sal_uInt16 nSId )
681 if( mxTable.is() )
683 const sal_Int32 nRowCount = mxTable->getRowCount();
684 const sal_Int32 nColCount = mxTable->getColumnCount();
685 if( nRowCount && nColCount )
687 CellPos aStart, aEnd;
688 getSelectedCells( aStart, aEnd );
690 switch( nSId )
692 case SID_TABLE_SELECT_ALL:
693 aEnd.mnCol = 0; aEnd.mnRow = 0;
694 aStart.mnCol = nColCount - 1; aStart.mnRow = nRowCount - 1;
695 break;
696 case SID_TABLE_SELECT_COL:
697 aEnd.mnRow = nRowCount - 1;
698 aStart.mnRow = 0;
699 break;
700 case SID_TABLE_SELECT_ROW:
701 aEnd.mnCol = nColCount - 1;
702 aStart.mnCol = 0;
703 break;
706 StartSelection( aEnd );
707 gotoCell( aStart, true, 0 );
712 // --------------------------------------------------------------------
713 void SvxTableController::onFormatTable( SfxRequest& rReq )
715 ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
716 if( !pTableObj )
717 return;
719 const SfxItemSet* pArgs = rReq.GetArgs();
721 if( !pArgs && pTableObj->GetModel() )
723 SfxItemSet aNewAttr( pTableObj->GetModel()->GetItemPool() );
724 MergeAttrFromSelectedCells(aNewAttr, sal_False);
726 // merge drawing layer text distance items into SvxBoxItem used by the dialog
727 SvxBoxItem aBoxItem( static_cast< const SvxBoxItem& >( aNewAttr.Get( SDRATTR_TABLE_BORDER ) ) );
728 aBoxItem.SetDistance( sal::static_int_cast< sal_uInt16 >( ((SdrTextLeftDistItem&)(aNewAttr.Get(SDRATTR_TEXT_LEFTDIST))).GetValue()), BOX_LINE_LEFT );
729 aBoxItem.SetDistance( sal::static_int_cast< sal_uInt16 >( ((SdrTextRightDistItem&)(aNewAttr.Get(SDRATTR_TEXT_RIGHTDIST))).GetValue()), BOX_LINE_RIGHT );
730 aBoxItem.SetDistance( sal::static_int_cast< sal_uInt16 >( ((SdrTextUpperDistItem&)(aNewAttr.Get(SDRATTR_TEXT_UPPERDIST))).GetValue()), BOX_LINE_TOP );
731 aBoxItem.SetDistance( sal::static_int_cast< sal_uInt16 >( ((SdrTextLowerDistItem&)(aNewAttr.Get(SDRATTR_TEXT_LOWERDIST))).GetValue()), BOX_LINE_BOTTOM );
732 aNewAttr.Put( aBoxItem );
734 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
735 std::auto_ptr< SfxAbstractTabDialog > pDlg( pFact ? pFact->CreateSvxFormatCellsDialog( NULL, &aNewAttr, pTableObj->GetModel(), pTableObj) : 0 );
736 if( pDlg.get() && pDlg->Execute() )
738 SfxItemSet aNewSet( *(pDlg->GetOutputItemSet ()) );
740 SvxBoxItem aNewBoxItem( static_cast< const SvxBoxItem& >( aNewSet.Get( SDRATTR_TABLE_BORDER ) ) );
742 if( aNewBoxItem.GetDistance( BOX_LINE_LEFT ) != aBoxItem.GetDistance( BOX_LINE_LEFT ) )
743 aNewSet.Put(SdrTextLeftDistItem( aNewBoxItem.GetDistance( BOX_LINE_LEFT ) ) );
745 if( aNewBoxItem.GetDistance( BOX_LINE_RIGHT ) != aBoxItem.GetDistance( BOX_LINE_RIGHT ) )
746 aNewSet.Put(SdrTextRightDistItem( aNewBoxItem.GetDistance( BOX_LINE_RIGHT ) ) );
748 if( aNewBoxItem.GetDistance( BOX_LINE_TOP ) != aBoxItem.GetDistance( BOX_LINE_TOP ) )
749 aNewSet.Put(SdrTextUpperDistItem( aNewBoxItem.GetDistance( BOX_LINE_TOP ) ) );
751 if( aNewBoxItem.GetDistance( BOX_LINE_BOTTOM ) != aBoxItem.GetDistance( BOX_LINE_BOTTOM ) )
752 aNewSet.Put(SdrTextLowerDistItem( aNewBoxItem.GetDistance( BOX_LINE_BOTTOM ) ) );
754 SetAttrToSelectedCells(aNewSet, sal_False);
756 UpdateTableShape();
760 // --------------------------------------------------------------------
762 void SvxTableController::Execute( SfxRequest& rReq )
764 const sal_uInt16 nSId = rReq.GetSlot();
765 switch( nSId )
767 case SID_TABLE_INSERT_ROW:
768 case SID_TABLE_INSERT_COL:
769 onInsert( nSId, rReq.GetArgs() );
770 break;
771 case SID_TABLE_DELETE_ROW:
772 case SID_TABLE_DELETE_COL:
773 onDelete( nSId );
774 break;
775 case SID_TABLE_SELECT_ALL:
776 case SID_TABLE_SELECT_COL:
777 case SID_TABLE_SELECT_ROW:
778 onSelect( nSId );
779 break;
780 case SID_FORMAT_TABLE_DLG:
781 onFormatTable( rReq );
782 break;
784 case SID_FRAME_LINESTYLE:
785 case SID_FRAME_LINECOLOR:
786 case SID_ATTR_BORDER:
788 const SfxItemSet* pArgs = rReq.GetArgs();
789 if( pArgs )
790 ApplyBorderAttr( *pArgs );
792 break;
794 case SID_ATTR_FILL_STYLE:
796 const SfxItemSet* pArgs = rReq.GetArgs();
797 if( pArgs )
798 SetAttributes( *pArgs, false );
800 break;
802 case SID_TABLE_MERGE_CELLS:
803 MergeMarkedCells();
804 break;
806 case SID_TABLE_SPLIT_CELLS:
807 SplitMarkedCells();
808 break;
810 case SID_TABLE_DISTRIBUTE_COLUMNS:
811 DistributeColumns();
812 break;
814 case SID_TABLE_DISTRIBUTE_ROWS:
815 DistributeRows();
816 break;
818 case SID_TABLE_VERT_BOTTOM:
819 case SID_TABLE_VERT_CENTER:
820 case SID_TABLE_VERT_NONE:
821 SetVertical( nSId );
822 break;
824 case SID_AUTOFORMAT:
825 case SID_TABLE_SORT_DIALOG:
826 case SID_TABLE_AUTOSUM:
827 default:
828 break;
830 case SID_TABLE_STYLE:
831 SetTableStyle( rReq.GetArgs() );
832 break;
834 case SID_TABLE_STYLE_SETTINGS:
835 SetTableStyleSettings( rReq.GetArgs() );
836 break;
840 void SvxTableController::SetTableStyle( const SfxItemSet* pArgs )
842 SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
843 SdrModel* pModel = pTableObj ? pTableObj->GetModel() : 0;
845 if( !pTableObj || !pModel || !pArgs || (SFX_ITEM_SET != pArgs->GetItemState(SID_TABLE_STYLE, sal_False)) )
846 return;
848 const SfxStringItem* pArg = dynamic_cast< const SfxStringItem* >( &pArgs->Get( SID_TABLE_STYLE ) );
849 if( pArg && mxTable.is() ) try
851 Reference< XStyleFamiliesSupplier > xSFS( pModel->getUnoModel(), UNO_QUERY_THROW );
852 Reference< XNameAccess > xFamilyNameAccess( xSFS->getStyleFamilies(), UNO_QUERY_THROW );
853 const OUString sFamilyName( RTL_CONSTASCII_USTRINGPARAM( "table" ) );
854 Reference< XNameAccess > xTableFamilyAccess( xFamilyNameAccess->getByName( sFamilyName ), UNO_QUERY_THROW );
856 if( xTableFamilyAccess->hasByName( pArg->GetValue() ) )
858 // found table style with the same name
859 Reference< XIndexAccess > xNewTableStyle( xTableFamilyAccess->getByName( pArg->GetValue() ), UNO_QUERY_THROW );
861 const bool bUndo = pModel->IsUndoEnabled();
863 if( bUndo )
865 pModel->BegUndo( ImpGetResStr(STR_TABLE_STYLE) );
866 pModel->AddUndo( new TableStyleUndo( *pTableObj ) );
869 pTableObj->setTableStyle( xNewTableStyle );
871 const sal_Int32 nRowCount = mxTable->getRowCount();
872 const sal_Int32 nColCount = mxTable->getColumnCount();
873 for( sal_Int32 nRow = 0; nRow < nRowCount; nRow++ )
875 for( sal_Int32 nCol = 0; nCol < nColCount; nCol++ ) try
877 CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
878 if( xCell.is() )
880 SfxItemSet aSet( xCell->GetItemSet() );
881 bool bChanges = false;
882 const SfxItemSet& rStyleAttribs = xCell->GetStyleSheet()->GetItemSet();
884 for ( sal_uInt16 nWhich = SDRATTR_START; nWhich <= SDRATTR_TABLE_LAST; nWhich++ )
886 if( (rStyleAttribs.GetItemState( nWhich ) == SFX_ITEM_ON) && (aSet.GetItemState( nWhich ) == SFX_ITEM_ON) )
888 aSet.ClearItem( nWhich );
889 bChanges = true;
893 if( bChanges )
895 if( bUndo )
896 xCell->AddUndo();
898 xCell->SetMergedItemSetAndBroadcast( aSet, sal_True );
902 catch( Exception& )
904 OSL_FAIL( "svx::SvxTableController::SetTableStyle(), exception caught!" );
908 if( bUndo )
909 pModel->EndUndo();
912 catch( Exception& )
914 OSL_FAIL( "svx::SvxTableController::SetTableStyle(), exception caught!" );
918 void SvxTableController::SetTableStyleSettings( const SfxItemSet* pArgs )
920 SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
921 SdrModel* pModel = pTableObj ? pTableObj->GetModel() : 0;
923 if( !pTableObj || !pModel )
924 return;
926 TableStyleSettings aSettings( pTableObj->getTableStyleSettings() );
928 const SfxPoolItem *pPoolItem=NULL;
930 if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USEFIRSTROWSTYLE, sal_False,&pPoolItem)) )
931 aSettings.mbUseFirstRow = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
933 if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USELASTROWSTYLE, sal_False,&pPoolItem)) )
934 aSettings.mbUseLastRow = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
936 if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USEBANDINGROWSTYLE, sal_False,&pPoolItem)) )
937 aSettings.mbUseRowBanding = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
939 if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USEFIRSTCOLUMNSTYLE, sal_False,&pPoolItem)) )
940 aSettings.mbUseFirstColumn = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
942 if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USELASTCOLUMNSTYLE, sal_False,&pPoolItem)) )
943 aSettings.mbUseLastColumn = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
945 if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USEBANDINGCOLUMNSTYLE, sal_False,&pPoolItem)) )
946 aSettings.mbUseColumnBanding = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
948 if( aSettings == pTableObj->getTableStyleSettings() )
949 return;
951 const bool bUndo = pModel->IsUndoEnabled();
953 if( bUndo )
955 pModel->BegUndo( ImpGetResStr(STR_TABLE_STYLE_SETTINGS) );
956 pModel->AddUndo( new TableStyleUndo( *pTableObj ) );
959 pTableObj->setTableStyleSettings( aSettings );
961 if( bUndo )
962 pModel->EndUndo();
965 void SvxTableController::SetVertical( sal_uInt16 nSId )
967 SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
968 if( mxTable.is() && pTableObj )
970 TableModelNotifyGuard aGuard( mxTable.get() );
972 CellPos aStart, aEnd;
973 getSelectedCells( aStart, aEnd );
975 SdrTextVertAdjust eAdj = SDRTEXTVERTADJUST_TOP;
977 switch( nSId )
979 case SID_TABLE_VERT_BOTTOM:
980 eAdj = SDRTEXTVERTADJUST_BOTTOM;
981 break;
982 case SID_TABLE_VERT_CENTER:
983 eAdj = SDRTEXTVERTADJUST_CENTER;
984 break;
985 //case SID_TABLE_VERT_NONE:
986 default:
987 break;
990 SdrTextVertAdjustItem aItem( eAdj );
992 for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
994 for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
996 CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
997 if( xCell.is() )
998 xCell->SetMergedItem(aItem);
1002 UpdateTableShape();
1006 void SvxTableController::MergeMarkedCells()
1008 CellPos aStart, aEnd;
1009 getSelectedCells( aStart, aEnd );
1010 SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1011 if( pTableObj )
1013 if( pTableObj->IsTextEditActive() )
1014 mpView->SdrEndTextEdit(sal_True);
1016 TableModelNotifyGuard aGuard( mxTable.get() );
1017 MergeRange( aStart.mnCol, aStart.mnRow, aEnd.mnCol, aEnd.mnRow );
1021 void SvxTableController::SplitMarkedCells()
1023 if( mxTable.is() )
1025 CellPos aStart, aEnd;
1026 getSelectedCells( aStart, aEnd );
1028 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
1029 std::auto_ptr< SvxAbstractSplittTableDialog > xDlg( pFact ? pFact->CreateSvxSplittTableDialog( NULL, false, 99, 99 ) : 0 );
1030 if( xDlg.get() && xDlg->Execute() )
1032 const sal_Int32 nCount = xDlg->GetCount() - 1;
1033 if( nCount < 1 )
1034 return;
1036 getSelectedCells( aStart, aEnd );
1038 Reference< XMergeableCellRange > xRange( mxTable->createCursorByRange( mxTable->getCellRangeByPosition( aStart.mnCol, aStart.mnRow, aEnd.mnCol, aEnd.mnRow ) ), UNO_QUERY_THROW );
1040 const sal_Int32 nRowCount = mxTable->getRowCount();
1041 const sal_Int32 nColCount = mxTable->getColumnCount();
1044 SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
1045 if( pTableObj )
1047 if( pTableObj->IsTextEditActive() )
1048 mpView->SdrEndTextEdit(sal_True);
1050 TableModelNotifyGuard aGuard( mxTable.get() );
1052 const bool bUndo = mpModel && mpModel->IsUndoEnabled();
1053 if( bUndo )
1055 mpModel->BegUndo( ImpGetResStr(STR_TABLE_SPLIT) );
1056 mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
1059 if( xDlg->IsHorizontal() )
1061 xRange->split( 0, nCount );
1063 else
1065 xRange->split( nCount, 0 );
1068 if( bUndo )
1069 mpModel->EndUndo();
1071 aEnd.mnRow += mxTable->getRowCount() - nRowCount;
1072 aEnd.mnCol += mxTable->getColumnCount() - nColCount;
1074 setSelectedCells( aStart, aEnd );
1079 void SvxTableController::DistributeColumns()
1081 SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
1082 if( pTableObj )
1084 const bool bUndo = mpModel && mpModel->IsUndoEnabled();
1085 if( bUndo )
1087 mpModel->BegUndo( ImpGetResStr(STR_TABLE_DISTRIBUTE_COLUMNS) );
1088 mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
1091 CellPos aStart, aEnd;
1092 getSelectedCells( aStart, aEnd );
1093 pTableObj->DistributeColumns( aStart.mnCol, aEnd.mnCol );
1095 if( bUndo )
1096 mpModel->EndUndo();
1100 void SvxTableController::DistributeRows()
1102 SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
1103 if( pTableObj )
1105 const bool bUndo = mpModel && mpModel->IsUndoEnabled();
1106 if( bUndo )
1108 mpModel->BegUndo( ImpGetResStr(STR_TABLE_DISTRIBUTE_ROWS) );
1109 mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
1112 CellPos aStart, aEnd;
1113 getSelectedCells( aStart, aEnd );
1114 pTableObj->DistributeRows( aStart.mnRow, aEnd.mnRow );
1116 if( bUndo )
1117 mpModel->EndUndo();
1121 bool SvxTableController::DeleteMarked()
1123 if( mbCellSelectionMode )
1125 if( mxTable.is() )
1127 CellPos aStart, aEnd;
1128 getSelectedCells( aStart, aEnd );
1129 for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
1131 for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
1133 CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
1134 if( xCell.is() )
1135 xCell->SetOutlinerParaObject( 0 );
1139 UpdateTableShape();
1140 return true;
1144 return false;
1147 bool SvxTableController::GetStyleSheet( SfxStyleSheet*& rpStyleSheet ) const
1149 if( hasSelectedCells() )
1151 rpStyleSheet = 0;
1153 if( mxTable.is() )
1155 SfxStyleSheet* pRet=0;
1156 bool b1st=true;
1158 CellPos aStart, aEnd;
1159 const_cast<SvxTableController&>(*this).getSelectedCells( aStart, aEnd );
1161 for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
1163 for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
1165 CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
1166 if( xCell.is() )
1168 SfxStyleSheet* pSS=xCell->GetStyleSheet();
1169 if(b1st)
1171 pRet=pSS;
1173 else if(pRet != pSS)
1175 return true;
1177 b1st=false;
1181 rpStyleSheet = pRet;
1182 return true;
1185 return false;
1188 bool SvxTableController::SetStyleSheet( SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr )
1190 if( hasSelectedCells() && (!pStyleSheet || pStyleSheet->GetFamily() == SFX_STYLE_FAMILY_FRAME) )
1192 if( mxTable.is() )
1194 CellPos aStart, aEnd;
1195 getSelectedCells( aStart, aEnd );
1197 for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
1199 for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
1201 CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
1202 if( xCell.is() )
1203 xCell->SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
1207 UpdateTableShape();
1208 return true;
1211 return false;
1214 // --------------------------------------------------------------------
1215 // internals
1216 // --------------------------------------------------------------------
1218 bool SvxTableController::checkTableObject()
1220 return mxTableObj.is();
1223 // --------------------------------------------------------------------
1225 sal_uInt16 SvxTableController::getKeyboardAction( const KeyEvent& rKEvt, Window* /*pWindow*/ )
1227 const bool bMod1 = rKEvt.GetKeyCode().IsMod1(); // ctrl
1228 const bool bMod2 = rKEvt.GetKeyCode().IsMod2() != 0; // Alt
1230 const bool bTextEdit = mpView->IsTextEdit();
1232 sal_uInt16 nAction = ACTION_HANDLED_BY_VIEW;
1234 ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1235 if( !pTableObj )
1236 return nAction;
1238 // handle special keys
1239 const sal_Int16 nCode = rKEvt.GetKeyCode().GetCode();
1240 switch( nCode )
1242 case awt::Key::ESCAPE: // handle escape
1244 if( bTextEdit )
1246 // escape during text edit ends text edit
1247 nAction = ACTION_STOP_TEXT_EDIT;
1249 if( mbCellSelectionMode )
1251 // escape with selected cells removes selection
1252 nAction = ACTION_REMOVE_SELECTION;
1254 break;
1256 case awt::Key::RETURN: // handle return
1258 if( !bMod1 && !bMod2 && !bTextEdit )
1260 // when not already editing, return starts text edit
1261 setSelectionStart( pTableObj->getFirstCell() );
1262 nAction = ACTION_EDIT_CELL;
1264 break;
1266 case awt::Key::F2: // f2 toggles text edit
1268 if( bMod1 || bMod2 ) // f2 with modifiers is handled by the view
1271 else if( bTextEdit )
1273 // f2 during text edit stops text edit
1274 nAction = ACTION_STOP_TEXT_EDIT;
1276 else if( mbCellSelectionMode )
1278 // f2 with selected cells removes selection
1279 nAction = ACTION_REMOVE_SELECTION;
1281 else
1283 // f2 with no selection and no text edit starts text edit
1284 setSelectionStart( pTableObj->getFirstCell() );
1285 nAction = ACTION_EDIT_CELL;
1287 break;
1289 case awt::Key::HOME:
1290 case awt::Key::NUM7:
1292 if( (bMod1 || bMod2) && (bTextEdit || mbCellSelectionMode) )
1294 if( bMod1 && !bMod2 )
1296 // strg + home jumps to first cell
1297 nAction = ACTION_GOTO_FIRST_CELL;
1299 else if( !bMod1 && bMod2 )
1301 // alt + home jumps to first column
1302 nAction = ACTION_GOTO_FIRST_COLUMN;
1305 break;
1307 case awt::Key::END:
1308 case awt::Key::NUM1:
1310 if( (bMod1 || bMod2) && (bTextEdit || mbCellSelectionMode) )
1312 if( bMod1 && !bMod2 )
1314 // strg + end jumps to last cell
1315 nAction = ACTION_GOTO_LAST_CELL;
1317 else if( !bMod1 && bMod2 )
1319 // alt + home jumps to last column
1320 nAction = ACTION_GOTO_LAST_COLUMN;
1323 break;
1326 case awt::Key::TAB:
1328 if( bTextEdit || mbCellSelectionMode )
1329 nAction = ACTION_TAB;
1330 break;
1333 case awt::Key::UP:
1334 case awt::Key::NUM8:
1335 case awt::Key::DOWN:
1336 case awt::Key::NUM2:
1337 case awt::Key::LEFT:
1338 case awt::Key::NUM4:
1339 case awt::Key::RIGHT:
1340 case awt::Key::NUM6:
1342 bool bTextMove = false;
1344 if( !bMod1 && bMod2 )
1346 if( (nCode == awt::Key::UP) || (nCode == awt::Key::NUM8) )
1348 nAction = ACTION_GOTO_LEFT_CELL;
1350 else if( (nCode == awt::Key::DOWN) || (nCode == awt::Key::NUM2) )
1352 nAction = ACTION_GOTO_RIGHT_CELL;
1354 break;
1357 if( !bTextMove )
1359 OutlinerView* pOLV = mpView->GetTextEditOutlinerView();
1360 if( pOLV )
1362 RemoveSelection();
1363 // during text edit, check if we navigate out of the cell
1364 ESelection aOldSelection = pOLV->GetSelection();
1365 pOLV->PostKeyEvent(rKEvt);
1366 bTextMove = pOLV && ( aOldSelection.IsEqual(pOLV->GetSelection()) );
1367 if( !bTextMove )
1369 nAction = ACTION_NONE;
1374 if( mbCellSelectionMode || bTextMove )
1376 // no text edit, navigate in cells if selection active
1377 switch( nCode )
1379 case awt::Key::LEFT:
1380 case awt::Key::NUM4:
1381 nAction = ACTION_GOTO_LEFT_CELL;
1382 break;
1383 case awt::Key::RIGHT:
1384 case awt::Key::NUM6:
1385 nAction = ACTION_GOTO_RIGHT_CELL;
1386 break;
1387 case awt::Key::DOWN:
1388 case awt::Key::NUM2:
1389 nAction = ACTION_GOTO_DOWN_CELL;
1390 break;
1391 case awt::Key::UP:
1392 case awt::Key::NUM8:
1393 nAction = ACTION_GOTO_UP_CELL;
1394 break;
1397 break;
1399 case awt::Key::PAGEUP:
1400 if( bMod2 )
1401 nAction = ACTION_GOTO_FIRST_ROW;
1402 break;
1404 case awt::Key::PAGEDOWN:
1405 if( bMod2 )
1406 nAction = ACTION_GOTO_LAST_ROW;
1407 break;
1409 return nAction;
1412 bool SvxTableController::executeAction( sal_uInt16 nAction, bool bSelect, Window* pWindow )
1414 ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1415 if( !pTableObj )
1416 return false;
1418 switch( nAction )
1420 case ACTION_GOTO_FIRST_CELL:
1422 gotoCell( pTableObj->getFirstCell(), bSelect, pWindow, nAction );
1423 break;
1426 case ACTION_GOTO_LEFT_CELL:
1428 gotoCell( pTableObj->getLeftCell( getSelectionEnd(), !bSelect ), bSelect, pWindow, nAction );
1429 break;
1432 case ACTION_GOTO_RIGHT_CELL:
1434 gotoCell( pTableObj->getRightCell( getSelectionEnd(), !bSelect ), bSelect, pWindow, nAction);
1435 break;
1438 case ACTION_GOTO_LAST_CELL:
1440 gotoCell( pTableObj->getLastCell(), bSelect, pWindow, nAction );
1441 break;
1444 case ACTION_GOTO_FIRST_COLUMN:
1446 CellPos aPos( pTableObj->getFirstCell().mnCol, getSelectionEnd().mnRow );
1447 gotoCell( aPos, bSelect, pWindow, nAction );
1448 break;
1451 case ACTION_GOTO_LAST_COLUMN:
1453 CellPos aPos( pTableObj->getLastCell().mnCol, getSelectionEnd().mnRow );
1454 gotoCell( aPos, bSelect, pWindow, nAction );
1455 break;
1458 case ACTION_GOTO_FIRST_ROW:
1460 CellPos aPos( getSelectionEnd().mnCol, pTableObj->getFirstCell().mnRow );
1461 gotoCell( aPos, bSelect, pWindow, nAction );
1462 break;
1465 case ACTION_GOTO_UP_CELL:
1467 gotoCell( pTableObj->getUpCell(getSelectionEnd(), !bSelect), bSelect, pWindow, nAction );
1468 break;
1471 case ACTION_GOTO_DOWN_CELL:
1473 gotoCell( pTableObj->getDownCell(getSelectionEnd(), !bSelect), bSelect, pWindow, nAction );
1474 break;
1477 case ACTION_GOTO_LAST_ROW:
1479 CellPos aPos( getSelectionEnd().mnCol, pTableObj->getLastCell().mnRow );
1480 gotoCell( aPos, bSelect, pWindow, nAction );
1481 break;
1484 case ACTION_EDIT_CELL:
1485 EditCell( getSelectionStart(), pWindow, 0, nAction );
1486 break;
1488 case ACTION_STOP_TEXT_EDIT:
1489 StopTextEdit();
1490 break;
1492 case ACTION_REMOVE_SELECTION:
1493 RemoveSelection();
1494 break;
1496 case ACTION_START_SELECTION:
1497 StartSelection( getSelectionStart() );
1498 break;
1500 case ACTION_TAB:
1502 if( bSelect )
1503 gotoCell( pTableObj->getPreviousCell( getSelectionEnd(), true ), false, pWindow, nAction );
1504 else
1506 CellPos aSelectionEnd( getSelectionEnd() );
1507 CellPos aNextCell( pTableObj->getNextCell( aSelectionEnd, true ) );
1508 if( aSelectionEnd == aNextCell )
1510 onInsert( SID_TABLE_INSERT_ROW, 0 );
1511 aNextCell = pTableObj->getNextCell( aSelectionEnd, true );
1513 gotoCell( aNextCell, false, pWindow, nAction );
1515 break;
1519 return nAction != ACTION_HANDLED_BY_VIEW;
1522 // --------------------------------------------------------------------
1524 void SvxTableController::gotoCell( const CellPos& rPos, bool bSelect, Window* pWindow, sal_uInt16 nAction )
1526 if( mxTableObj.is() && static_cast<SdrTableObj*>(mxTableObj.get())->IsTextEditActive() )
1527 mpView->SdrEndTextEdit(sal_True);
1529 if( bSelect )
1531 maCursorLastPos = rPos;
1532 if( mxTableObj.is() )
1533 static_cast< SdrTableObj* >( mxTableObj.get() )->setActiveCell( rPos );
1535 if( !mbCellSelectionMode )
1537 setSelectedCells( maCursorFirstPos, rPos );
1539 else
1541 UpdateSelection( rPos );
1544 else
1546 RemoveSelection();
1547 EditCell( rPos, pWindow, 0, nAction );
1551 // --------------------------------------------------------------------
1553 const CellPos& SvxTableController::getSelectionStart()
1555 checkCell( maCursorFirstPos );
1556 return maCursorFirstPos;
1559 // --------------------------------------------------------------------
1561 void SvxTableController::setSelectionStart( const CellPos& rPos )
1563 maCursorFirstPos = rPos;
1566 // --------------------------------------------------------------------
1568 const CellPos& SvxTableController::getSelectionEnd()
1570 checkCell( maCursorLastPos );
1571 return maCursorLastPos;
1574 // --------------------------------------------------------------------
1576 void SvxTableController::MergeRange( sal_Int32 nFirstCol, sal_Int32 nFirstRow, sal_Int32 nLastCol, sal_Int32 nLastRow )
1578 if( mxTable.is() ) try
1580 Reference< XMergeableCellRange > xRange( mxTable->createCursorByRange( mxTable->getCellRangeByPosition( nFirstCol, nFirstRow,nLastCol, nLastRow ) ), UNO_QUERY_THROW );
1581 if( xRange->isMergeable() )
1583 const bool bUndo = mpModel && mpModel->IsUndoEnabled();
1584 if( bUndo )
1586 mpModel->BegUndo( ImpGetResStr(STR_TABLE_MERGE) );
1587 mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*mxTableObj.get()) );
1590 xRange->merge();
1592 if( bUndo )
1593 mpModel->EndUndo();
1596 catch( Exception& )
1598 DBG_ASSERT( false, "sdr::table::SvxTableController::MergeRange(), exception caught!" );
1604 // --------------------------------------------------------------------
1606 void SvxTableController::checkCell( CellPos& rPos )
1608 if( mxTable.is() ) try
1610 if( rPos.mnCol >= mxTable->getColumnCount() )
1611 rPos.mnCol = mxTable->getColumnCount()-1;
1613 if( rPos.mnRow >= mxTable->getRowCount() )
1614 rPos.mnRow = mxTable->getRowCount()-1;
1616 catch( Exception& )
1618 OSL_FAIL("sdr::table::SvxTableController::checkCell(), exception caught!" );
1622 // --------------------------------------------------------------------
1624 void SvxTableController::findMergeOrigin( CellPos& rPos )
1626 if( mxTable.is() ) try
1628 Reference< XMergeableCell > xCell( mxTable->getCellByPosition( rPos.mnCol, rPos.mnRow ), UNO_QUERY_THROW );
1629 if( xCell.is() && xCell->isMerged() )
1631 ::findMergeOrigin( mxTable, rPos.mnCol, rPos.mnRow, rPos.mnCol, rPos.mnRow );
1634 catch( Exception& )
1636 OSL_FAIL("sdr::table::SvxTableController::findMergeOrigin(), exception caught!" );
1640 // --------------------------------------------------------------------
1642 void SvxTableController::EditCell( const CellPos& rPos, ::Window* pWindow, const awt::MouseEvent* pMouseEvent /*= 0*/, sal_uInt16 nAction /*= ACTION_NONE */ )
1644 SdrPageView* pPV = mpView->GetSdrPageView();
1646 ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1647 if( pTableObj && pTableObj->GetPage() == pPV->GetPage() )
1649 bool bEmptyOutliner = false;
1651 if(!pTableObj->GetOutlinerParaObject() && mpView->GetTextEditOutliner())
1653 ::Outliner* pOutl = mpView->GetTextEditOutliner();
1654 sal_uIntPtr nParaAnz = pOutl->GetParagraphCount();
1655 Paragraph* p1stPara = pOutl->GetParagraph( 0 );
1657 if(nParaAnz==1 && p1stPara)
1659 // Bei nur einem Pararaph
1660 if (pOutl->GetText(p1stPara).Len() == 0)
1662 bEmptyOutliner = true;
1667 CellPos aPos( rPos );
1668 findMergeOrigin( aPos );
1670 if( pTableObj != mpView->GetTextEditObject() || bEmptyOutliner || !pTableObj->IsTextEditActive( aPos ) )
1672 if( pTableObj->IsTextEditActive() )
1673 mpView->SdrEndTextEdit(sal_True);
1675 pTableObj->setActiveCell( aPos );
1677 // create new outliner, owner will be the SdrObjEditView
1678 SdrOutliner* pOutl = SdrMakeOutliner( OUTLINERMODE_OUTLINEOBJECT, mpModel );
1679 if( pTableObj->IsVerticalWriting() )
1680 pOutl->SetVertical( sal_True );
1682 if(mpView->SdrBeginTextEdit(pTableObj, pPV, pWindow, sal_True, pOutl))
1684 maCursorLastPos = maCursorFirstPos = rPos;
1686 OutlinerView* pOLV = mpView->GetTextEditOutlinerView();
1688 bool bNoSel = true;
1690 if( pMouseEvent )
1692 ::MouseEvent aMEvt( *pMouseEvent );
1694 SdrViewEvent aVEvt;
1695 SdrHitKind eHit = mpView->PickAnything(aMEvt, SDRMOUSEBUTTONDOWN, aVEvt);
1697 if (eHit == SDRHIT_TEXTEDIT)
1699 // Text getroffen
1700 pOLV->MouseButtonDown(aMEvt);
1701 pOLV->MouseMove(aMEvt);
1702 pOLV->MouseButtonUp(aMEvt);
1703 // pOLV->MouseButtonDown(aMEvt);
1704 bNoSel = false;
1706 else
1708 nAction = ACTION_GOTO_LEFT_CELL;
1712 if( bNoSel )
1714 // Move cursor to end of text
1715 ESelection aNewSelection;
1717 const WritingMode eMode = pTableObj->GetWritingMode();
1718 if( ((nAction == ACTION_GOTO_LEFT_CELL) || (nAction == ACTION_GOTO_RIGHT_CELL)) && (eMode != WritingMode_TB_RL) )
1720 const bool bLast = ((nAction == ACTION_GOTO_LEFT_CELL) && (eMode == WritingMode_LR_TB)) ||
1721 ((nAction == ACTION_GOTO_RIGHT_CELL) && (eMode == WritingMode_RL_TB));
1723 if( bLast )
1724 aNewSelection = ESelection(EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND, EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND);
1726 pOLV->SetSelection(aNewSelection);
1733 // --------------------------------------------------------------------
1735 bool SvxTableController::StopTextEdit()
1737 if(mpView->IsTextEdit())
1739 mpView->SdrEndTextEdit();
1740 mpView->SetCurrentObj(OBJ_TABLE);
1741 mpView->SetEditMode(SDREDITMODE_EDIT);
1742 return true;
1744 else
1746 return false;
1750 // --------------------------------------------------------------------
1752 void SvxTableController::getSelectedCells( CellPos& rFirst, CellPos& rLast )
1754 if( mbCellSelectionMode )
1756 checkCell( maCursorFirstPos );
1757 checkCell( maCursorLastPos );
1759 rFirst.mnCol = std::min( maCursorFirstPos.mnCol, maCursorLastPos.mnCol );
1760 rFirst.mnRow = std::min( maCursorFirstPos.mnRow, maCursorLastPos.mnRow );
1761 rLast.mnCol = std::max( maCursorFirstPos.mnCol, maCursorLastPos.mnCol );
1762 rLast.mnRow = std::max( maCursorFirstPos.mnRow, maCursorLastPos.mnRow );
1764 bool bExt = false;
1765 if( mxTable.is() ) do
1767 bExt = false;
1768 for( sal_Int32 nRow = rFirst.mnRow; nRow <= rLast.mnRow && !bExt; nRow++ )
1770 for( sal_Int32 nCol = rFirst.mnCol; nCol <= rLast.mnCol && !bExt; nCol++ )
1772 Reference< XMergeableCell > xCell( mxTable->getCellByPosition( nCol, nRow ), UNO_QUERY );
1773 if( !xCell.is() )
1774 continue;
1776 if( xCell->isMerged() )
1778 CellPos aPos( nCol, nRow );
1779 findMergeOrigin( aPos );
1780 if( (aPos.mnCol < rFirst.mnCol) || (aPos.mnRow < rFirst.mnRow) )
1782 rFirst.mnCol = std::min( rFirst.mnCol, aPos.mnCol );
1783 rFirst.mnRow = std::min( rFirst.mnRow, aPos.mnRow );
1784 bExt = true;
1787 else
1789 if( ((nCol + xCell->getColumnSpan() - 1) > rLast.mnCol) || (nRow + xCell->getRowSpan() - 1 ) > rLast.mnRow )
1791 rLast.mnCol = std::max( rLast.mnCol, nCol + xCell->getColumnSpan() - 1 );
1792 rLast.mnRow = std::max( rLast.mnRow, nRow + xCell->getRowSpan() - 1 );
1793 bExt = true;
1799 while(bExt);
1801 else if( mpView && mpView->IsTextEdit() )
1803 rFirst = getSelectionStart();
1804 findMergeOrigin( rFirst );
1805 rLast = rFirst;
1807 if( mxTable.is() )
1809 Reference< XMergeableCell > xCell( mxTable->getCellByPosition( rLast.mnCol, rLast.mnRow ), UNO_QUERY );
1810 if( xCell.is() )
1812 rLast.mnCol += xCell->getColumnSpan() - 1;
1813 rLast.mnRow += xCell->getRowSpan() - 1;
1817 else
1819 rFirst.mnCol = 0;
1820 rFirst.mnRow = 0;
1821 if( mxTable.is() )
1823 rLast.mnRow = mxTable->getRowCount()-1;
1824 rLast.mnCol = mxTable->getColumnCount()-1;
1826 else
1828 rLast.mnRow = 0;
1829 rLast.mnCol = 0;
1834 // --------------------------------------------------------------------
1836 void SvxTableController::StartSelection( const CellPos& rPos )
1838 StopTextEdit();
1839 mbCellSelectionMode = true;
1840 maCursorLastPos = maCursorFirstPos = rPos;
1841 mpView->MarkListHasChanged();
1844 // --------------------------------------------------------------------
1846 void SvxTableController::setSelectedCells( const CellPos& rStart, const CellPos& rEnd )
1848 StopTextEdit();
1849 mbCellSelectionMode = true;
1850 maCursorFirstPos = rStart;
1851 UpdateSelection( rEnd );
1854 // --------------------------------------------------------------------
1856 void SvxTableController::UpdateSelection( const CellPos& rPos )
1858 maCursorLastPos = rPos;
1859 mpView->MarkListHasChanged();
1862 // --------------------------------------------------------------------
1864 void SvxTableController::clearSelection()
1866 RemoveSelection();
1869 // --------------------------------------------------------------------
1871 void SvxTableController::selectAll()
1873 if( mxTable.is() )
1875 CellPos aPos1, aPos2( mxTable->getColumnCount()-1, mxTable->getRowCount()-1 );
1876 if( (aPos2.mnCol >= 0) && (aPos2.mnRow >= 0) )
1878 setSelectedCells( aPos1, aPos2 );
1883 // --------------------------------------------------------------------
1885 void SvxTableController::RemoveSelection()
1887 if( mbCellSelectionMode )
1889 mbCellSelectionMode = false;
1890 mpView->MarkListHasChanged();
1894 // --------------------------------------------------------------------
1896 void SvxTableController::onTableModified()
1898 if( mnUpdateEvent == 0 )
1899 mnUpdateEvent = Application::PostUserEvent( LINK( this, SvxTableController, UpdateHdl ) );
1901 // --------------------------------------------------------------------
1903 void SvxTableController::updateSelectionOverlay()
1905 destroySelectionOverlay();
1906 if( mbCellSelectionMode )
1908 ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1909 if( pTableObj )
1911 sdr::overlay::OverlayObjectCell::RangeVector aRanges;
1913 Rectangle aRect;
1914 CellPos aStart,aEnd;
1915 getSelectedCells( aStart, aEnd );
1916 pTableObj->getCellBounds( aStart, aRect );
1918 basegfx::B2DRange a2DRange( basegfx::B2DPoint(aRect.Left(), aRect.Top()) );
1919 a2DRange.expand( basegfx::B2DPoint(aRect.Right(), aRect.Bottom()) );
1921 findMergeOrigin( aEnd );
1922 pTableObj->getCellBounds( aEnd, aRect );
1923 a2DRange.expand( basegfx::B2DPoint(aRect.Left(), aRect.Top()) );
1924 a2DRange.expand( basegfx::B2DPoint(aRect.Right(), aRect.Bottom()) );
1925 aRanges.push_back( a2DRange );
1927 ::Color aHighlight( COL_BLUE );
1928 OutputDevice* pOutDev = mpView->GetFirstOutputDevice();
1929 if( pOutDev )
1930 aHighlight = pOutDev->GetSettings().GetStyleSettings().GetHighlightColor();
1932 const sal_uInt32 nCount = mpView->PaintWindowCount();
1933 for( sal_uInt32 nIndex = 0; nIndex < nCount; nIndex++ )
1935 SdrPaintWindow* pPaintWindow = mpView->GetPaintWindow(nIndex);
1936 if( pPaintWindow )
1938 rtl::Reference < ::sdr::overlay::OverlayManager > xOverlayManager = pPaintWindow->GetOverlayManager();
1939 if( xOverlayManager.is() )
1941 // sdr::overlay::CellOverlayType eType = sdr::overlay::CELL_OVERLAY_INVERT;
1942 sdr::overlay::CellOverlayType eType = sdr::overlay::CELL_OVERLAY_TRANSPARENT;
1944 sdr::overlay::OverlayObjectCell* pOverlay = new sdr::overlay::OverlayObjectCell( eType, aHighlight, aRanges );
1946 xOverlayManager->add(*pOverlay);
1947 mpSelectionOverlay = new ::sdr::overlay::OverlayObjectList;
1948 mpSelectionOverlay->append(*pOverlay);
1956 // --------------------------------------------------------------------
1958 void SvxTableController::destroySelectionOverlay()
1960 if( mpSelectionOverlay )
1962 delete mpSelectionOverlay;
1963 mpSelectionOverlay = 0;
1967 // --------------------------------------------------------------------
1969 void SvxTableController::MergeAttrFromSelectedCells(SfxItemSet& rAttr, bool bOnlyHardAttr) const
1971 if( mxTable.is() )
1973 CellPos aStart, aEnd;
1974 const_cast<SvxTableController&>(*this).getSelectedCells( aStart, aEnd );
1976 for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
1978 for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
1980 CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
1981 if( xCell.is() && !xCell->isMerged() )
1983 const SfxItemSet& rSet = xCell->GetItemSet();
1984 SfxWhichIter aIter(rSet);
1985 sal_uInt16 nWhich(aIter.FirstWhich());
1986 while(nWhich)
1988 if(!bOnlyHardAttr)
1990 if(SFX_ITEM_DONTCARE == rSet.GetItemState(nWhich, sal_False))
1991 rAttr.InvalidateItem(nWhich);
1992 else
1993 rAttr.MergeValue(rSet.Get(nWhich), sal_True);
1995 else if(SFX_ITEM_SET == rSet.GetItemState(nWhich, sal_False))
1997 const SfxPoolItem& rItem = rSet.Get(nWhich);
1998 rAttr.MergeValue(rItem, sal_True);
2001 nWhich = aIter.NextWhich();
2008 if( mpView->IsTextEdit() )
2013 // --------------------------------------------------------------------
2015 const sal_uInt16 CELL_BEFORE = 0x0001;
2016 const sal_uInt16 CELL_LEFT = 0x0002;
2017 const sal_uInt16 CELL_RIGHT = 0x0004;
2018 const sal_uInt16 CELL_AFTER = 0x0008;
2020 const sal_uInt16 CELL_UPPER = 0x0010;
2021 const sal_uInt16 CELL_TOP = 0x0020;
2022 const sal_uInt16 CELL_BOTTOM = 0x0040;
2023 const sal_uInt16 CELL_LOWER = 0x0080;
2025 // --------------------------------------------------------------------
2027 static void ImplSetLinePreserveColor( SvxBoxItem& rNewFrame, const SvxBorderLine* pNew, sal_uInt16 nLine )
2029 if( pNew )
2031 const SvxBorderLine* pOld = rNewFrame.GetLine(nLine);
2032 if( pOld )
2034 SvxBorderLine aNewLine( *pNew );
2035 aNewLine.SetColor( pOld->GetColor() );
2036 rNewFrame.SetLine( &aNewLine, nLine );
2037 return;
2040 rNewFrame.SetLine( pNew, nLine );
2043 // --------------------------------------------------------------------
2045 static void ImplApplyBoxItem( sal_uInt16 nCellFlags, const SvxBoxItem* pBoxItem, const SvxBoxInfoItem* pBoxInfoItem, SvxBoxItem& rNewFrame )
2047 if( (nCellFlags & (CELL_BEFORE|CELL_AFTER|CELL_UPPER|CELL_LOWER)) != 0 )
2049 // current cell is outside the selection
2051 if( (nCellFlags & ( CELL_BEFORE|CELL_AFTER)) == 0 ) // check if its not nw or ne corner
2053 if( nCellFlags & CELL_UPPER )
2055 if( pBoxInfoItem->IsValid(VALID_TOP) )
2056 rNewFrame.SetLine(0, BOX_LINE_BOTTOM );
2058 else if( nCellFlags & CELL_LOWER )
2060 if( pBoxInfoItem->IsValid(VALID_BOTTOM) )
2061 rNewFrame.SetLine( 0, BOX_LINE_TOP );
2064 else if( (nCellFlags & ( CELL_UPPER|CELL_LOWER)) == 0 ) // check if its not sw or se corner
2066 if( nCellFlags & CELL_BEFORE )
2068 if( pBoxInfoItem->IsValid(VALID_LEFT) )
2069 rNewFrame.SetLine( 0, BOX_LINE_RIGHT );
2071 else if( nCellFlags & CELL_AFTER )
2073 if( pBoxInfoItem->IsValid(VALID_RIGHT) )
2074 rNewFrame.SetLine( 0, BOX_LINE_LEFT );
2078 else
2080 // current cell is inside the selection
2082 if( (nCellFlags & CELL_LEFT) ? pBoxInfoItem->IsValid(VALID_LEFT) : pBoxInfoItem->IsValid(VALID_VERT) )
2083 rNewFrame.SetLine( (nCellFlags & CELL_LEFT) ? pBoxItem->GetLeft() : pBoxInfoItem->GetVert(), BOX_LINE_LEFT );
2085 if( (nCellFlags & CELL_RIGHT) ? pBoxInfoItem->IsValid(VALID_RIGHT) : pBoxInfoItem->IsValid(VALID_VERT) )
2086 rNewFrame.SetLine( (nCellFlags & CELL_RIGHT) ? pBoxItem->GetRight() : pBoxInfoItem->GetVert(), BOX_LINE_RIGHT );
2088 if( (nCellFlags & CELL_TOP) ? pBoxInfoItem->IsValid(VALID_TOP) : pBoxInfoItem->IsValid(VALID_HORI) )
2089 rNewFrame.SetLine( (nCellFlags & CELL_TOP) ? pBoxItem->GetTop() : pBoxInfoItem->GetHori(), BOX_LINE_TOP );
2091 if( (nCellFlags & CELL_BOTTOM) ? pBoxInfoItem->IsValid(VALID_BOTTOM) : pBoxInfoItem->IsValid(VALID_HORI) )
2092 rNewFrame.SetLine( (nCellFlags & CELL_BOTTOM) ? pBoxItem->GetBottom() : pBoxInfoItem->GetHori(), BOX_LINE_BOTTOM );
2094 // apply distance to borders
2095 if( pBoxInfoItem->IsValid( VALID_DISTANCE ) )
2096 for( sal_uInt16 nLine = 0; nLine < 4; ++nLine )
2097 rNewFrame.SetDistance( pBoxItem->GetDistance( nLine ), nLine );
2101 // --------------------------------------------------------------------
2103 static void ImplSetLineColor( SvxBoxItem& rNewFrame, sal_uInt16 nLine, const Color& rColor )
2105 const SvxBorderLine* pSourceLine = rNewFrame.GetLine( nLine );
2106 if( pSourceLine )
2108 SvxBorderLine aLine( *pSourceLine );
2109 aLine.SetColor( rColor );
2110 rNewFrame.SetLine( &aLine, nLine );
2114 // --------------------------------------------------------------------
2116 static void ImplApplyLineColorItem( sal_uInt16 nCellFlags, const SvxColorItem* pLineColorItem, SvxBoxItem& rNewFrame )
2118 const Color aColor( pLineColorItem->GetValue() );
2120 if( (nCellFlags & (CELL_LOWER|CELL_BEFORE|CELL_AFTER)) == 0 )
2121 ImplSetLineColor( rNewFrame, BOX_LINE_BOTTOM, aColor );
2123 if( (nCellFlags & (CELL_UPPER|CELL_BEFORE|CELL_AFTER)) == 0 )
2124 ImplSetLineColor( rNewFrame, BOX_LINE_TOP, aColor );
2126 if( (nCellFlags & (CELL_UPPER|CELL_LOWER|CELL_AFTER)) == 0 )
2127 ImplSetLineColor( rNewFrame, BOX_LINE_RIGHT, aColor );
2129 if( (nCellFlags & (CELL_UPPER|CELL_LOWER|CELL_BEFORE)) == 0 )
2130 ImplSetLineColor( rNewFrame, BOX_LINE_LEFT, aColor );
2133 // --------------------------------------------------------------------
2135 static void ImplApplyBorderLineItem( sal_uInt16 nCellFlags, const SvxBorderLine* pBorderLineItem, SvxBoxItem& rNewFrame )
2137 if( (nCellFlags & ( CELL_BEFORE|CELL_AFTER|CELL_UPPER|CELL_LOWER)) != 0 )
2139 if( (nCellFlags & ( CELL_BEFORE|CELL_AFTER)) == 0 ) // check if its not nw or ne corner
2141 if( nCellFlags & CELL_UPPER )
2143 if( rNewFrame.GetBottom() )
2144 ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_BOTTOM );
2146 else if( nCellFlags & CELL_LOWER )
2148 if( rNewFrame.GetTop() )
2149 ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_TOP );
2152 else if( (nCellFlags & ( CELL_UPPER|CELL_LOWER)) == 0 ) // check if its not sw or se corner
2154 if( nCellFlags & CELL_BEFORE )
2156 if( rNewFrame.GetRight() )
2157 ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_RIGHT );
2159 else if( nCellFlags & CELL_AFTER )
2161 if( rNewFrame.GetLeft() )
2162 ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_LEFT );
2166 else
2168 if( rNewFrame.GetBottom() )
2169 ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_BOTTOM );
2170 if( rNewFrame.GetTop() )
2171 ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_TOP );
2172 if( rNewFrame.GetRight() )
2173 ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_RIGHT );
2174 if( rNewFrame.GetLeft() )
2175 ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_LEFT );
2179 // --------------------------------------------------------------------
2181 void SvxTableController::ApplyBorderAttr( const SfxItemSet& rAttr )
2183 if( mxTable.is() )
2185 const sal_Int32 nRowCount = mxTable->getRowCount();
2186 const sal_Int32 nColCount = mxTable->getColumnCount();
2187 if( nRowCount && nColCount )
2189 const SvxBoxItem* pBoxItem = 0;
2190 if(SFX_ITEM_SET == rAttr.GetItemState(SDRATTR_TABLE_BORDER, sal_False) )
2191 pBoxItem = dynamic_cast< const SvxBoxItem* >( &rAttr.Get( SDRATTR_TABLE_BORDER ) );
2193 const SvxBoxInfoItem* pBoxInfoItem = 0;
2194 if(SFX_ITEM_SET == rAttr.GetItemState(SDRATTR_TABLE_BORDER_INNER, sal_False) )
2195 pBoxInfoItem = dynamic_cast< const SvxBoxInfoItem* >( &rAttr.Get( SDRATTR_TABLE_BORDER_INNER ) );
2197 const SvxColorItem* pLineColorItem = 0;
2198 if(SFX_ITEM_SET == rAttr.GetItemState(SID_FRAME_LINECOLOR, sal_False) )
2199 pLineColorItem = dynamic_cast< const SvxColorItem* >( &rAttr.Get( SID_FRAME_LINECOLOR ) );
2201 const SvxBorderLine* pBorderLineItem = 0;
2202 if(SFX_ITEM_SET == rAttr.GetItemState(SID_FRAME_LINESTYLE, sal_False) )
2203 pBorderLineItem = ((const SvxLineItem&)rAttr.Get( SID_FRAME_LINESTYLE )).GetLine();
2205 if( pBoxInfoItem && !pBoxItem )
2207 const static SvxBoxItem gaEmptyBoxItem( SDRATTR_TABLE_BORDER );
2208 pBoxItem = &gaEmptyBoxItem;
2210 else if( pBoxItem && !pBoxInfoItem )
2212 const static SvxBoxInfoItem gaEmptyBoxInfoItem( SDRATTR_TABLE_BORDER_INNER );
2213 pBoxInfoItem = &gaEmptyBoxInfoItem;
2216 CellPos aStart, aEnd;
2217 getSelectedCells( aStart, aEnd );
2219 const sal_Int32 nLastRow = std::min( aEnd.mnRow + 2, nRowCount );
2220 const sal_Int32 nLastCol = std::min( aEnd.mnCol + 2, nColCount );
2222 for( sal_Int32 nRow = std::max( aStart.mnRow - 1, (sal_Int32)0 ); nRow < nLastRow; nRow++ )
2224 sal_uInt16 nRowFlags = 0;
2225 nRowFlags |= (nRow == aStart.mnRow) ? CELL_TOP : 0;
2226 nRowFlags |= (nRow == aEnd.mnRow) ? CELL_BOTTOM : 0;
2227 nRowFlags |= (nRow < aStart.mnRow) ? CELL_UPPER : 0;
2228 nRowFlags |= (nRow > aEnd.mnRow) ? CELL_LOWER : 0;
2230 for( sal_Int32 nCol = std::max( aStart.mnCol - 1, (sal_Int32)0 ); nCol < nLastCol; nCol++ )
2232 CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
2233 if( !xCell.is() )
2234 continue;
2236 const SfxItemSet& rSet = xCell->GetItemSet();
2237 const SvxBoxItem* pOldOuter = (const SvxBoxItem*) &rSet.Get( SDRATTR_TABLE_BORDER );
2239 SvxBoxItem aNewFrame( *pOldOuter );
2241 sal_uInt16 nCellFlags = nRowFlags;
2242 nCellFlags |= (nCol == aStart.mnCol) ? CELL_LEFT : 0;
2243 nCellFlags |= (nCol == aEnd.mnCol) ? CELL_RIGHT : 0;
2244 nCellFlags |= (nCol < aStart.mnCol) ? CELL_BEFORE : 0;
2245 nCellFlags |= (nCol > aEnd.mnCol) ? CELL_AFTER : 0;
2247 if( pBoxItem && pBoxInfoItem )
2248 ImplApplyBoxItem( nCellFlags, pBoxItem, pBoxInfoItem, aNewFrame );
2250 if( pLineColorItem )
2251 ImplApplyLineColorItem( nCellFlags, pLineColorItem, aNewFrame );
2253 if( pBorderLineItem )
2254 ImplApplyBorderLineItem( nCellFlags, pBorderLineItem, aNewFrame );
2256 if (aNewFrame != *pOldOuter)
2258 SfxItemSet aAttr(*rSet.GetPool(), rSet.GetRanges());
2259 aAttr.Put(aNewFrame);
2260 xCell->SetMergedItemSetAndBroadcast( aAttr, false );
2268 // --------------------------------------------------------------------
2270 void SvxTableController::UpdateTableShape()
2272 SdrObject* pTableObj = mxTableObj.get();
2273 if( pTableObj )
2275 pTableObj->ActionChanged();
2276 pTableObj->BroadcastObjectChange();
2278 updateSelectionOverlay();
2282 // --------------------------------------------------------------------
2284 void SvxTableController::SetAttrToSelectedCells(const SfxItemSet& rAttr, bool bReplaceAll)
2286 if( mxTable.is() )
2288 const bool bUndo = mpModel && mpModel->IsUndoEnabled();
2290 if( bUndo )
2291 mpModel->BegUndo( ImpGetResStr(STR_TABLE_NUMFORMAT) );
2293 CellPos aStart, aEnd;
2294 getSelectedCells( aStart, aEnd );
2296 SfxItemSet aAttr(*rAttr.GetPool(), rAttr.GetRanges());
2297 aAttr.Put(rAttr, sal_True);
2299 const bool bFrame = (rAttr.GetItemState( SDRATTR_TABLE_BORDER ) == SFX_ITEM_SET) || (rAttr.GetItemState( SDRATTR_TABLE_BORDER_INNER ) == SFX_ITEM_SET);
2301 if( bFrame )
2303 aAttr.ClearItem( SDRATTR_TABLE_BORDER );
2304 aAttr.ClearItem( SDRATTR_TABLE_BORDER_INNER );
2307 for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
2309 for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
2311 CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
2312 if( xCell.is() )
2314 if( bUndo )
2315 xCell->AddUndo();
2316 xCell->SetMergedItemSetAndBroadcast(aAttr, bReplaceAll);
2321 if( bFrame )
2323 ApplyBorderAttr( rAttr );
2326 UpdateTableShape();
2328 if( bUndo )
2329 mpModel->EndUndo();
2334 // --------------------------------------------------------------------
2336 bool SvxTableController::GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr) const
2338 if( mxTableObj.is() && hasSelectedCells() )
2340 MergeAttrFromSelectedCells( rTargetSet, bOnlyHardAttr );
2342 if( mpView->IsTextEdit() )
2344 if( mxTableObj->GetOutlinerParaObject() )
2345 rTargetSet.Put( SvxScriptTypeItem( mxTableObj->GetOutlinerParaObject()->GetTextObject().GetScriptType() ) );
2347 OutlinerView* pTextEditOutlinerView = mpView->GetTextEditOutlinerView();
2348 if(pTextEditOutlinerView)
2350 // FALSE= InvalidItems nicht al Default, sondern als "Loecher" betrachten
2351 rTargetSet.Put(pTextEditOutlinerView->GetAttribs(), sal_False);
2352 rTargetSet.Put( SvxScriptTypeItem( pTextEditOutlinerView->GetSelectedScriptType() ), sal_False );
2356 return true;
2358 else
2360 return false;
2364 // --------------------------------------------------------------------
2366 bool SvxTableController::SetAttributes(const SfxItemSet& rSet, bool bReplaceAll)
2368 if( mbCellSelectionMode || mpView->IsTextEdit() )
2370 SetAttrToSelectedCells( rSet, bReplaceAll );
2371 return true;
2373 return false;
2376 // --------------------------------------------------------------------
2378 bool SvxTableController::GetMarkedObjModel( SdrPage* pNewPage )
2380 if( mxTableObj.is() && mbCellSelectionMode && pNewPage ) try
2382 ::sdr::table::SdrTableObj& rTableObj = *static_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
2384 CellPos aStart, aEnd;
2385 getSelectedCells( aStart, aEnd );
2387 SdrTableObj* pNewTableObj = rTableObj.CloneRange( aStart, aEnd );
2389 pNewTableObj->SetPage( pNewPage );
2390 pNewTableObj->SetModel( pNewPage->GetModel() );
2392 SdrInsertReason aReason(SDRREASON_VIEWCALL);
2393 pNewPage->InsertObject(pNewTableObj,CONTAINER_APPEND,&aReason);
2395 return true;
2397 catch( Exception& )
2399 OSL_FAIL( "svx::SvxTableController::GetMarkedObjModel(), exception caught!" );
2401 return false;
2404 // --------------------------------------------------------------------
2406 bool SvxTableController::PasteObjModel( const SdrModel& rModel )
2408 if( mxTableObj.is() && mpView && (rModel.GetPageCount() >= 1) )
2410 const SdrPage* pPastePage = rModel.GetPage(0);
2411 if( pPastePage && pPastePage->GetObjCount() == 1 )
2413 SdrTableObj* pPasteTableObj = dynamic_cast< SdrTableObj* >( pPastePage->GetObj(0) );
2414 if( pPasteTableObj )
2416 return PasteObject( pPasteTableObj );
2421 return false;
2424 // --------------------------------------------------------------------
2426 bool SvxTableController::PasteObject( SdrTableObj* pPasteTableObj )
2428 if( !pPasteTableObj )
2429 return false;
2431 Reference< XTable > xPasteTable( pPasteTableObj->getTable() );
2432 if( !xPasteTable.is() )
2433 return false;
2435 if( !mxTable.is() )
2436 return false;
2438 sal_Int32 nPasteColumns = xPasteTable->getColumnCount();
2439 sal_Int32 nPasteRows = xPasteTable->getRowCount();
2441 CellPos aStart, aEnd;
2442 getSelectedCells( aStart, aEnd );
2444 if( mpView->IsTextEdit() )
2445 mpView->SdrEndTextEdit(sal_True);
2447 sal_Int32 nColumns = mxTable->getColumnCount();
2448 sal_Int32 nRows = mxTable->getRowCount();
2450 const sal_Int32 nMissing = nPasteRows - ( nRows - aStart.mnRow );
2451 if( nMissing > 0 )
2453 Reference< XTableRows > xRows( mxTable->getRows() );
2454 xRows->insertByIndex( nRows, nMissing );
2455 nRows = mxTable->getRowCount();
2458 nPasteRows = std::min( nPasteRows, nRows - aStart.mnRow );
2459 nPasteColumns = std::min( nPasteColumns, nColumns - aStart.mnCol );
2461 // copy cell contents
2462 for( sal_Int32 nRow = 0; nRow < nPasteRows; ++nRow )
2464 for( sal_Int32 nCol = 0; nCol < nPasteColumns; ++nCol )
2466 CellRef xTargetCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( aStart.mnCol + nCol, aStart.mnRow + nRow ).get() ) );
2467 if( xTargetCell.is() && !xTargetCell->isMerged() )
2469 xTargetCell->AddUndo();
2470 xTargetCell->cloneFrom( dynamic_cast< Cell* >( xPasteTable->getCellByPosition( nCol, nRow ).get() ) );
2471 nCol += xTargetCell->getColumnSpan() - 1;
2476 UpdateTableShape();
2478 return true;
2481 bool SvxTableController::TakeFormatPaintBrush( boost::shared_ptr< SfxItemSet >& /*rFormatSet*/ )
2483 // SdrView::TakeFormatPaintBrush() is enough
2484 return false;
2487 bool SvxTableController::ApplyFormatPaintBrush( SfxItemSet& rFormatSet, bool bNoCharacterFormats, bool bNoParagraphFormats )
2489 if( mbCellSelectionMode )
2491 SdrTextObj* pTableObj = dynamic_cast<SdrTextObj*>( mxTableObj.get() );
2492 if( !pTableObj )
2493 return false;
2495 const bool bUndo = mpModel && mpModel->IsUndoEnabled();
2497 if( bUndo )
2498 mpModel->BegUndo( ImpGetResStr(STR_TABLE_NUMFORMAT) );
2500 CellPos aStart, aEnd;
2501 getSelectedCells( aStart, aEnd );
2503 SfxItemSet aAttr(*rFormatSet.GetPool(), rFormatSet.GetRanges());
2504 aAttr.Put(rFormatSet, sal_True);
2506 const bool bFrame = (rFormatSet.GetItemState( SDRATTR_TABLE_BORDER ) == SFX_ITEM_SET) || (rFormatSet.GetItemState( SDRATTR_TABLE_BORDER_INNER ) == SFX_ITEM_SET);
2508 if( bFrame )
2510 aAttr.ClearItem( SDRATTR_TABLE_BORDER );
2511 aAttr.ClearItem( SDRATTR_TABLE_BORDER_INNER );
2514 const sal_uInt16* pRanges = rFormatSet.GetRanges();
2515 bool bTextOnly = true;
2517 while( *pRanges )
2519 if( (*pRanges != EE_PARA_START) && (*pRanges != EE_CHAR_START) )
2521 bTextOnly = true;
2522 break;
2524 pRanges += 2;
2527 const bool bReplaceAll = false;
2528 for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
2530 for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
2532 CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
2533 if( xCell.is() )
2535 if( bUndo )
2536 xCell->AddUndo();
2537 if( !bTextOnly )
2538 xCell->SetMergedItemSetAndBroadcast(aAttr, bReplaceAll);
2540 SdrText* pText = static_cast< SdrText* >( xCell.get() );
2541 mpView->ApplyFormatPaintBrushToText( rFormatSet, *pTableObj, pText, bNoCharacterFormats, bNoParagraphFormats );
2546 if( bFrame )
2548 ApplyBorderAttr( rFormatSet );
2551 UpdateTableShape();
2553 if( bUndo )
2554 mpModel->EndUndo();
2556 return true;
2559 return false;
2563 // --------------------------------------------------------------------
2565 IMPL_LINK_NOARG(SvxTableController, UpdateHdl)
2567 mnUpdateEvent = 0;
2569 if( mbCellSelectionMode )
2571 CellPos aStart( maCursorFirstPos );
2572 CellPos aEnd( maCursorLastPos );
2573 checkCell(aStart);
2574 checkCell(aEnd);
2575 if( aStart != maCursorFirstPos || aEnd != maCursorLastPos )
2577 setSelectedCells( aStart, aEnd );
2580 updateSelectionOverlay();
2582 return 0;
2587 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */