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