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