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