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