Update ooo320-m1
[ooovba.git] / svx / source / table / tablecontroller.cxx
blob4d6eb39511aa60f3e15401c675329d7456eea1e3
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: tablecontroller.cxx,v $
10 * $Revision: 1.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
34 #include "tablecontroller.hxx"
36 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
37 #include <com/sun/star/container/XIndexAccess.hpp>
39 #include <com/sun/star/beans/XPropertySet.hpp>
40 #include <com/sun/star/table/XMergeableCellRange.hpp>
41 #include <com/sun/star/table/XMergeableCell.hpp>
43 #include <sal/config.h>
45 #include <vcl/svapp.hxx>
46 #include <svtools/whiter.hxx>
48 #include <sfx2/request.hxx>
50 #include <svx/scripttypeitem.hxx>
51 #include <svx/svdotable.hxx>
52 #include <svx/sdr/overlay/overlayobjectcell.hxx>
53 #include <svx/sdr/overlay/overlaymanager.hxx>
54 #include <svx/svxids.hrc>
55 #include <svx/outlobj.hxx>
56 #include <svx/svdoutl.hxx>
57 #include <svx/svdpagv.hxx>
58 #include <svx/svdetc.hxx>
59 #include <svx/editobj.hxx>
60 #include "editstat.hxx"
61 #include "unolingu.hxx"
62 #include "svx/sdrpagewindow.hxx"
63 #include <svx/selectioncontroller.hxx>
64 #include <svx/svdmodel.hxx>
65 #include "sdrpaintwindow.hxx"
66 #include <svx/svxdlg.hxx>
67 #include <svx/boxitem.hxx>
68 #include "cell.hxx"
69 #include <svx/borderline.hxx>
70 #include <svx/colritem.hxx>
71 #include "bolnitem.hxx"
72 #include "svdstr.hrc"
73 #include "svdglob.hxx"
74 #include "svx/svdpage.hxx"
75 #include "tableundo.hxx"
76 #include "tablelayouter.hxx"
78 using ::rtl::OUString;
79 using namespace ::sdr::table;
80 using namespace ::com::sun::star;
81 using namespace ::com::sun::star::uno;
82 using namespace ::com::sun::star::table;
83 using namespace ::com::sun::star::beans;
84 using namespace ::com::sun::star::container;
85 using namespace ::com::sun::star::text;
86 using namespace ::com::sun::star::style;
88 namespace sdr { namespace table {
90 // --------------------------------------------------------------------
91 // class SvxTableControllerModifyListener
92 // --------------------------------------------------------------------
94 class SvxTableControllerModifyListener : public ::cppu::WeakImplHelper1< ::com::sun::star::util::XModifyListener >
96 public:
97 SvxTableControllerModifyListener( SvxTableController* pController )
98 : mpController( pController ) {}
100 // XModifyListener
101 virtual void SAL_CALL modified( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException);
103 // XEventListener
104 virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);
106 SvxTableController* mpController;
109 // --------------------------------------------------------------------
110 // XModifyListener
111 // --------------------------------------------------------------------
113 void SAL_CALL SvxTableControllerModifyListener::modified( const ::com::sun::star::lang::EventObject& ) throw (::com::sun::star::uno::RuntimeException)
115 if( mpController )
116 mpController->onTableModified();
119 // --------------------------------------------------------------------
120 // XEventListener
121 // --------------------------------------------------------------------
123 void SAL_CALL SvxTableControllerModifyListener::disposing( const ::com::sun::star::lang::EventObject& ) throw (::com::sun::star::uno::RuntimeException)
125 mpController = 0;
128 // --------------------------------------------------------------------
129 // class SvxTableController
130 // --------------------------------------------------------------------
132 rtl::Reference< sdr::SelectionController > CreateTableController( SdrObjEditView* pView, const SdrObject* pObj, const rtl::Reference< sdr::SelectionController >& xRefController )
134 return SvxTableController::create( pView, pObj, xRefController );
137 // --------------------------------------------------------------------
139 rtl::Reference< sdr::SelectionController > SvxTableController::create( SdrObjEditView* pView, const SdrObject* pObj, const rtl::Reference< sdr::SelectionController >& xRefController )
141 if( xRefController.is() )
143 SvxTableController* pController = dynamic_cast< SvxTableController* >( xRefController.get() );
144 if( pController && (pController->mxTableObj.get() == pObj) && (pController->mpView == pView) )
145 return xRefController;
147 return new SvxTableController( pView, pObj );
150 // --------------------------------------------------------------------
152 SvxTableController::SvxTableController( SdrObjEditView* pView, const SdrObject* pObj )
153 : mbCellSelectionMode(false)
154 , mbLeftButtonDown(false)
155 , mpSelectionOverlay(0)
156 , mpView( dynamic_cast< SdrView* >( pView ) )
157 , mxTableObj( dynamic_cast< SdrTableObj* >( const_cast< SdrObject* >( pObj ) ) )
158 , mpModel( 0 )
159 , mnUpdateEvent( 0 )
161 if( pObj )
162 mpModel = pObj->GetModel();
164 if( mxTableObj.is() )
166 static_cast< const SdrTableObj* >( pObj )->getActiveCellPos( maCursorFirstPos );
167 maCursorLastPos = maCursorFirstPos;
169 Reference< XTable > xTable( static_cast< const SdrTableObj* >( pObj )->getTable() );
170 if( xTable.is() )
172 mxModifyListener = new SvxTableControllerModifyListener( this );
173 xTable->addModifyListener( mxModifyListener );
175 mxTable.set( dynamic_cast< TableModel* >( xTable.get() ) );
180 // --------------------------------------------------------------------
182 SvxTableController::~SvxTableController()
184 if( mnUpdateEvent )
186 Application::RemoveUserEvent( mnUpdateEvent );
189 if( mxModifyListener.is() && mxTableObj.get() )
191 Reference< XTable > xTable( static_cast< SdrTableObj* >( mxTableObj.get() )->getTable() );
192 if( xTable.is() )
194 xTable->removeModifyListener( mxModifyListener );
195 mxModifyListener.clear();
200 // --------------------------------------------------------------------
202 const sal_uInt16 ACTION_NONE = 0;
203 const sal_uInt16 ACTION_GOTO_FIRST_CELL = 1;
204 const sal_uInt16 ACTION_GOTO_FIRST_COLUMN = 2;
205 const sal_uInt16 ACTION_GOTO_FIRST_ROW = 3;
206 const sal_uInt16 ACTION_GOTO_LEFT_CELL = 4;
207 const sal_uInt16 ACTION_GOTO_UP_CELL = 5;
208 const sal_uInt16 ACTION_GOTO_RIGHT_CELL = 6;
209 const sal_uInt16 ACTION_GOTO_DOWN_CELL = 7;
210 const sal_uInt16 ACTION_GOTO_LAST_CELL = 8;
211 const sal_uInt16 ACTION_GOTO_LAST_COLUMN = 9;
212 const sal_uInt16 ACTION_GOTO_LAST_ROW = 10;
213 const sal_uInt16 ACTION_EDIT_CELL = 11;
214 const sal_uInt16 ACTION_STOP_TEXT_EDIT = 12;
215 const sal_uInt16 ACTION_REMOVE_SELECTION = 13;
216 const sal_uInt16 ACTION_START_SELECTION = 14;
217 const sal_uInt16 ACTION_HANDLED_BY_VIEW = 15;
218 const sal_uInt16 ACTION_TAB = 18;
220 bool SvxTableController::onKeyInput(const KeyEvent& rKEvt, Window* pWindow )
222 if( !checkTableObject() )
223 return false;
225 // check if we are read only
226 if( mpModel && mpModel->IsReadOnly())
228 switch( rKEvt.GetKeyCode().GetCode() )
230 case awt::Key::DOWN:
231 case awt::Key::UP:
232 case awt::Key::LEFT:
233 case awt::Key::RIGHT:
234 case awt::Key::TAB:
235 case awt::Key::HOME:
236 case awt::Key::END:
237 case awt::Key::NUM2:
238 case awt::Key::NUM4:
239 case awt::Key::NUM6:
240 case awt::Key::NUM8:
241 case awt::Key::ESCAPE:
242 case awt::Key::F2:
243 break;
244 default:
245 // tell the view we eat the event, no further processing needed
246 return true;
250 sal_uInt16 nAction = getKeyboardAction( rKEvt, pWindow );
252 return executeAction( nAction, ( rKEvt.GetKeyCode().IsShift() ) ? sal_True : sal_False, pWindow );
255 // --------------------------------------------------------------------
256 // ::com::sun::star::awt::XMouseClickHandler:
257 // --------------------------------------------------------------------
259 bool SvxTableController::onMouseButtonDown(const MouseEvent& rMEvt, Window* pWindow )
261 if( !pWindow || !checkTableObject() )
262 return false;
264 SdrViewEvent aVEvt;
265 if( !rMEvt.IsRight() && mpView->PickAnything(rMEvt,SDRMOUSEBUTTONDOWN, aVEvt) == SDRHIT_HANDLE )
266 return false;
268 TableHitKind eHit = static_cast< SdrTableObj* >(mxTableObj.get())->CheckTableHit( pWindow->PixelToLogic(rMEvt.GetPosPixel()), maMouseDownPos.mnCol, maMouseDownPos.mnRow, 0 );
270 mbLeftButtonDown = (rMEvt.GetClicks() == 1) && rMEvt.IsLeft();
272 if( eHit == SDRTABLEHIT_CELL )
274 StartSelection( maMouseDownPos );
275 return true;
278 if( rMEvt.IsRight() && eHit != SDRTABLEHIT_NONE )
279 return true; // right click will become context menu
281 // for cell selektion with the mouse remember our first hit
282 if( mbLeftButtonDown )
284 RemoveSelection();
286 Point aPnt(rMEvt.GetPosPixel());
287 if (pWindow!=NULL)
288 aPnt=pWindow->PixelToLogic(aPnt);
290 SdrHdl* pHdl = mpView->PickHandle(aPnt);
292 if( pHdl )
294 mbLeftButtonDown = false;
296 else
298 ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
300 if( !pWindow || !pTableObj || eHit == SDRTABLEHIT_NONE)
302 mbLeftButtonDown = false;
307 return false;
310 // --------------------------------------------------------------------
312 bool SvxTableController::onMouseButtonUp(const MouseEvent& rMEvt, Window* /*pWin*/)
314 if( !checkTableObject() )
315 return false;
317 mbLeftButtonDown = false;
319 if( rMEvt.GetClicks() == 2 )
320 return true;
322 return false;
325 // --------------------------------------------------------------------
327 bool SvxTableController::onMouseMove(const MouseEvent& rMEvt, Window* pWindow )
329 if( !checkTableObject() )
330 return false;
332 if( rMEvt.IsLeft() )
334 int i = 0;
335 i++;
338 SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
339 CellPos aPos;
340 if( mbLeftButtonDown && pTableObj && pTableObj->CheckTableHit( pWindow->PixelToLogic(rMEvt.GetPosPixel()), aPos.mnCol, aPos.mnRow, 0 ) != SDRTABLEHIT_NONE )
342 if(aPos != maMouseDownPos)
344 if( mbCellSelectionMode )
346 setSelectedCells( maMouseDownPos, aPos );
347 return true;
349 else
351 StartSelection( maMouseDownPos );
354 else if( mbCellSelectionMode )
356 UpdateSelection( aPos );
357 return true;
360 return false;
363 // --------------------------------------------------------------------
365 void SvxTableController::onSelectionHasChanged()
367 bool bSelected = false;
369 SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
370 if( pTableObj && pTableObj->IsTextEditActive() )
372 pTableObj->getActiveCellPos( maCursorFirstPos );
373 maCursorLastPos = maCursorFirstPos;
374 mbCellSelectionMode = false;
376 else
378 const SdrMarkList& rMarkList= mpView->GetMarkedObjectList();
379 if( rMarkList.GetMarkCount() == 1 )
380 bSelected = mxTableObj.get() == rMarkList.GetMark(0)->GetMarkedSdrObj();
383 if( bSelected )
385 updateSelectionOverlay();
387 else
389 destroySelectionOverlay();
393 // --------------------------------------------------------------------
395 void SvxTableController::GetState( SfxItemSet& rSet )
397 if( !mxTable.is() || !mxTableObj.is() || !mxTableObj->GetModel() )
398 return;
400 SfxItemSet* pSet = 0;
402 bool bVertDone = false;
404 // Iterate over all requested items in the set.
405 SfxWhichIter aIter( rSet );
406 USHORT nWhich = aIter.FirstWhich();
407 while (nWhich)
409 switch (nWhich)
411 case SID_TABLE_VERT_BOTTOM:
412 case SID_TABLE_VERT_CENTER:
413 case SID_TABLE_VERT_NONE:
415 if( !mxTable.is() || !mxTableObj->GetModel() )
417 rSet.DisableItem(nWhich);
419 else if(!bVertDone)
421 if( !pSet )
423 pSet = new SfxItemSet( mxTableObj->GetModel()->GetItemPool() );
424 MergeAttrFromSelectedCells(*pSet, FALSE);
427 SdrTextVertAdjust eAdj = SDRTEXTVERTADJUST_BLOCK;
429 if( pSet->GetItemState( SDRATTR_TEXT_VERTADJUST ) != SFX_ITEM_DONTCARE )
430 eAdj = ((SdrTextVertAdjustItem&)(pSet->Get(SDRATTR_TEXT_VERTADJUST))).GetValue();
432 rSet.Put(SfxBoolItem(SID_TABLE_VERT_BOTTOM, eAdj == SDRTEXTVERTADJUST_BOTTOM));
433 rSet.Put(SfxBoolItem(SID_TABLE_VERT_CENTER, eAdj == SDRTEXTVERTADJUST_CENTER));
434 rSet.Put(SfxBoolItem(SID_TABLE_VERT_NONE, eAdj == SDRTEXTVERTADJUST_TOP));
435 bVertDone = true;
437 break;
439 case SID_TABLE_DELETE_ROW:
440 if( !mxTable.is() || !hasSelectedCells() || (mxTable->getRowCount() <= 1) )
441 rSet.DisableItem(SID_TABLE_DELETE_ROW);
442 break;
443 case SID_TABLE_DELETE_COL:
444 if( !mxTable.is() || !hasSelectedCells() || (mxTable->getColumnCount() <= 1) )
445 rSet.DisableItem(SID_TABLE_DELETE_COL);
446 break;
447 case SID_TABLE_MERGE_CELLS:
448 if( !mxTable.is() || !hasSelectedCells() )
449 rSet.DisableItem(SID_TABLE_MERGE_CELLS);
450 break;
451 case SID_TABLE_SPLIT_CELLS:
452 if( !hasSelectedCells() || !mxTable.is() )
453 rSet.DisableItem(SID_TABLE_SPLIT_CELLS);
454 break;
456 case SID_OPTIMIZE_TABLE:
457 case SID_TABLE_DISTRIBUTE_COLUMNS:
458 case SID_TABLE_DISTRIBUTE_ROWS:
460 bool bDistributeColumns = false;
461 bool bDistributeRows = false;
462 if( mxTable.is() )
464 CellPos aStart, aEnd;
465 getSelectedCells( aStart, aEnd );
467 bDistributeColumns = aStart.mnCol != aEnd.mnCol;
468 bDistributeRows = aStart.mnRow != aEnd.mnRow;
470 if( !bDistributeColumns && !bDistributeRows )
471 rSet.DisableItem(SID_OPTIMIZE_TABLE);
472 if( !bDistributeColumns )
473 rSet.DisableItem(SID_TABLE_DISTRIBUTE_COLUMNS);
474 if( !bDistributeRows )
475 rSet.DisableItem(SID_TABLE_DISTRIBUTE_ROWS);
476 break;
479 case SID_AUTOFORMAT:
480 case SID_TABLE_SORT_DIALOG:
481 case SID_TABLE_AUTOSUM:
482 // if( !mxTable.is() )
483 // rSet.DisableItem( nWhich );
484 break;
485 default:
486 break;
488 nWhich = aIter.NextWhich();
490 if( pSet )
491 delete pSet;
494 // --------------------------------------------------------------------
496 void SvxTableController::onInsert( sal_uInt16 nSId, const SfxItemSet* pArgs )
498 ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
499 if( !pTableObj )
500 return;
502 if( mxTable.is() ) try
505 bool bInsertAfter = true;
506 sal_uInt16 nCount = 0;
507 if( pArgs )
509 const SfxPoolItem* pItem = 0;
510 pArgs->GetItemState(nSId, FALSE, &pItem);
511 if (pItem)
513 nCount = ((const SfxInt16Item* )pItem)->GetValue();
514 if(SFX_ITEM_SET == pArgs->GetItemState(SID_TABLE_PARAM_INSERT_AFTER, TRUE, &pItem))
515 bInsertAfter = ((const SfxBoolItem* )pItem)->GetValue();
519 CellPos aStart, aEnd;
520 if( hasSelectedCells() )
522 getSelectedCells( aStart, aEnd );
524 else
526 if( bInsertAfter )
528 aStart.mnCol = mxTable->getColumnCount() - 1;
529 aStart.mnRow = mxTable->getRowCount() - 1;
530 aEnd = aStart;
534 if( pTableObj->IsTextEditActive() )
535 mpView->SdrEndTextEdit(sal_True);
537 RemoveSelection();
539 const OUString sSize( RTL_CONSTASCII_USTRINGPARAM( "Size" ) );
541 const bool bUndo = mpModel && mpModel->IsUndoEnabled();
543 switch( nSId )
545 case SID_TABLE_INSERT_COL:
547 TableModelNotifyGuard aGuard( mxTable.get() );
549 if( bUndo )
551 mpModel->BegUndo( ImpGetResStr(STR_TABLE_INSCOL) );
552 mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
555 Reference< XTableColumns > xCols( mxTable->getColumns() );
556 const sal_Int32 nNewColumns = (nCount == 0) ? (aEnd.mnCol - aStart.mnCol + 1) : nCount;
557 const sal_Int32 nNewStartColumn = aEnd.mnCol + (bInsertAfter ? 1 : 0);
558 xCols->insertByIndex( nNewStartColumn, nNewColumns );
560 for( sal_Int32 nOffset = 0; nOffset < nNewColumns; nOffset++ )
562 Reference< XPropertySet >( xCols->getByIndex( aEnd.mnCol + nOffset + 1 ), UNO_QUERY_THROW )->
563 setPropertyValue( sSize,
564 Reference< XPropertySet >( xCols->getByIndex( aStart.mnCol + nOffset ), UNO_QUERY_THROW )->
565 getPropertyValue( sSize ) );
568 if( bUndo )
569 mpModel->EndUndo();
571 aStart.mnCol = nNewStartColumn;
572 aStart.mnRow = 0;
573 aEnd.mnCol = aStart.mnCol + nNewColumns - 1;
574 aEnd.mnRow = mxTable->getRowCount() - 1;
575 break;
578 case SID_TABLE_INSERT_ROW:
580 TableModelNotifyGuard aGuard( mxTable.get() );
582 if( bUndo )
584 mpModel->BegUndo( ImpGetResStr(STR_TABLE_INSROW ) );
585 mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
588 Reference< XTableRows > xRows( mxTable->getRows() );
589 const sal_Int32 nNewRows = (nCount == 0) ? (aEnd.mnRow - aStart.mnRow + 1) : nCount;
590 const sal_Int32 nNewRowStart = aEnd.mnRow + (bInsertAfter ? 1 : 0);
591 xRows->insertByIndex( nNewRowStart, nNewRows );
593 for( sal_Int32 nOffset = 0; nOffset < nNewRows; nOffset++ )
595 Reference< XPropertySet >( xRows->getByIndex( aEnd.mnRow + nOffset + 1 ), UNO_QUERY_THROW )->
596 setPropertyValue( sSize,
597 Reference< XPropertySet >( xRows->getByIndex( aStart.mnRow + nOffset ), UNO_QUERY_THROW )->
598 getPropertyValue( sSize ) );
601 if( bUndo )
602 mpModel->EndUndo();
604 aStart.mnCol = 0;
605 aStart.mnRow = nNewRowStart;
606 aEnd.mnCol = mxTable->getColumnCount() - 1;
607 aEnd.mnRow = aStart.mnRow + nNewRows - 1;
608 break;
612 StartSelection( aStart );
613 UpdateSelection( aEnd );
615 catch( Exception& e )
617 (void)e;
618 DBG_ERROR("svx::SvxTableController::onInsert(), exception caught!");
622 // --------------------------------------------------------------------
624 void SvxTableController::onDelete( sal_uInt16 nSId )
626 ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
627 if( !pTableObj )
628 return;
630 if( mxTable.is() && hasSelectedCells() )
632 CellPos aStart, aEnd;
633 getSelectedCells( aStart, aEnd );
635 if( pTableObj->IsTextEditActive() )
636 mpView->SdrEndTextEdit(sal_True);
638 RemoveSelection();
640 bool bDeleteTable = false;
641 switch( nSId )
643 case SID_TABLE_DELETE_COL:
645 const sal_Int32 nRemovedColumns = aEnd.mnCol - aStart.mnCol + 1;
646 if( nRemovedColumns == mxTable->getColumnCount() )
648 bDeleteTable = true;
650 else
652 Reference< XTableColumns > xCols( mxTable->getColumns() );
653 xCols->removeByIndex( aStart.mnCol, nRemovedColumns );
655 break;
658 case SID_TABLE_DELETE_ROW:
660 const sal_Int32 nRemovedRows = aEnd.mnRow - aStart.mnRow + 1;
661 if( nRemovedRows == mxTable->getRowCount() )
663 bDeleteTable = true;
665 else
667 Reference< XTableRows > xRows( mxTable->getRows() );
668 xRows->removeByIndex( aStart.mnRow, nRemovedRows );
670 break;
674 if( bDeleteTable )
675 mpView->DeleteMarkedObj();
676 else
677 UpdateTableShape();
681 // --------------------------------------------------------------------
683 void SvxTableController::onSelect( sal_uInt16 nSId )
685 if( mxTable.is() )
687 const sal_Int32 nRowCount = mxTable->getRowCount();
688 const sal_Int32 nColCount = mxTable->getColumnCount();
689 if( nRowCount && nColCount )
691 CellPos aStart, aEnd;
692 getSelectedCells( aStart, aEnd );
694 switch( nSId )
696 case SID_TABLE_SELECT_ALL:
697 aEnd.mnCol = 0; aEnd.mnRow = 0;
698 aStart.mnCol = nColCount - 1; aStart.mnRow = nRowCount - 1;
699 break;
700 case SID_TABLE_SELECT_COL:
701 aEnd.mnRow = nRowCount - 1;
702 aStart.mnRow = 0;
703 break;
704 case SID_TABLE_SELECT_ROW:
705 aEnd.mnCol = nColCount - 1;
706 aStart.mnCol = 0;
707 break;
710 StartSelection( aEnd );
711 gotoCell( aStart, true, 0 );
716 // --------------------------------------------------------------------
717 void SvxTableController::onFormatTable( SfxRequest& rReq )
719 ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
720 if( !pTableObj )
721 return;
723 const SfxItemSet* pArgs = rReq.GetArgs();
725 if( !pArgs && pTableObj->GetModel() )
727 SfxItemSet aNewAttr( pTableObj->GetModel()->GetItemPool() );
728 MergeAttrFromSelectedCells(aNewAttr, FALSE);
730 // merge drawing layer text distance items into SvxBoxItem used by the dialog
731 SvxBoxItem aBoxItem( static_cast< const SvxBoxItem& >( aNewAttr.Get( SDRATTR_TABLE_BORDER ) ) );
732 aBoxItem.SetDistance( sal::static_int_cast< USHORT >( ((SdrTextLeftDistItem&)(aNewAttr.Get(SDRATTR_TEXT_LEFTDIST))).GetValue()), BOX_LINE_LEFT );
733 aBoxItem.SetDistance( sal::static_int_cast< USHORT >( ((SdrTextRightDistItem&)(aNewAttr.Get(SDRATTR_TEXT_RIGHTDIST))).GetValue()), BOX_LINE_RIGHT );
734 aBoxItem.SetDistance( sal::static_int_cast< USHORT >( ((SdrTextUpperDistItem&)(aNewAttr.Get(SDRATTR_TEXT_UPPERDIST))).GetValue()), BOX_LINE_TOP );
735 aBoxItem.SetDistance( sal::static_int_cast< USHORT >( ((SdrTextLowerDistItem&)(aNewAttr.Get(SDRATTR_TEXT_LOWERDIST))).GetValue()), BOX_LINE_BOTTOM );
736 aNewAttr.Put( aBoxItem );
738 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
739 std::auto_ptr< SfxAbstractTabDialog > pDlg( pFact ? pFact->CreateSvxFormatCellsDialog( NULL, &aNewAttr, pTableObj->GetModel(), pTableObj) : 0 );
740 if( pDlg.get() && pDlg->Execute() )
742 SfxItemSet aNewSet( *(pDlg->GetOutputItemSet ()) );
744 SvxBoxItem aNewBoxItem( static_cast< const SvxBoxItem& >( aNewSet.Get( SDRATTR_TABLE_BORDER ) ) );
746 if( aNewBoxItem.GetDistance( BOX_LINE_LEFT ) != aBoxItem.GetDistance( BOX_LINE_LEFT ) )
747 aNewSet.Put(SdrTextLeftDistItem( aNewBoxItem.GetDistance( BOX_LINE_LEFT ) ) );
749 if( aNewBoxItem.GetDistance( BOX_LINE_RIGHT ) != aBoxItem.GetDistance( BOX_LINE_RIGHT ) )
750 aNewSet.Put(SdrTextRightDistItem( aNewBoxItem.GetDistance( BOX_LINE_RIGHT ) ) );
752 if( aNewBoxItem.GetDistance( BOX_LINE_TOP ) != aBoxItem.GetDistance( BOX_LINE_TOP ) )
753 aNewSet.Put(SdrTextUpperDistItem( aNewBoxItem.GetDistance( BOX_LINE_TOP ) ) );
755 if( aNewBoxItem.GetDistance( BOX_LINE_BOTTOM ) != aBoxItem.GetDistance( BOX_LINE_BOTTOM ) )
756 aNewSet.Put(SdrTextLowerDistItem( aNewBoxItem.GetDistance( BOX_LINE_BOTTOM ) ) );
758 SetAttrToSelectedCells(aNewSet, FALSE);
760 UpdateTableShape();
764 // --------------------------------------------------------------------
766 void SvxTableController::Execute( SfxRequest& rReq )
768 const sal_uInt16 nSId = rReq.GetSlot();
769 switch( nSId )
771 case SID_TABLE_INSERT_ROW:
772 case SID_TABLE_INSERT_COL:
773 onInsert( nSId, rReq.GetArgs() );
774 break;
775 case SID_TABLE_DELETE_ROW:
776 case SID_TABLE_DELETE_COL:
777 onDelete( nSId );
778 break;
779 case SID_TABLE_SELECT_ALL:
780 case SID_TABLE_SELECT_COL:
781 case SID_TABLE_SELECT_ROW:
782 onSelect( nSId );
783 break;
784 case SID_FORMAT_TABLE_DLG:
785 onFormatTable( rReq );
786 break;
788 case SID_FRAME_LINESTYLE:
789 case SID_FRAME_LINECOLOR:
790 case SID_ATTR_BORDER:
792 const SfxItemSet* pArgs = rReq.GetArgs();
793 if( pArgs )
794 ApplyBorderAttr( *pArgs );
796 break;
798 case SID_ATTR_FILL_STYLE:
800 const SfxItemSet* pArgs = rReq.GetArgs();
801 if( pArgs )
802 SetAttributes( *pArgs, false );
804 break;
806 case SID_TABLE_MERGE_CELLS:
807 MergeMarkedCells();
808 break;
810 case SID_TABLE_SPLIT_CELLS:
811 SplitMarkedCells();
812 break;
814 case SID_TABLE_DISTRIBUTE_COLUMNS:
815 DistributeColumns();
816 break;
818 case SID_TABLE_DISTRIBUTE_ROWS:
819 DistributeRows();
820 break;
822 case SID_TABLE_VERT_BOTTOM:
823 case SID_TABLE_VERT_CENTER:
824 case SID_TABLE_VERT_NONE:
825 SetVertical( nSId );
826 break;
828 case SID_AUTOFORMAT:
829 case SID_TABLE_SORT_DIALOG:
830 case SID_TABLE_AUTOSUM:
831 default:
832 break;
834 case SID_TABLE_STYLE:
835 SetTableStyle( rReq.GetArgs() );
836 break;
838 case SID_TABLE_STYLE_SETTINGS:
839 SetTableStyleSettings( rReq.GetArgs() );
840 break;
844 void SvxTableController::SetTableStyle( const SfxItemSet* pArgs )
846 SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
847 SdrModel* pModel = pTableObj ? pTableObj->GetModel() : 0;
849 if( !pTableObj || !pModel || !pArgs || (SFX_ITEM_SET != pArgs->GetItemState(SID_TABLE_STYLE, FALSE)) )
850 return;
852 const SfxStringItem* pArg = dynamic_cast< const SfxStringItem* >( &pArgs->Get( SID_TABLE_STYLE ) );
853 if( pArg && mxTable.is() ) try
855 Reference< XStyleFamiliesSupplier > xSFS( pModel->getUnoModel(), UNO_QUERY_THROW );
856 Reference< XNameAccess > xFamilyNameAccess( xSFS->getStyleFamilies(), UNO_QUERY_THROW );
857 const OUString sFamilyName( RTL_CONSTASCII_USTRINGPARAM( "table" ) );
858 Reference< XNameAccess > xTableFamilyAccess( xFamilyNameAccess->getByName( sFamilyName ), UNO_QUERY_THROW );
860 if( xTableFamilyAccess->hasByName( pArg->GetValue() ) )
862 // found table style with the same name
863 Reference< XIndexAccess > xNewTableStyle( xTableFamilyAccess->getByName( pArg->GetValue() ), UNO_QUERY_THROW );
865 const bool bUndo = pModel->IsUndoEnabled();
867 if( bUndo )
869 pModel->BegUndo( ImpGetResStr(STR_TABLE_STYLE) );
870 pModel->AddUndo( new TableStyleUndo( *pTableObj ) );
873 pTableObj->setTableStyle( xNewTableStyle );
875 const sal_Int32 nRowCount = mxTable->getRowCount();
876 const sal_Int32 nColCount = mxTable->getColumnCount();
877 for( sal_Int32 nRow = 0; nRow < nRowCount; nRow++ )
879 for( sal_Int32 nCol = 0; nCol < nColCount; nCol++ ) try
881 CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
882 if( xCell.is() )
884 SfxItemSet aSet( xCell->GetItemSet() );
885 bool bChanges = false;
886 const SfxItemSet& rStyleAttribs = xCell->GetStyleSheet()->GetItemSet();
888 for ( USHORT nWhich = SDRATTR_START; nWhich <= SDRATTR_TABLE_LAST; nWhich++ )
890 if( (rStyleAttribs.GetItemState( nWhich ) == SFX_ITEM_ON) && (aSet.GetItemState( nWhich ) == SFX_ITEM_ON) )
892 aSet.ClearItem( nWhich );
893 bChanges = true;
897 if( bChanges )
899 if( bUndo )
900 xCell->AddUndo();
902 xCell->SetMergedItemSetAndBroadcast( aSet, sal_True );
906 catch( Exception& e )
908 (void)e;
909 DBG_ERROR( "svx::SvxTableController::SetTableStyle(), exception caught!" );
913 if( bUndo )
914 pModel->EndUndo();
917 catch( Exception& e )
919 (void)e;
920 DBG_ERROR( "svx::SvxTableController::SetTableStyle(), exception caught!" );
924 void SvxTableController::SetTableStyleSettings( const SfxItemSet* pArgs )
926 SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
927 SdrModel* pModel = pTableObj ? pTableObj->GetModel() : 0;
929 if( !pTableObj || !pModel )
930 return;
932 TableStyleSettings aSettings( pTableObj->getTableStyleSettings() );
934 const SfxPoolItem *pPoolItem=NULL;
936 if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USEFIRSTROWSTYLE, FALSE,&pPoolItem)) )
937 aSettings.mbUseFirstRow = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
939 if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USELASTROWSTYLE, FALSE,&pPoolItem)) )
940 aSettings.mbUseLastRow = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
942 if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USEBANDINGROWSTYLE, FALSE,&pPoolItem)) )
943 aSettings.mbUseRowBanding = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
945 if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USEFIRSTCOLUMNSTYLE, FALSE,&pPoolItem)) )
946 aSettings.mbUseFirstColumn = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
948 if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USELASTCOLUMNSTYLE, FALSE,&pPoolItem)) )
949 aSettings.mbUseLastColumn = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
951 if( (SFX_ITEM_SET == pArgs->GetItemState(ID_VAL_USEBANDINGCOLUMNSTYLE, FALSE,&pPoolItem)) )
952 aSettings.mbUseColumnBanding = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
954 if( aSettings == pTableObj->getTableStyleSettings() )
955 return;
957 const bool bUndo = pModel->IsUndoEnabled();
959 if( bUndo )
961 pModel->BegUndo( ImpGetResStr(STR_TABLE_STYLE_SETTINGS) );
962 pModel->AddUndo( new TableStyleUndo( *pTableObj ) );
965 pTableObj->setTableStyleSettings( aSettings );
967 if( bUndo )
968 pModel->EndUndo();
971 void SvxTableController::SetVertical( sal_uInt16 nSId )
973 SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
974 if( mxTable.is() && pTableObj )
976 TableModelNotifyGuard aGuard( mxTable.get() );
978 CellPos aStart, aEnd;
979 getSelectedCells( aStart, aEnd );
981 SdrTextVertAdjust eAdj = SDRTEXTVERTADJUST_TOP;
983 switch( nSId )
985 case SID_TABLE_VERT_BOTTOM:
986 eAdj = SDRTEXTVERTADJUST_BOTTOM;
987 break;
988 case SID_TABLE_VERT_CENTER:
989 eAdj = SDRTEXTVERTADJUST_CENTER;
990 break;
991 //case SID_TABLE_VERT_NONE:
992 default:
993 break;
996 SdrTextVertAdjustItem aItem( eAdj );
998 for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
1000 for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
1002 CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
1003 if( xCell.is() )
1004 xCell->SetMergedItem(aItem);
1008 UpdateTableShape();
1012 void SvxTableController::MergeMarkedCells()
1014 CellPos aStart, aEnd;
1015 getSelectedCells( aStart, aEnd );
1016 SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1017 if( pTableObj )
1019 if( pTableObj->IsTextEditActive() )
1020 mpView->SdrEndTextEdit(sal_True);
1022 TableModelNotifyGuard aGuard( mxTable.get() );
1023 MergeRange( aStart.mnCol, aStart.mnRow, aEnd.mnCol, aEnd.mnRow );
1027 void SvxTableController::SplitMarkedCells()
1029 if( mxTable.is() )
1031 CellPos aStart, aEnd;
1032 getSelectedCells( aStart, aEnd );
1034 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
1035 std::auto_ptr< SvxAbstractSplittTableDialog > xDlg( pFact ? pFact->CreateSvxSplittTableDialog( NULL, false, 99, 99 ) : 0 );
1036 if( xDlg.get() && xDlg->Execute() )
1038 const sal_Int32 nCount = xDlg->GetCount() - 1;
1039 if( nCount < 1 )
1040 return;
1042 getSelectedCells( aStart, aEnd );
1044 Reference< XMergeableCellRange > xRange( mxTable->createCursorByRange( mxTable->getCellRangeByPosition( aStart.mnCol, aStart.mnRow, aEnd.mnCol, aEnd.mnRow ) ), UNO_QUERY_THROW );
1046 const sal_Int32 nRowCount = mxTable->getRowCount();
1047 const sal_Int32 nColCount = mxTable->getColumnCount();
1050 SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
1051 if( pTableObj )
1053 if( pTableObj->IsTextEditActive() )
1054 mpView->SdrEndTextEdit(sal_True);
1056 TableModelNotifyGuard aGuard( mxTable.get() );
1058 const bool bUndo = mpModel && mpModel->IsUndoEnabled();
1059 if( bUndo )
1061 mpModel->BegUndo( ImpGetResStr(STR_TABLE_SPLIT) );
1062 mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
1065 if( xDlg->IsHorizontal() )
1067 xRange->split( 0, nCount );
1069 else
1071 xRange->split( nCount, 0 );
1074 if( bUndo )
1075 mpModel->EndUndo();
1077 aEnd.mnRow += mxTable->getRowCount() - nRowCount;
1078 aEnd.mnCol += mxTable->getColumnCount() - nColCount;
1080 setSelectedCells( aStart, aEnd );
1085 void SvxTableController::DistributeColumns()
1087 SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
1088 if( pTableObj )
1090 const bool bUndo = mpModel && mpModel->IsUndoEnabled();
1091 if( bUndo )
1093 mpModel->BegUndo( ImpGetResStr(STR_TABLE_DISTRIBUTE_COLUMNS) );
1094 mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
1097 CellPos aStart, aEnd;
1098 getSelectedCells( aStart, aEnd );
1099 pTableObj->DistributeColumns( aStart.mnCol, aEnd.mnCol );
1101 if( bUndo )
1102 mpModel->EndUndo();
1106 void SvxTableController::DistributeRows()
1108 SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
1109 if( pTableObj )
1111 const bool bUndo = mpModel && mpModel->IsUndoEnabled();
1112 if( bUndo )
1114 mpModel->BegUndo( ImpGetResStr(STR_TABLE_DISTRIBUTE_ROWS) );
1115 mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
1118 CellPos aStart, aEnd;
1119 getSelectedCells( aStart, aEnd );
1120 pTableObj->DistributeRows( aStart.mnRow, aEnd.mnRow );
1122 if( bUndo )
1123 mpModel->EndUndo();
1127 bool SvxTableController::DeleteMarked()
1129 if( mbCellSelectionMode )
1131 if( mxTable.is() )
1133 CellPos aStart, aEnd;
1134 getSelectedCells( aStart, aEnd );
1135 for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
1137 for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
1139 CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
1140 if( xCell.is() )
1141 xCell->SetOutlinerParaObject( 0 );
1145 UpdateTableShape();
1146 return true;
1150 return false;
1153 bool SvxTableController::GetStyleSheet( SfxStyleSheet*& rpStyleSheet ) const
1155 if( hasSelectedCells() )
1157 rpStyleSheet = 0;
1159 if( mxTable.is() )
1161 SfxStyleSheet* pRet=0;
1162 bool b1st=true;
1164 CellPos aStart, aEnd;
1165 const_cast<SvxTableController&>(*this).getSelectedCells( aStart, aEnd );
1167 for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
1169 for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
1171 CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
1172 if( xCell.is() )
1174 SfxStyleSheet* pSS=xCell->GetStyleSheet();
1175 if(b1st)
1177 pRet=pSS;
1179 else if(pRet != pSS)
1181 return true;
1183 b1st=false;
1187 rpStyleSheet = pRet;
1188 return true;
1191 return false;
1194 bool SvxTableController::SetStyleSheet( SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr )
1196 if( hasSelectedCells() && (!pStyleSheet || pStyleSheet->GetFamily() == SFX_STYLE_FAMILY_FRAME) )
1198 if( mxTable.is() )
1200 CellPos aStart, aEnd;
1201 getSelectedCells( aStart, aEnd );
1203 for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
1205 for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
1207 CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
1208 if( xCell.is() )
1209 xCell->SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
1213 UpdateTableShape();
1214 return true;
1217 return false;
1220 // --------------------------------------------------------------------
1221 // internals
1222 // --------------------------------------------------------------------
1224 bool SvxTableController::checkTableObject()
1226 return mxTableObj.is();
1229 // --------------------------------------------------------------------
1231 sal_uInt16 SvxTableController::getKeyboardAction( const KeyEvent& rKEvt, Window* /*pWindow*/ )
1233 const bool bMod1 = rKEvt.GetKeyCode().IsMod1(); // ctrl
1234 const bool bMod2 = rKEvt.GetKeyCode().IsMod2() != 0; // Alt
1236 const bool bTextEdit = mpView->IsTextEdit();
1238 sal_uInt16 nAction = ACTION_HANDLED_BY_VIEW;
1240 ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1241 if( !pTableObj )
1242 return nAction;
1244 // handle special keys
1245 const sal_Int16 nCode = rKEvt.GetKeyCode().GetCode();
1246 switch( nCode )
1248 case awt::Key::ESCAPE: // handle escape
1250 if( bTextEdit )
1252 // escape during text edit ends text edit
1253 nAction = ACTION_STOP_TEXT_EDIT;
1255 if( mbCellSelectionMode )
1257 // escape with selected cells removes selection
1258 nAction = ACTION_REMOVE_SELECTION;
1260 break;
1262 case awt::Key::RETURN: // handle return
1264 if( !bMod1 && !bMod2 && !bTextEdit )
1266 // when not already editing, return starts text edit
1267 setSelectionStart( pTableObj->getFirstCell() );
1268 nAction = ACTION_EDIT_CELL;
1270 break;
1272 case awt::Key::F2: // f2 toggles text edit
1274 if( bMod1 || bMod2 ) // f2 with modifiers is handled by the view
1277 else if( bTextEdit )
1279 // f2 during text edit stops text edit
1280 nAction = ACTION_STOP_TEXT_EDIT;
1282 else if( mbCellSelectionMode )
1284 // f2 with selected cells removes selection
1285 nAction = ACTION_REMOVE_SELECTION;
1287 else
1289 // f2 with no selection and no text edit starts text edit
1290 setSelectionStart( pTableObj->getFirstCell() );
1291 nAction = ACTION_EDIT_CELL;
1293 break;
1295 case awt::Key::HOME:
1296 case awt::Key::NUM7:
1298 if( (bMod1 || bMod2) && (bTextEdit || mbCellSelectionMode) )
1300 if( bMod1 && !bMod2 )
1302 // strg + home jumps to first cell
1303 nAction = ACTION_GOTO_FIRST_CELL;
1305 else if( !bMod1 && bMod2 )
1307 // alt + home jumps to first column
1308 nAction = ACTION_GOTO_FIRST_COLUMN;
1311 break;
1313 case awt::Key::END:
1314 case awt::Key::NUM1:
1316 if( (bMod1 || bMod2) && (bTextEdit || mbCellSelectionMode) )
1318 if( bMod1 && !bMod2 )
1320 // strg + end jumps to last cell
1321 nAction = ACTION_GOTO_LAST_CELL;
1323 else if( !bMod1 && bMod2 )
1325 // alt + home jumps to last column
1326 nAction = ACTION_GOTO_LAST_COLUMN;
1329 break;
1332 case awt::Key::TAB:
1334 if( bTextEdit || mbCellSelectionMode )
1335 nAction = ACTION_TAB;
1336 break;
1339 case awt::Key::UP:
1340 case awt::Key::NUM8:
1341 case awt::Key::DOWN:
1342 case awt::Key::NUM2:
1343 case awt::Key::LEFT:
1344 case awt::Key::NUM4:
1345 case awt::Key::RIGHT:
1346 case awt::Key::NUM6:
1348 bool bTextMove = false;
1350 if( !bMod1 && bMod2 )
1352 if( (nCode == awt::Key::UP) || (nCode == awt::Key::NUM8) )
1354 nAction = ACTION_GOTO_LEFT_CELL;
1356 else if( (nCode == awt::Key::DOWN) || (nCode == awt::Key::NUM2) )
1358 nAction = ACTION_GOTO_RIGHT_CELL;
1360 break;
1363 if( !bTextMove )
1365 OutlinerView* pOLV = mpView->GetTextEditOutlinerView();
1366 if( pOLV )
1368 RemoveSelection();
1369 // during text edit, check if we navigate out of the cell
1370 ESelection aOldSelection = pOLV->GetSelection();
1371 pOLV->PostKeyEvent(rKEvt);
1372 bTextMove = pOLV && ( aOldSelection.IsEqual(pOLV->GetSelection()) );
1373 if( !bTextMove )
1375 nAction = ACTION_NONE;
1380 if( mbCellSelectionMode || bTextMove )
1382 // no text edit, navigate in cells if selection active
1383 switch( nCode )
1385 case awt::Key::LEFT:
1386 case awt::Key::NUM4:
1387 nAction = ACTION_GOTO_LEFT_CELL;
1388 break;
1389 case awt::Key::RIGHT:
1390 case awt::Key::NUM6:
1391 nAction = ACTION_GOTO_RIGHT_CELL;
1392 break;
1393 case awt::Key::DOWN:
1394 case awt::Key::NUM2:
1395 nAction = ACTION_GOTO_DOWN_CELL;
1396 break;
1397 case awt::Key::UP:
1398 case awt::Key::NUM8:
1399 nAction = ACTION_GOTO_UP_CELL;
1400 break;
1403 break;
1405 case awt::Key::PAGEUP:
1406 if( bMod2 )
1407 nAction = ACTION_GOTO_FIRST_ROW;
1408 break;
1410 case awt::Key::PAGEDOWN:
1411 if( bMod2 )
1412 nAction = ACTION_GOTO_LAST_ROW;
1413 break;
1415 return nAction;
1418 bool SvxTableController::executeAction( sal_uInt16 nAction, bool bSelect, Window* pWindow )
1420 ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1421 if( !pTableObj )
1422 return false;
1424 switch( nAction )
1426 case ACTION_GOTO_FIRST_CELL:
1428 gotoCell( pTableObj->getFirstCell(), bSelect, pWindow, nAction );
1429 break;
1432 case ACTION_GOTO_LEFT_CELL:
1434 gotoCell( pTableObj->getLeftCell( getSelectionEnd(), !bSelect ), bSelect, pWindow, nAction );
1435 break;
1438 case ACTION_GOTO_RIGHT_CELL:
1440 gotoCell( pTableObj->getRightCell( getSelectionEnd(), !bSelect ), bSelect, pWindow, nAction);
1441 break;
1444 case ACTION_GOTO_LAST_CELL:
1446 gotoCell( pTableObj->getLastCell(), bSelect, pWindow, nAction );
1447 break;
1450 case ACTION_GOTO_FIRST_COLUMN:
1452 CellPos aPos( pTableObj->getFirstCell().mnCol, getSelectionEnd().mnRow );
1453 gotoCell( aPos, bSelect, pWindow, nAction );
1454 break;
1457 case ACTION_GOTO_LAST_COLUMN:
1459 CellPos aPos( pTableObj->getLastCell().mnCol, getSelectionEnd().mnRow );
1460 gotoCell( aPos, bSelect, pWindow, nAction );
1461 break;
1464 case ACTION_GOTO_FIRST_ROW:
1466 CellPos aPos( getSelectionEnd().mnCol, pTableObj->getFirstCell().mnRow );
1467 gotoCell( aPos, bSelect, pWindow, nAction );
1468 break;
1471 case ACTION_GOTO_UP_CELL:
1473 gotoCell( pTableObj->getUpCell(getSelectionEnd(), !bSelect), bSelect, pWindow, nAction );
1474 break;
1477 case ACTION_GOTO_DOWN_CELL:
1479 gotoCell( pTableObj->getDownCell(getSelectionEnd(), !bSelect), bSelect, pWindow, nAction );
1480 break;
1483 case ACTION_GOTO_LAST_ROW:
1485 CellPos aPos( getSelectionEnd().mnCol, pTableObj->getLastCell().mnRow );
1486 gotoCell( aPos, bSelect, pWindow, nAction );
1487 break;
1490 case ACTION_EDIT_CELL:
1491 EditCell( getSelectionStart(), pWindow, 0, nAction );
1492 break;
1494 case ACTION_STOP_TEXT_EDIT:
1495 StopTextEdit();
1496 break;
1498 case ACTION_REMOVE_SELECTION:
1499 RemoveSelection();
1500 break;
1502 case ACTION_START_SELECTION:
1503 StartSelection( getSelectionStart() );
1504 break;
1506 case ACTION_TAB:
1508 if( bSelect )
1509 gotoCell( pTableObj->getPreviousCell( getSelectionEnd(), true ), false, pWindow, nAction );
1510 else
1512 CellPos aSelectionEnd( getSelectionEnd() );
1513 CellPos aNextCell( pTableObj->getNextCell( aSelectionEnd, true ) );
1514 if( aSelectionEnd == aNextCell )
1516 onInsert( SID_TABLE_INSERT_ROW, 0 );
1517 aNextCell = pTableObj->getNextCell( aSelectionEnd, true );
1519 gotoCell( aNextCell, false, pWindow, nAction );
1521 break;
1525 return nAction != ACTION_HANDLED_BY_VIEW;
1528 // --------------------------------------------------------------------
1530 void SvxTableController::gotoCell( const CellPos& rPos, bool bSelect, Window* pWindow, sal_uInt16 nAction )
1532 if( mxTableObj.is() && static_cast<SdrTableObj*>(mxTableObj.get())->IsTextEditActive() )
1533 mpView->SdrEndTextEdit(sal_True);
1535 if( bSelect )
1537 maCursorLastPos = rPos;
1538 if( mxTableObj.is() )
1539 static_cast< SdrTableObj* >( mxTableObj.get() )->setActiveCell( rPos );
1541 if( !mbCellSelectionMode )
1543 setSelectedCells( maCursorFirstPos, rPos );
1545 else
1547 UpdateSelection( rPos );
1550 else
1552 RemoveSelection();
1553 EditCell( rPos, pWindow, 0, nAction );
1557 // --------------------------------------------------------------------
1559 const CellPos& SvxTableController::getSelectionStart()
1561 checkCell( maCursorFirstPos );
1562 return maCursorFirstPos;
1565 // --------------------------------------------------------------------
1567 void SvxTableController::setSelectionStart( const CellPos& rPos )
1569 maCursorFirstPos = rPos;
1572 // --------------------------------------------------------------------
1574 const CellPos& SvxTableController::getSelectionEnd()
1576 checkCell( maCursorLastPos );
1577 return maCursorLastPos;
1580 // --------------------------------------------------------------------
1582 Reference< XCellCursor > SvxTableController::getSelectionCursor()
1584 Reference< XCellCursor > xCursor;
1586 if( mxTable.is() )
1588 if( hasSelectedCells() )
1590 CellPos aStart, aEnd;
1591 getSelectedCells( aStart, aEnd );
1592 xCursor = mxTable->createCursorByRange( mxTable->getCellRangeByPosition( aStart.mnCol, aStart.mnRow, aEnd.mnCol, aEnd.mnRow ) );
1594 else
1596 xCursor = mxTable->createCursor();
1600 return xCursor;
1603 void SvxTableController::MergeRange( sal_Int32 nFirstCol, sal_Int32 nFirstRow, sal_Int32 nLastCol, sal_Int32 nLastRow )
1605 if( mxTable.is() ) try
1607 Reference< XMergeableCellRange > xRange( mxTable->createCursorByRange( mxTable->getCellRangeByPosition( nFirstCol, nFirstRow,nLastCol, nLastRow ) ), UNO_QUERY_THROW );
1608 if( xRange->isMergeable() )
1610 const bool bUndo = mpModel && mpModel->IsUndoEnabled();
1611 if( bUndo )
1613 mpModel->BegUndo( ImpGetResStr(STR_TABLE_MERGE) );
1614 mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*mxTableObj.get()) );
1617 xRange->merge();
1619 if( bUndo )
1620 mpModel->EndUndo();
1623 catch( Exception& )
1625 DBG_ASSERT( false, "sdr::table::SvxTableController::MergeRange(), exception caught!" );
1631 // --------------------------------------------------------------------
1633 void SvxTableController::checkCell( CellPos& rPos )
1635 if( mxTable.is() ) try
1637 if( rPos.mnCol >= mxTable->getColumnCount() )
1638 rPos.mnCol = mxTable->getColumnCount()-1;
1640 if( rPos.mnRow >= mxTable->getRowCount() )
1641 rPos.mnRow = mxTable->getRowCount()-1;
1643 catch( Exception& e )
1645 (void)e;
1646 DBG_ERROR("sdr::table::SvxTableController::checkCell(), exception caught!" );
1650 // --------------------------------------------------------------------
1652 void SvxTableController::findMergeOrigin( CellPos& rPos )
1654 if( mxTable.is() ) try
1656 Reference< XMergeableCell > xCell( mxTable->getCellByPosition( rPos.mnCol, rPos.mnRow ), UNO_QUERY_THROW );
1657 if( xCell.is() && xCell->isMerged() )
1659 ::findMergeOrigin( mxTable, rPos.mnCol, rPos.mnRow, rPos.mnCol, rPos.mnRow );
1662 catch( Exception& e )
1664 (void)e;
1665 DBG_ERROR("sdr::table::SvxTableController::findMergeOrigin(), exception caught!" );
1669 // --------------------------------------------------------------------
1671 void SvxTableController::EditCell( const CellPos& rPos, ::Window* pWindow, const awt::MouseEvent* pMouseEvent /*= 0*/, sal_uInt16 nAction /*= ACTION_NONE */ )
1673 SdrPageView* pPV = mpView->GetSdrPageView();
1675 ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1676 if( pTableObj && pTableObj->GetPage() == pPV->GetPage() )
1678 bool bEmptyOutliner = false;
1680 if(!pTableObj->GetOutlinerParaObject() && mpView->GetTextEditOutliner())
1682 ::Outliner* pOutl = mpView->GetTextEditOutliner();
1683 ULONG nParaAnz = pOutl->GetParagraphCount();
1684 Paragraph* p1stPara = pOutl->GetParagraph( 0 );
1686 if(nParaAnz==1 && p1stPara)
1688 // Bei nur einem Pararaph
1689 if (pOutl->GetText(p1stPara).Len() == 0)
1691 bEmptyOutliner = true;
1696 CellPos aPos( rPos );
1697 findMergeOrigin( aPos );
1699 if( pTableObj != mpView->GetTextEditObject() || bEmptyOutliner || !pTableObj->IsTextEditActive( aPos ) )
1701 if( pTableObj->IsTextEditActive() )
1702 mpView->SdrEndTextEdit(sal_True);
1704 pTableObj->setActiveCell( aPos );
1706 // create new outliner, owner will be the SdrObjEditView
1707 SdrOutliner* pOutl = SdrMakeOutliner( OUTLINERMODE_OUTLINEOBJECT, mpModel );
1708 if( pTableObj->IsVerticalWriting() )
1709 pOutl->SetVertical( TRUE );
1711 if(mpView->SdrBeginTextEdit(pTableObj, pPV, pWindow, sal_True, pOutl))
1713 maCursorLastPos = maCursorFirstPos = rPos;
1715 OutlinerView* pOLV = mpView->GetTextEditOutlinerView();
1717 bool bNoSel = true;
1719 if( pMouseEvent )
1721 ::MouseEvent aMEvt( *pMouseEvent );
1723 SdrViewEvent aVEvt;
1724 SdrHitKind eHit = mpView->PickAnything(aMEvt, SDRMOUSEBUTTONDOWN, aVEvt);
1726 if (eHit == SDRHIT_TEXTEDIT)
1728 // Text getroffen
1729 pOLV->MouseButtonDown(aMEvt);
1730 pOLV->MouseMove(aMEvt);
1731 pOLV->MouseButtonUp(aMEvt);
1732 // pOLV->MouseButtonDown(aMEvt);
1733 bNoSel = false;
1735 else
1737 nAction = ACTION_GOTO_LEFT_CELL;
1741 if( bNoSel )
1743 // Move cursor to end of text
1744 ESelection aNewSelection;
1746 const WritingMode eMode = pTableObj->GetWritingMode();
1747 if( ((nAction == ACTION_GOTO_LEFT_CELL) || (nAction == ACTION_GOTO_RIGHT_CELL)) && (eMode != WritingMode_TB_RL) )
1749 const bool bLast = ((nAction == ACTION_GOTO_LEFT_CELL) && (eMode == WritingMode_LR_TB)) ||
1750 ((nAction == ACTION_GOTO_RIGHT_CELL) && (eMode == WritingMode_RL_TB));
1752 if( bLast )
1753 aNewSelection = ESelection(EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND, EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND);
1755 pOLV->SetSelection(aNewSelection);
1762 // --------------------------------------------------------------------
1764 bool SvxTableController::StopTextEdit()
1766 if(mpView->IsTextEdit())
1768 mpView->SdrEndTextEdit();
1769 mpView->SetCurrentObj(OBJ_TABLE);
1770 mpView->SetEditMode(SDREDITMODE_EDIT);
1771 return true;
1773 else
1775 return false;
1779 // --------------------------------------------------------------------
1781 void SvxTableController::DeleteTable()
1786 // --------------------------------------------------------------------
1788 void SvxTableController::getSelectedCells( CellPos& rFirst, CellPos& rLast )
1790 if( mbCellSelectionMode )
1792 checkCell( maCursorFirstPos );
1793 checkCell( maCursorLastPos );
1795 rFirst.mnCol = std::min( maCursorFirstPos.mnCol, maCursorLastPos.mnCol );
1796 rFirst.mnRow = std::min( maCursorFirstPos.mnRow, maCursorLastPos.mnRow );
1797 rLast.mnCol = std::max( maCursorFirstPos.mnCol, maCursorLastPos.mnCol );
1798 rLast.mnRow = std::max( maCursorFirstPos.mnRow, maCursorLastPos.mnRow );
1800 bool bExt = false;
1801 if( mxTable.is() ) do
1803 bExt = false;
1804 for( sal_Int32 nRow = rFirst.mnRow; nRow <= rLast.mnRow && !bExt; nRow++ )
1806 for( sal_Int32 nCol = rFirst.mnCol; nCol <= rLast.mnCol && !bExt; nCol++ )
1808 Reference< XMergeableCell > xCell( mxTable->getCellByPosition( nCol, nRow ), UNO_QUERY );
1809 if( !xCell.is() )
1810 continue;
1812 if( xCell->isMerged() )
1814 CellPos aPos( nCol, nRow );
1815 findMergeOrigin( aPos );
1816 if( (aPos.mnCol < rFirst.mnCol) || (aPos.mnRow < rFirst.mnRow) )
1818 rFirst.mnCol = std::min( rFirst.mnCol, aPos.mnCol );
1819 rFirst.mnRow = std::min( rFirst.mnRow, aPos.mnRow );
1820 bExt = true;
1823 else
1825 if( ((nCol + xCell->getColumnSpan() - 1) > rLast.mnCol) || (nRow + xCell->getRowSpan() - 1 ) > rLast.mnRow )
1827 rLast.mnCol = std::max( rLast.mnCol, nCol + xCell->getColumnSpan() - 1 );
1828 rLast.mnRow = std::max( rLast.mnRow, nRow + xCell->getRowSpan() - 1 );
1829 bExt = true;
1835 while(bExt);
1837 else if( mpView && mpView->IsTextEdit() )
1839 rFirst = getSelectionStart();
1840 findMergeOrigin( rFirst );
1841 rLast = rFirst;
1843 if( mxTable.is() )
1845 Reference< XMergeableCell > xCell( mxTable->getCellByPosition( rLast.mnCol, rLast.mnRow ), UNO_QUERY );
1846 if( xCell.is() )
1848 rLast.mnCol += xCell->getColumnSpan() - 1;
1849 rLast.mnRow += xCell->getRowSpan() - 1;
1853 else
1855 rFirst.mnCol = 0;
1856 rFirst.mnRow = 0;
1857 if( mxTable.is() )
1859 rLast.mnRow = mxTable->getRowCount()-1;
1860 rLast.mnCol = mxTable->getColumnCount()-1;
1862 else
1864 rLast.mnRow = 0;
1865 rLast.mnCol = 0;
1870 // --------------------------------------------------------------------
1872 void SvxTableController::StartSelection( const CellPos& rPos )
1874 StopTextEdit();
1875 mbCellSelectionMode = true;
1876 maCursorLastPos = maCursorFirstPos = rPos;
1877 mpView->MarkListHasChanged();
1880 // --------------------------------------------------------------------
1882 void SvxTableController::setSelectedCells( const CellPos& rStart, const CellPos& rEnd )
1884 StopTextEdit();
1885 mbCellSelectionMode = true;
1886 maCursorFirstPos = rStart;
1887 UpdateSelection( rEnd );
1890 // --------------------------------------------------------------------
1892 void SvxTableController::UpdateSelection( const CellPos& rPos )
1894 maCursorLastPos = rPos;
1895 mpView->MarkListHasChanged();
1898 // --------------------------------------------------------------------
1900 void SvxTableController::clearSelection()
1902 RemoveSelection();
1905 // --------------------------------------------------------------------
1907 void SvxTableController::selectAll()
1909 if( mxTable.is() )
1911 CellPos aPos1, aPos2( mxTable->getColumnCount()-1, mxTable->getRowCount()-1 );
1912 if( (aPos2.mnCol >= 0) && (aPos2.mnRow >= 0) )
1914 setSelectedCells( aPos1, aPos2 );
1919 // --------------------------------------------------------------------
1921 void SvxTableController::RemoveSelection()
1923 if( mbCellSelectionMode )
1925 mbCellSelectionMode = false;
1926 mpView->MarkListHasChanged();
1930 // --------------------------------------------------------------------
1932 void SvxTableController::onTableModified()
1934 if( mnUpdateEvent == 0 )
1935 mnUpdateEvent = Application::PostUserEvent( LINK( this, SvxTableController, UpdateHdl ) );
1937 // --------------------------------------------------------------------
1939 void SvxTableController::updateSelectionOverlay()
1941 destroySelectionOverlay();
1942 if( mbCellSelectionMode )
1944 ::sdr::table::SdrTableObj* pTableObj = dynamic_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
1945 if( pTableObj )
1947 sdr::overlay::OverlayObjectCell::RangeVector aRanges;
1949 Rectangle aRect;
1950 CellPos aStart,aEnd;
1951 getSelectedCells( aStart, aEnd );
1952 pTableObj->getCellBounds( aStart, aRect );
1954 basegfx::B2DRange a2DRange( basegfx::B2DPoint(aRect.Left(), aRect.Top()) );
1955 a2DRange.expand( basegfx::B2DPoint(aRect.Right(), aRect.Bottom()) );
1957 findMergeOrigin( aEnd );
1958 pTableObj->getCellBounds( aEnd, aRect );
1959 a2DRange.expand( basegfx::B2DPoint(aRect.Left(), aRect.Top()) );
1960 a2DRange.expand( basegfx::B2DPoint(aRect.Right(), aRect.Bottom()) );
1961 aRanges.push_back( a2DRange );
1963 ::Color aHighlight( COL_BLUE );
1964 OutputDevice* pOutDev = mpView->GetFirstOutputDevice();
1965 if( pOutDev )
1966 aHighlight = pOutDev->GetSettings().GetStyleSettings().GetHighlightColor();
1968 const sal_uInt32 nCount = mpView->PaintWindowCount();
1969 for( sal_uInt32 nIndex = 0; nIndex < nCount; nIndex++ )
1971 SdrPaintWindow* pPaintWindow = mpView->GetPaintWindow(nIndex);
1972 if( pPaintWindow )
1974 ::sdr::overlay::OverlayManager* pOverlayManager = pPaintWindow->GetOverlayManager();
1975 if( pOverlayManager )
1977 // sdr::overlay::CellOverlayType eType = sdr::overlay::CELL_OVERLAY_INVERT;
1978 sdr::overlay::CellOverlayType eType = sdr::overlay::CELL_OVERLAY_TRANSPARENT;
1980 sdr::overlay::OverlayObjectCell* pOverlay = new sdr::overlay::OverlayObjectCell( eType, aHighlight, aRanges );
1982 pOverlayManager->add(*pOverlay);
1983 mpSelectionOverlay = new ::sdr::overlay::OverlayObjectList;
1984 mpSelectionOverlay->append(*pOverlay);
1992 // --------------------------------------------------------------------
1994 void SvxTableController::destroySelectionOverlay()
1996 if( mpSelectionOverlay )
1998 delete mpSelectionOverlay;
1999 mpSelectionOverlay = 0;
2003 // --------------------------------------------------------------------
2005 void SvxTableController::MergeAttrFromSelectedCells(SfxItemSet& rAttr, bool bOnlyHardAttr) const
2007 if( mxTable.is() )
2009 CellPos aStart, aEnd;
2010 const_cast<SvxTableController&>(*this).getSelectedCells( aStart, aEnd );
2012 for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
2014 for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
2016 CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
2017 if( xCell.is() && !xCell->isMerged() )
2019 const SfxItemSet& rSet = xCell->GetItemSet();
2020 SfxWhichIter aIter(rSet);
2021 sal_uInt16 nWhich(aIter.FirstWhich());
2022 while(nWhich)
2024 if(!bOnlyHardAttr)
2026 if(SFX_ITEM_DONTCARE == rSet.GetItemState(nWhich, FALSE))
2027 rAttr.InvalidateItem(nWhich);
2028 else
2029 rAttr.MergeValue(rSet.Get(nWhich), TRUE);
2031 else if(SFX_ITEM_SET == rSet.GetItemState(nWhich, FALSE))
2033 const SfxPoolItem& rItem = rSet.Get(nWhich);
2034 rAttr.MergeValue(rItem, TRUE);
2037 nWhich = aIter.NextWhich();
2044 if( mpView->IsTextEdit() )
2049 // --------------------------------------------------------------------
2051 const sal_uInt16 CELL_BEFORE = 0x0001;
2052 const sal_uInt16 CELL_LEFT = 0x0002;
2053 const sal_uInt16 CELL_RIGHT = 0x0004;
2054 const sal_uInt16 CELL_AFTER = 0x0008;
2056 const sal_uInt16 CELL_UPPER = 0x0010;
2057 const sal_uInt16 CELL_TOP = 0x0020;
2058 const sal_uInt16 CELL_BOTTOM = 0x0040;
2059 const sal_uInt16 CELL_LOWER = 0x0080;
2061 // --------------------------------------------------------------------
2063 static void ImplSetLinePreserveColor( SvxBoxItem& rNewFrame, const SvxBorderLine* pNew, USHORT nLine )
2065 if( pNew )
2067 const SvxBorderLine* pOld = rNewFrame.GetLine(nLine);
2068 if( pOld )
2070 SvxBorderLine aNewLine( *pNew );
2071 aNewLine.SetColor( pOld->GetColor() );
2072 rNewFrame.SetLine( &aNewLine, nLine );
2073 return;
2076 rNewFrame.SetLine( pNew, nLine );
2079 // --------------------------------------------------------------------
2081 static void ImplApplyBoxItem( sal_uInt16 nCellFlags, const SvxBoxItem* pBoxItem, const SvxBoxInfoItem* pBoxInfoItem, SvxBoxItem& rNewFrame )
2083 if( (nCellFlags & (CELL_BEFORE|CELL_AFTER|CELL_UPPER|CELL_LOWER)) != 0 )
2085 // current cell is outside the selection
2087 if( (nCellFlags & ( CELL_BEFORE|CELL_AFTER)) == 0 ) // check if its not nw or ne corner
2089 if( nCellFlags & CELL_UPPER )
2091 if( pBoxInfoItem->IsValid(VALID_TOP) )
2092 rNewFrame.SetLine(0, BOX_LINE_BOTTOM );
2094 else if( nCellFlags & CELL_LOWER )
2096 if( pBoxInfoItem->IsValid(VALID_BOTTOM) )
2097 rNewFrame.SetLine( 0, BOX_LINE_TOP );
2100 else if( (nCellFlags & ( CELL_UPPER|CELL_LOWER)) == 0 ) // check if its not sw or se corner
2102 if( nCellFlags & CELL_BEFORE )
2104 if( pBoxInfoItem->IsValid(VALID_LEFT) )
2105 rNewFrame.SetLine( 0, BOX_LINE_RIGHT );
2107 else if( nCellFlags & CELL_AFTER )
2109 if( pBoxInfoItem->IsValid(VALID_RIGHT) )
2110 rNewFrame.SetLine( 0, BOX_LINE_LEFT );
2114 else
2116 // current cell is inside the selection
2118 if( (nCellFlags & CELL_LEFT) ? pBoxInfoItem->IsValid(VALID_LEFT) : pBoxInfoItem->IsValid(VALID_VERT) )
2119 rNewFrame.SetLine( (nCellFlags & CELL_LEFT) ? pBoxItem->GetLeft() : pBoxInfoItem->GetVert(), BOX_LINE_LEFT );
2121 if( (nCellFlags & CELL_RIGHT) ? pBoxInfoItem->IsValid(VALID_RIGHT) : pBoxInfoItem->IsValid(VALID_VERT) )
2122 rNewFrame.SetLine( (nCellFlags & CELL_RIGHT) ? pBoxItem->GetRight() : pBoxInfoItem->GetVert(), BOX_LINE_RIGHT );
2124 if( (nCellFlags & CELL_TOP) ? pBoxInfoItem->IsValid(VALID_TOP) : pBoxInfoItem->IsValid(VALID_HORI) )
2125 rNewFrame.SetLine( (nCellFlags & CELL_TOP) ? pBoxItem->GetTop() : pBoxInfoItem->GetHori(), BOX_LINE_TOP );
2127 if( (nCellFlags & CELL_BOTTOM) ? pBoxInfoItem->IsValid(VALID_BOTTOM) : pBoxInfoItem->IsValid(VALID_HORI) )
2128 rNewFrame.SetLine( (nCellFlags & CELL_BOTTOM) ? pBoxItem->GetBottom() : pBoxInfoItem->GetHori(), BOX_LINE_BOTTOM );
2130 // apply distance to borders
2131 if( pBoxInfoItem->IsValid( VALID_DISTANCE ) )
2132 for( USHORT nLine = 0; nLine < 4; ++nLine )
2133 rNewFrame.SetDistance( pBoxItem->GetDistance( nLine ), nLine );
2137 // --------------------------------------------------------------------
2139 static void ImplSetLineColor( SvxBoxItem& rNewFrame, USHORT nLine, const Color& rColor )
2141 const SvxBorderLine* pSourceLine = rNewFrame.GetLine( nLine );
2142 if( pSourceLine )
2144 SvxBorderLine aLine( *pSourceLine );
2145 aLine.SetColor( rColor );
2146 rNewFrame.SetLine( &aLine, nLine );
2150 // --------------------------------------------------------------------
2152 static void ImplApplyLineColorItem( sal_uInt16 nCellFlags, const SvxColorItem* pLineColorItem, SvxBoxItem& rNewFrame )
2154 const Color aColor( pLineColorItem->GetValue() );
2156 if( (nCellFlags & (CELL_LOWER|CELL_BEFORE|CELL_AFTER)) == 0 )
2157 ImplSetLineColor( rNewFrame, BOX_LINE_BOTTOM, aColor );
2159 if( (nCellFlags & (CELL_UPPER|CELL_BEFORE|CELL_AFTER)) == 0 )
2160 ImplSetLineColor( rNewFrame, BOX_LINE_TOP, aColor );
2162 if( (nCellFlags & (CELL_UPPER|CELL_LOWER|CELL_AFTER)) == 0 )
2163 ImplSetLineColor( rNewFrame, BOX_LINE_RIGHT, aColor );
2165 if( (nCellFlags & (CELL_UPPER|CELL_LOWER|CELL_BEFORE)) == 0 )
2166 ImplSetLineColor( rNewFrame, BOX_LINE_LEFT, aColor );
2169 // --------------------------------------------------------------------
2171 static void ImplApplyBorderLineItem( sal_uInt16 nCellFlags, const SvxBorderLine* pBorderLineItem, SvxBoxItem& rNewFrame )
2173 if( (nCellFlags & ( CELL_BEFORE|CELL_AFTER|CELL_UPPER|CELL_LOWER)) != 0 )
2175 if( (nCellFlags & ( CELL_BEFORE|CELL_AFTER)) == 0 ) // check if its not nw or ne corner
2177 if( nCellFlags & CELL_UPPER )
2179 if( rNewFrame.GetBottom() )
2180 ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_BOTTOM );
2182 else if( nCellFlags & CELL_LOWER )
2184 if( rNewFrame.GetTop() )
2185 ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_TOP );
2188 else if( (nCellFlags & ( CELL_UPPER|CELL_LOWER)) == 0 ) // check if its not sw or se corner
2190 if( nCellFlags & CELL_BEFORE )
2192 if( rNewFrame.GetRight() )
2193 ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_RIGHT );
2195 else if( nCellFlags & CELL_AFTER )
2197 if( rNewFrame.GetLeft() )
2198 ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_LEFT );
2202 else
2204 if( rNewFrame.GetBottom() )
2205 ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_BOTTOM );
2206 if( rNewFrame.GetTop() )
2207 ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_TOP );
2208 if( rNewFrame.GetRight() )
2209 ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_RIGHT );
2210 if( rNewFrame.GetLeft() )
2211 ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, BOX_LINE_LEFT );
2215 // --------------------------------------------------------------------
2217 void SvxTableController::ApplyBorderAttr( const SfxItemSet& rAttr )
2219 if( mxTable.is() )
2221 const sal_Int32 nRowCount = mxTable->getRowCount();
2222 const sal_Int32 nColCount = mxTable->getColumnCount();
2223 if( nRowCount && nColCount )
2225 const SvxBoxItem* pBoxItem = 0;
2226 if(SFX_ITEM_SET == rAttr.GetItemState(SDRATTR_TABLE_BORDER, FALSE) )
2227 pBoxItem = dynamic_cast< const SvxBoxItem* >( &rAttr.Get( SDRATTR_TABLE_BORDER ) );
2229 const SvxBoxInfoItem* pBoxInfoItem = 0;
2230 if(SFX_ITEM_SET == rAttr.GetItemState(SDRATTR_TABLE_BORDER_INNER, FALSE) )
2231 pBoxInfoItem = dynamic_cast< const SvxBoxInfoItem* >( &rAttr.Get( SDRATTR_TABLE_BORDER_INNER ) );
2233 const SvxColorItem* pLineColorItem = 0;
2234 if(SFX_ITEM_SET == rAttr.GetItemState(SID_FRAME_LINECOLOR, FALSE) )
2235 pLineColorItem = dynamic_cast< const SvxColorItem* >( &rAttr.Get( SID_FRAME_LINECOLOR ) );
2237 const SvxBorderLine* pBorderLineItem = 0;
2238 if(SFX_ITEM_SET == rAttr.GetItemState(SID_FRAME_LINESTYLE, FALSE) )
2239 pBorderLineItem = ((const SvxLineItem&)rAttr.Get( SID_FRAME_LINESTYLE )).GetLine();
2241 if( pBoxInfoItem && !pBoxItem )
2243 const static SvxBoxItem gaEmptyBoxItem( SDRATTR_TABLE_BORDER );
2244 pBoxItem = &gaEmptyBoxItem;
2246 else if( pBoxItem && !pBoxInfoItem )
2248 const static SvxBoxInfoItem gaEmptyBoxInfoItem( SDRATTR_TABLE_BORDER_INNER );
2249 pBoxInfoItem = &gaEmptyBoxInfoItem;
2252 CellPos aStart, aEnd;
2253 getSelectedCells( aStart, aEnd );
2255 const sal_Int32 nLastRow = std::min( aEnd.mnRow + 2, nRowCount );
2256 const sal_Int32 nLastCol = std::min( aEnd.mnCol + 2, nColCount );
2258 for( sal_Int32 nRow = std::max( aStart.mnRow - 1, (sal_Int32)0 ); nRow < nLastRow; nRow++ )
2260 sal_uInt16 nRowFlags = 0;
2261 nRowFlags |= (nRow == aStart.mnRow) ? CELL_TOP : 0;
2262 nRowFlags |= (nRow == aEnd.mnRow) ? CELL_BOTTOM : 0;
2263 nRowFlags |= (nRow < aStart.mnRow) ? CELL_UPPER : 0;
2264 nRowFlags |= (nRow > aEnd.mnRow) ? CELL_LOWER : 0;
2266 for( sal_Int32 nCol = std::max( aStart.mnCol - 1, (sal_Int32)0 ); nCol < nLastCol; nCol++ )
2268 CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
2269 if( !xCell.is() )
2270 continue;
2272 const SfxItemSet& rSet = xCell->GetItemSet();
2273 const SvxBoxItem* pOldOuter = (const SvxBoxItem*) &rSet.Get( SDRATTR_TABLE_BORDER );
2275 SvxBoxItem aNewFrame( *pOldOuter );
2277 sal_uInt16 nCellFlags = nRowFlags;
2278 nCellFlags |= (nCol == aStart.mnCol) ? CELL_LEFT : 0;
2279 nCellFlags |= (nCol == aEnd.mnCol) ? CELL_RIGHT : 0;
2280 nCellFlags |= (nCol < aStart.mnCol) ? CELL_BEFORE : 0;
2281 nCellFlags |= (nCol > aEnd.mnCol) ? CELL_AFTER : 0;
2283 if( pBoxItem && pBoxInfoItem )
2284 ImplApplyBoxItem( nCellFlags, pBoxItem, pBoxInfoItem, aNewFrame );
2286 if( pLineColorItem )
2287 ImplApplyLineColorItem( nCellFlags, pLineColorItem, aNewFrame );
2289 if( pBorderLineItem )
2290 ImplApplyBorderLineItem( nCellFlags, pBorderLineItem, aNewFrame );
2292 if (aNewFrame != *pOldOuter)
2294 SfxItemSet aAttr(*rSet.GetPool(), rSet.GetRanges());
2295 aAttr.Put(aNewFrame);
2296 xCell->SetMergedItemSetAndBroadcast( aAttr, false );
2304 // --------------------------------------------------------------------
2306 void SvxTableController::UpdateTableShape()
2308 SdrObject* pTableObj = mxTableObj.get();
2309 if( pTableObj )
2311 pTableObj->ActionChanged();
2312 pTableObj->BroadcastObjectChange();
2314 updateSelectionOverlay();
2318 // --------------------------------------------------------------------
2320 void SvxTableController::SetAttrToSelectedCells(const SfxItemSet& rAttr, bool bReplaceAll)
2322 if( mxTable.is() )
2324 const bool bUndo = mpModel && mpModel->IsUndoEnabled();
2326 if( bUndo )
2327 mpModel->BegUndo( ImpGetResStr(STR_TABLE_NUMFORMAT) );
2329 CellPos aStart, aEnd;
2330 getSelectedCells( aStart, aEnd );
2332 SfxItemSet aAttr(*rAttr.GetPool(), rAttr.GetRanges());
2333 aAttr.Put(rAttr, TRUE);
2335 const bool bFrame = (rAttr.GetItemState( SDRATTR_TABLE_BORDER ) == SFX_ITEM_SET) || (rAttr.GetItemState( SDRATTR_TABLE_BORDER_INNER ) == SFX_ITEM_SET);
2337 if( bFrame )
2339 aAttr.ClearItem( SDRATTR_TABLE_BORDER );
2340 aAttr.ClearItem( SDRATTR_TABLE_BORDER_INNER );
2343 for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
2345 for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
2347 CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
2348 if( xCell.is() )
2350 if( bUndo )
2351 xCell->AddUndo();
2352 xCell->SetMergedItemSetAndBroadcast(aAttr, bReplaceAll);
2357 if( bFrame )
2359 ApplyBorderAttr( rAttr );
2362 UpdateTableShape();
2364 if( bUndo )
2365 mpModel->EndUndo();
2370 // --------------------------------------------------------------------
2372 bool SvxTableController::GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr) const
2374 if( mxTableObj.is() && hasSelectedCells() )
2376 MergeAttrFromSelectedCells( rTargetSet, bOnlyHardAttr );
2378 if( mpView->IsTextEdit() )
2380 if( mxTableObj->GetOutlinerParaObject() )
2381 rTargetSet.Put( SvxScriptTypeItem( mxTableObj->GetOutlinerParaObject()->GetTextObject().GetScriptType() ) );
2383 OutlinerView* pTextEditOutlinerView = mpView->GetTextEditOutlinerView();
2384 if(pTextEditOutlinerView)
2386 // FALSE= InvalidItems nicht al Default, sondern als "Loecher" betrachten
2387 rTargetSet.Put(pTextEditOutlinerView->GetAttribs(), FALSE);
2388 rTargetSet.Put( SvxScriptTypeItem( pTextEditOutlinerView->GetSelectedScriptType() ), FALSE );
2392 return true;
2394 else
2396 return false;
2400 // --------------------------------------------------------------------
2402 bool SvxTableController::SetAttributes(const SfxItemSet& rSet, bool bReplaceAll)
2404 if( mbCellSelectionMode || mpView->IsTextEdit() )
2406 SetAttrToSelectedCells( rSet, bReplaceAll );
2407 return true;
2409 return false;
2412 // --------------------------------------------------------------------
2414 bool SvxTableController::GetMarkedObjModel( SdrPage* pNewPage )
2416 if( mxTableObj.is() && mbCellSelectionMode && pNewPage ) try
2418 ::sdr::table::SdrTableObj& rTableObj = *static_cast< ::sdr::table::SdrTableObj* >( mxTableObj.get() );
2420 CellPos aStart, aEnd;
2421 getSelectedCells( aStart, aEnd );
2423 SdrTableObj* pNewTableObj = rTableObj.CloneRange( aStart, aEnd );
2425 pNewTableObj->SetPage( pNewPage );
2426 pNewTableObj->SetModel( pNewPage->GetModel() );
2428 SdrInsertReason aReason(SDRREASON_VIEWCALL);
2429 pNewPage->InsertObject(pNewTableObj,CONTAINER_APPEND,&aReason);
2431 return true;
2433 catch( Exception& )
2435 DBG_ERROR( "svx::SvxTableController::GetMarkedObjModel(), exception caught!" );
2437 return false;
2440 // --------------------------------------------------------------------
2442 bool SvxTableController::PasteObjModel( const SdrModel& rModel )
2444 if( mxTableObj.is() && mpView && (rModel.GetPageCount() >= 1) )
2446 const SdrPage* pPastePage = rModel.GetPage(0);
2447 if( pPastePage && pPastePage->GetObjCount() == 1 )
2449 SdrTableObj* pPasteTableObj = dynamic_cast< SdrTableObj* >( pPastePage->GetObj(0) );
2450 if( pPasteTableObj )
2452 return PasteObject( pPasteTableObj );
2457 return false;
2460 // --------------------------------------------------------------------
2462 bool SvxTableController::PasteObject( SdrTableObj* pPasteTableObj )
2464 if( !pPasteTableObj )
2465 return false;
2467 Reference< XTable > xPasteTable( pPasteTableObj->getTable() );
2468 if( !xPasteTable.is() )
2469 return false;
2471 if( !mxTable.is() )
2472 return false;
2474 sal_Int32 nPasteColumns = xPasteTable->getColumnCount();
2475 sal_Int32 nPasteRows = xPasteTable->getRowCount();
2477 CellPos aStart, aEnd;
2478 getSelectedCells( aStart, aEnd );
2480 if( mpView->IsTextEdit() )
2481 mpView->SdrEndTextEdit(sal_True);
2483 sal_Int32 nColumns = mxTable->getColumnCount();
2484 sal_Int32 nRows = mxTable->getRowCount();
2486 const sal_Int32 nMissing = nPasteRows - ( nRows - aStart.mnRow );
2487 if( nMissing > 0 )
2489 Reference< XTableRows > xRows( mxTable->getRows() );
2490 xRows->insertByIndex( nRows, nMissing );
2491 nRows = mxTable->getRowCount();
2494 nPasteRows = std::min( nPasteRows, nRows - aStart.mnRow );
2495 nPasteColumns = std::min( nPasteColumns, nColumns - aStart.mnCol );
2497 // copy cell contents
2498 for( sal_Int32 nRow = 0; nRow < nPasteRows; ++nRow )
2500 for( sal_Int32 nCol = 0; nCol < nPasteColumns; ++nCol )
2502 CellRef xTargetCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( aStart.mnCol + nCol, aStart.mnRow + nRow ).get() ) );
2503 if( xTargetCell.is() && !xTargetCell->isMerged() )
2505 xTargetCell->AddUndo();
2506 xTargetCell->cloneFrom( dynamic_cast< Cell* >( xPasteTable->getCellByPosition( nCol, nRow ).get() ) );
2507 nCol += xTargetCell->getColumnSpan() - 1;
2512 UpdateTableShape();
2514 return true;
2517 // --------------------------------------------------------------------
2519 IMPL_LINK( SvxTableController, UpdateHdl, void *, EMPTYARG )
2521 mnUpdateEvent = 0;
2523 if( mbCellSelectionMode )
2525 CellPos aStart( maCursorFirstPos );
2526 CellPos aEnd( maCursorLastPos );
2527 checkCell(aStart);
2528 checkCell(aEnd);
2529 if( aStart != maCursorFirstPos || aEnd != maCursorLastPos )
2531 setSelectedCells( aStart, aEnd );
2534 updateSelectionOverlay();
2536 return 0;