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