LCOV - code coverage report
Current view: top level - svx/source/table - tablecontroller.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1 1538 0.1 %
Date: 2015-06-13 12:38:46 Functions: 2 92 2.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <algorithm>
      21             : 
      22             : #include <svx/sdr/table/tablecontroller.hxx>
      23             : #include <tablemodel.hxx>
      24             : 
      25             : #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
      26             : #include <com/sun/star/container/XIndexAccess.hpp>
      27             : 
      28             : #include <com/sun/star/beans/XPropertySet.hpp>
      29             : #include <com/sun/star/table/XMergeableCellRange.hpp>
      30             : #include <com/sun/star/table/XMergeableCell.hpp>
      31             : 
      32             : #include <sal/config.h>
      33             : 
      34             : #include <vcl/svapp.hxx>
      35             : #include <vcl/settings.hxx>
      36             : 
      37             : #include <svl/whiter.hxx>
      38             : 
      39             : #include <sfx2/request.hxx>
      40             : 
      41             : #include <editeng/scripttypeitem.hxx>
      42             : #include <svx/svdotable.hxx>
      43             : #include <svx/sdr/overlay/overlayobjectcell.hxx>
      44             : #include <svx/sdr/overlay/overlaymanager.hxx>
      45             : #include <svx/svxids.hrc>
      46             : #include <editeng/outlobj.hxx>
      47             : #include <svx/svdoutl.hxx>
      48             : #include <svx/svdpagv.hxx>
      49             : #include <svx/svdetc.hxx>
      50             : #include <editeng/editobj.hxx>
      51             : #include "editeng/editstat.hxx"
      52             : #include "editeng/unolingu.hxx"
      53             : #include "svx/sdrpagewindow.hxx"
      54             : #include <svx/selectioncontroller.hxx>
      55             : #include <svx/svdmodel.hxx>
      56             : #include "svx/sdrpaintwindow.hxx"
      57             : #include <svx/svxdlg.hxx>
      58             : #include <editeng/boxitem.hxx>
      59             : #include "cell.hxx"
      60             : #include <editeng/borderline.hxx>
      61             : #include <editeng/colritem.hxx>
      62             : #include "editeng/lineitem.hxx"
      63             : #include "svx/svdstr.hrc"
      64             : #include "svdglob.hxx"
      65             : #include "svx/svdpage.hxx"
      66             : #include "tableundo.hxx"
      67             : #include "tablelayouter.hxx"
      68             : #include <vcl/msgbox.hxx>
      69             : #include <LibreOfficeKit/LibreOfficeKitEnums.h>
      70             : #include <memory>
      71             : #include <o3tl/enumarray.hxx>
      72             : #include <o3tl/enumrange.hxx>
      73             : 
      74             : using ::editeng::SvxBorderLine;
      75             : using namespace sdr::table;
      76             : using namespace ::com::sun::star;
      77             : using namespace ::com::sun::star::uno;
      78             : using namespace ::com::sun::star::table;
      79             : using namespace ::com::sun::star::beans;
      80             : using namespace ::com::sun::star::container;
      81             : using namespace ::com::sun::star::text;
      82             : using namespace ::com::sun::star::style;
      83             : 
      84             : namespace sdr { namespace table {
      85             : 
      86           0 : class SvxTableControllerModifyListener : public ::cppu::WeakImplHelper1< ::com::sun::star::util::XModifyListener >
      87             : {
      88             : public:
      89           0 :     explicit SvxTableControllerModifyListener( SvxTableController* pController )
      90           0 :         : mpController( pController ) {}
      91             : 
      92             :     // XModifyListener
      93             :     virtual void SAL_CALL modified( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
      94             : 
      95             :     // XEventListener
      96             :     virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
      97             : 
      98             :     SvxTableController* mpController;
      99             : };
     100             : 
     101             : 
     102             : // XModifyListener
     103             : 
     104             : 
     105           0 : void SAL_CALL SvxTableControllerModifyListener::modified( const ::com::sun::star::lang::EventObject&  ) throw (::com::sun::star::uno::RuntimeException, std::exception)
     106             : {
     107           0 :     if( mpController )
     108           0 :         mpController->onTableModified();
     109           0 : }
     110             : 
     111             : 
     112             : // XEventListener
     113             : 
     114             : 
     115           0 : void SAL_CALL SvxTableControllerModifyListener::disposing( const ::com::sun::star::lang::EventObject&  ) throw (::com::sun::star::uno::RuntimeException, std::exception)
     116             : {
     117           0 :     mpController = 0;
     118           0 : }
     119             : 
     120             : 
     121             : // class SvxTableController
     122             : 
     123             : 
     124           0 : rtl::Reference< sdr::SelectionController > CreateTableController( SdrObjEditView* pView, const SdrObject* pObj, const rtl::Reference< sdr::SelectionController >& xRefController )
     125             : {
     126           0 :     return SvxTableController::create( pView, pObj, xRefController );
     127             : }
     128             : 
     129             : 
     130             : 
     131           0 : rtl::Reference< sdr::SelectionController > SvxTableController::create( SdrObjEditView* pView, const SdrObject* pObj, const rtl::Reference< sdr::SelectionController >& xRefController )
     132             : {
     133           0 :     if( xRefController.is() )
     134             :     {
     135           0 :         SvxTableController* pController = dynamic_cast< SvxTableController* >( xRefController.get() );
     136           0 :         if( pController && (pController->mxTableObj.get() == pObj) && (pController->mpView == pView)  )
     137           0 :             return xRefController;
     138             :     }
     139           0 :     return new SvxTableController( pView, pObj );
     140             : }
     141             : 
     142             : 
     143             : 
     144           0 : SvxTableController::SvxTableController( SdrObjEditView* pView, const SdrObject* pObj )
     145             : : mbCellSelectionMode(false)
     146             : , mbLeftButtonDown(false)
     147             : , mpSelectionOverlay(0)
     148             : , mpView( dynamic_cast< SdrView* >( pView ) )
     149             : , mxTableObj( dynamic_cast< SdrTableObj* >( const_cast< SdrObject* >( pObj ) ) )
     150             : , mpModel( 0 )
     151           0 : , mnUpdateEvent( 0 )
     152             : {
     153           0 :     if( pObj )
     154             :     {
     155           0 :         mpModel = pObj->GetModel();
     156             : 
     157           0 :         if( mxTableObj.is() )
     158             :         {
     159           0 :             static_cast< const SdrTableObj* >( pObj )->getActiveCellPos( maCursorFirstPos );
     160           0 :             maCursorLastPos = maCursorFirstPos;
     161             : 
     162           0 :             Reference< XTable > xTable( static_cast< const SdrTableObj* >( pObj )->getTable() );
     163           0 :             if( xTable.is() )
     164             :             {
     165           0 :                 mxModifyListener = new SvxTableControllerModifyListener( this );
     166           0 :                 xTable->addModifyListener( mxModifyListener );
     167             : 
     168           0 :                 mxTable.set( dynamic_cast< TableModel* >( xTable.get() ) );
     169           0 :             }
     170             :         }
     171             :     }
     172           0 : }
     173             : 
     174           0 : SvxTableController::~SvxTableController()
     175             : {
     176           0 :     if( mnUpdateEvent )
     177             :     {
     178           0 :         Application::RemoveUserEvent( mnUpdateEvent );
     179             :     }
     180             : 
     181           0 :     if( mxModifyListener.is() && mxTableObj.get() )
     182             :     {
     183           0 :         Reference< XTable > xTable( static_cast< SdrTableObj* >( mxTableObj.get() )->getTable() );
     184           0 :         if( xTable.is() )
     185             :         {
     186           0 :             xTable->removeModifyListener( mxModifyListener );
     187           0 :             mxModifyListener.clear();
     188           0 :         }
     189             :     }
     190           0 : }
     191             : 
     192             : 
     193             : 
     194             : const sal_uInt16 ACTION_NONE = 0;
     195             : const sal_uInt16 ACTION_GOTO_FIRST_CELL = 1;
     196             : const sal_uInt16 ACTION_GOTO_FIRST_COLUMN = 2;
     197             : const sal_uInt16 ACTION_GOTO_FIRST_ROW = 3;
     198             : const sal_uInt16 ACTION_GOTO_LEFT_CELL = 4;
     199             : const sal_uInt16 ACTION_GOTO_UP_CELL = 5;
     200             : const sal_uInt16 ACTION_GOTO_RIGHT_CELL = 6;
     201             : const sal_uInt16 ACTION_GOTO_DOWN_CELL = 7;
     202             : const sal_uInt16 ACTION_GOTO_LAST_CELL = 8;
     203             : const sal_uInt16 ACTION_GOTO_LAST_COLUMN = 9;
     204             : const sal_uInt16 ACTION_GOTO_LAST_ROW = 10;
     205             : const sal_uInt16 ACTION_EDIT_CELL = 11;
     206             : const sal_uInt16 ACTION_STOP_TEXT_EDIT = 12;
     207             : const sal_uInt16 ACTION_REMOVE_SELECTION = 13;
     208             : const sal_uInt16 ACTION_START_SELECTION = 14;
     209             : const sal_uInt16 ACTION_HANDLED_BY_VIEW = 15;
     210             : const sal_uInt16 ACTION_TAB = 18;
     211             : 
     212           0 : bool SvxTableController::onKeyInput(const KeyEvent& rKEvt, vcl::Window* pWindow )
     213             : {
     214           0 :     if( !checkTableObject() )
     215           0 :         return false;
     216             : 
     217             :     // check if we are read only
     218           0 :     if( mpModel && mpModel->IsReadOnly())
     219             :     {
     220           0 :         switch( rKEvt.GetKeyCode().GetCode() )
     221             :         {
     222             :         case awt::Key::DOWN:
     223             :         case awt::Key::UP:
     224             :         case awt::Key::LEFT:
     225             :         case awt::Key::RIGHT:
     226             :         case awt::Key::TAB:
     227             :         case awt::Key::HOME:
     228             :         case awt::Key::END:
     229             :         case awt::Key::NUM2:
     230             :         case awt::Key::NUM4:
     231             :         case awt::Key::NUM6:
     232             :         case awt::Key::NUM8:
     233             :         case awt::Key::ESCAPE:
     234             :         case awt::Key::F2:
     235           0 :             break;
     236             :         default:
     237             :             // tell the view we eat the event, no further processing needed
     238           0 :             return true;
     239             :         }
     240             :     }
     241             : 
     242           0 :     sal_uInt16 nAction = getKeyboardAction( rKEvt, pWindow );
     243             : 
     244           0 :     return executeAction( nAction, rKEvt.GetKeyCode().IsShift(), pWindow );
     245             : }
     246             : 
     247             : 
     248             : // ::com::sun::star::awt::XMouseClickHandler:
     249             : 
     250             : 
     251           0 : bool SvxTableController::onMouseButtonDown(const MouseEvent& rMEvt, vcl::Window* pWindow )
     252             : {
     253           0 :     if (mxTableObj->GetModel()->isTiledRendering() && !pWindow)
     254             :     {
     255             :         // Tiled rendering: get the window that has the disabled map mode.
     256           0 :         if (OutputDevice* pOutputDevice = mpView->GetFirstOutputDevice())
     257             :         {
     258           0 :             if (pOutputDevice->GetOutDevType() == OUTDEV_WINDOW)
     259           0 :                 pWindow = static_cast<vcl::Window*>(pOutputDevice);
     260             :         }
     261             :     }
     262             : 
     263           0 :     if( !pWindow || !checkTableObject() )
     264           0 :         return false;
     265             : 
     266           0 :     SdrViewEvent aVEvt;
     267           0 :     if( !rMEvt.IsRight() && mpView->PickAnything(rMEvt,SdrMouseEventKind::BUTTONDOWN, aVEvt) == SDRHIT_HANDLE )
     268           0 :         return false;
     269             : 
     270           0 :     TableHitKind eHit = static_cast< SdrTableObj* >(mxTableObj.get())->CheckTableHit( pWindow->PixelToLogic(rMEvt.GetPosPixel()), maMouseDownPos.mnCol, maMouseDownPos.mnRow, 0 );
     271             : 
     272           0 :     mbLeftButtonDown = (rMEvt.GetClicks() == 1) && rMEvt.IsLeft();
     273             : 
     274           0 :     if( eHit == SDRTABLEHIT_CELL )
     275             :     {
     276           0 :         StartSelection( maMouseDownPos );
     277           0 :         return true;
     278             :     }
     279             : 
     280           0 :     if( rMEvt.IsRight() && eHit != SDRTABLEHIT_NONE )
     281           0 :         return true; // right click will become context menu
     282             : 
     283             :     // for cell selection with the mouse remember our first hit
     284           0 :     if( mbLeftButtonDown )
     285             :     {
     286           0 :         RemoveSelection();
     287             : 
     288           0 :         Point aPnt(rMEvt.GetPosPixel());
     289           0 :         if (pWindow!=NULL)
     290           0 :             aPnt=pWindow->PixelToLogic(aPnt);
     291             : 
     292           0 :         SdrHdl* pHdl = mpView->PickHandle(aPnt);
     293             : 
     294           0 :         if( pHdl )
     295             :         {
     296           0 :             mbLeftButtonDown = false;
     297             :         }
     298             :         else
     299             :         {
     300           0 :             sdr::table::SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( mxTableObj.get() );
     301             : 
     302           0 :             if( !pWindow || !pTableObj || eHit  == SDRTABLEHIT_NONE)
     303             :             {
     304           0 :                 mbLeftButtonDown = false;
     305             :             }
     306             :         }
     307             :     }
     308             : 
     309           0 :     if (mxTableObj->GetModel()->isTiledRendering() && rMEvt.GetClicks() == 2 && rMEvt.IsLeft() && eHit == SDRTABLEHIT_CELLTEXTAREA)
     310             :     {
     311           0 :         bool bEmptyOutliner = false;
     312           0 :         if (Outliner* pOutliner = mpView->GetTextEditOutliner())
     313             :         {
     314           0 :             if (pOutliner->GetParagraphCount() == 1)
     315             :             {
     316           0 :                 if (Paragraph* pParagraph = pOutliner->GetParagraph(0))
     317           0 :                     bEmptyOutliner = pOutliner->GetText(pParagraph).isEmpty();
     318             :             }
     319             :         }
     320           0 :         if (bEmptyOutliner)
     321             :         {
     322             :             // Tiled rendering: a left double-click in an empty cell: select it.
     323           0 :             StartSelection(maMouseDownPos);
     324           0 :             setSelectedCells(maMouseDownPos, maMouseDownPos);
     325             :             // Update graphic selection, should be hidden now.
     326           0 :             mpView->AdjustMarkHdl();
     327           0 :             return true;
     328             :         }
     329             :     }
     330             : 
     331           0 :     return false;
     332             : }
     333             : 
     334             : 
     335             : 
     336           0 : bool SvxTableController::onMouseButtonUp(const MouseEvent& rMEvt, vcl::Window* /*pWin*/)
     337             : {
     338           0 :     if( !checkTableObject() )
     339           0 :         return false;
     340             : 
     341           0 :     mbLeftButtonDown = false;
     342             : 
     343           0 :     if( rMEvt.GetClicks() == 2 )
     344           0 :         return true;
     345             : 
     346           0 :     return false;
     347             : }
     348             : 
     349             : 
     350             : 
     351           0 : bool SvxTableController::onMouseMove(const MouseEvent& rMEvt, vcl::Window* pWindow )
     352             : {
     353           0 :     if( !checkTableObject() )
     354           0 :         return false;
     355             : 
     356           0 :     SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
     357           0 :     CellPos aPos;
     358           0 :     if( mbLeftButtonDown && pTableObj && pTableObj->CheckTableHit( pWindow->PixelToLogic(rMEvt.GetPosPixel()), aPos.mnCol, aPos.mnRow, 0 ) != SDRTABLEHIT_NONE )
     359             :     {
     360           0 :         if(aPos != maMouseDownPos)
     361             :         {
     362           0 :             if( mbCellSelectionMode )
     363             :             {
     364           0 :                 setSelectedCells( maMouseDownPos, aPos );
     365           0 :                 return true;
     366             :             }
     367             :             else
     368             :             {
     369           0 :                 StartSelection( maMouseDownPos );
     370             :             }
     371             :         }
     372           0 :         else if( mbCellSelectionMode )
     373             :         {
     374           0 :             UpdateSelection( aPos );
     375           0 :             return true;
     376             :         }
     377             :     }
     378           0 :     return false;
     379             : }
     380             : 
     381             : 
     382             : 
     383           0 : void SvxTableController::onSelectionHasChanged()
     384             : {
     385           0 :     bool bSelected = false;
     386             : 
     387           0 :     SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
     388           0 :     if( pTableObj && pTableObj->IsTextEditActive() )
     389             :     {
     390           0 :         pTableObj->getActiveCellPos( maCursorFirstPos );
     391           0 :         maCursorLastPos = maCursorFirstPos;
     392           0 :         mbCellSelectionMode = false;
     393             :     }
     394             :     else
     395             :     {
     396           0 :         const SdrMarkList& rMarkList= mpView->GetMarkedObjectList();
     397           0 :         if( rMarkList.GetMarkCount() == 1 )
     398           0 :             bSelected = mxTableObj.get() == rMarkList.GetMark(0)->GetMarkedSdrObj();
     399             :         /* fdo#46186 Selecting the table means selecting the entire cells */
     400           0 :         if (!hasSelectedCells() && pTableObj)
     401             :         {
     402           0 :             maCursorFirstPos = SdrTableObj::getFirstCell();
     403           0 :             maCursorLastPos = pTableObj->getLastCell();
     404           0 :             mbCellSelectionMode=true;
     405             :         }
     406             :     }
     407             : 
     408           0 :     if( bSelected )
     409             :     {
     410           0 :         updateSelectionOverlay();
     411             :     }
     412             :     else
     413             :     {
     414           0 :         destroySelectionOverlay();
     415             :     }
     416           0 : }
     417             : 
     418             : 
     419             : 
     420           0 : void SvxTableController::GetState( SfxItemSet& rSet )
     421             : {
     422           0 :     if( !mxTable.is() || !mxTableObj.is() || !mxTableObj->GetModel() )
     423           0 :         return;
     424             : 
     425           0 :     std::unique_ptr<SfxItemSet> xSet;
     426             : 
     427           0 :     bool bVertDone = false;
     428             : 
     429             :     // Iterate over all requested items in the set.
     430           0 :     SfxWhichIter aIter( rSet );
     431           0 :     sal_uInt16 nWhich = aIter.FirstWhich();
     432           0 :     while (nWhich)
     433             :     {
     434           0 :         switch (nWhich)
     435             :         {
     436             :             case SID_TABLE_VERT_BOTTOM:
     437             :             case SID_TABLE_VERT_CENTER:
     438             :             case SID_TABLE_VERT_NONE:
     439             :                 {
     440           0 :                     if( !mxTable.is() || !mxTableObj->GetModel() )
     441             :                     {
     442           0 :                         rSet.DisableItem(nWhich);
     443             :                     }
     444           0 :                     else if(!bVertDone)
     445             :                     {
     446           0 :                         if (!xSet)
     447             :                         {
     448           0 :                             xSet.reset(new SfxItemSet( mxTableObj->GetModel()->GetItemPool() ));
     449           0 :                             MergeAttrFromSelectedCells(*xSet, false);
     450             :                         }
     451             : 
     452           0 :                         SdrTextVertAdjust eAdj = SDRTEXTVERTADJUST_BLOCK;
     453             : 
     454           0 :                         if (xSet->GetItemState( SDRATTR_TEXT_VERTADJUST ) != SfxItemState::DONTCARE)
     455           0 :                             eAdj = static_cast<const SdrTextVertAdjustItem&>(xSet->Get(SDRATTR_TEXT_VERTADJUST)).GetValue();
     456             : 
     457           0 :                         rSet.Put(SfxBoolItem(SID_TABLE_VERT_BOTTOM, eAdj == SDRTEXTVERTADJUST_BOTTOM));
     458           0 :                         rSet.Put(SfxBoolItem(SID_TABLE_VERT_CENTER, eAdj == SDRTEXTVERTADJUST_CENTER));
     459           0 :                         rSet.Put(SfxBoolItem(SID_TABLE_VERT_NONE, eAdj == SDRTEXTVERTADJUST_TOP));
     460           0 :                         bVertDone = true;
     461             :                     }
     462           0 :                     break;
     463             :                 }
     464             :             case SID_TABLE_DELETE_ROW:
     465           0 :                 if( !mxTable.is() || !hasSelectedCells() || (mxTable->getRowCount() <= 1) )
     466           0 :                     rSet.DisableItem(SID_TABLE_DELETE_ROW);
     467           0 :                 break;
     468             :             case SID_TABLE_DELETE_COL:
     469           0 :                 if( !mxTable.is() || !hasSelectedCells() || (mxTable->getColumnCount() <= 1) )
     470           0 :                     rSet.DisableItem(SID_TABLE_DELETE_COL);
     471           0 :                 break;
     472             :             case SID_TABLE_MERGE_CELLS:
     473           0 :                 if( !mxTable.is() || !hasSelectedCells() )
     474           0 :                     rSet.DisableItem(SID_TABLE_MERGE_CELLS);
     475           0 :                 break;
     476             :             case SID_TABLE_SPLIT_CELLS:
     477           0 :                 if( !hasSelectedCells() || !mxTable.is() )
     478           0 :                     rSet.DisableItem(SID_TABLE_SPLIT_CELLS);
     479           0 :                 break;
     480             : 
     481             :             case SID_OPTIMIZE_TABLE:
     482             :             case SID_TABLE_DISTRIBUTE_COLUMNS:
     483             :             case SID_TABLE_DISTRIBUTE_ROWS:
     484             :             {
     485           0 :                 bool bDistributeColumns = false;
     486           0 :                 bool bDistributeRows = false;
     487           0 :                 if( mxTable.is() )
     488             :                 {
     489           0 :                     CellPos aStart, aEnd;
     490           0 :                     getSelectedCells( aStart, aEnd );
     491             : 
     492           0 :                     bDistributeColumns = aStart.mnCol != aEnd.mnCol;
     493           0 :                     bDistributeRows = aStart.mnRow != aEnd.mnRow;
     494             :                 }
     495           0 :                 if( !bDistributeColumns && !bDistributeRows )
     496           0 :                     rSet.DisableItem(SID_OPTIMIZE_TABLE);
     497           0 :                 if( !bDistributeColumns )
     498           0 :                     rSet.DisableItem(SID_TABLE_DISTRIBUTE_COLUMNS);
     499           0 :                 if( !bDistributeRows )
     500           0 :                     rSet.DisableItem(SID_TABLE_DISTRIBUTE_ROWS);
     501           0 :                 break;
     502             :             }
     503             : 
     504             :             case SID_AUTOFORMAT:
     505             :             case SID_TABLE_SORT_DIALOG:
     506             :             case SID_TABLE_AUTOSUM:
     507             : //              if( !mxTable.is() )
     508             : //                  rSet.DisableItem( nWhich );
     509           0 :                 break;
     510             :             default:
     511           0 :                 break;
     512             :         }
     513           0 :         nWhich = aIter.NextWhich();
     514           0 :     }
     515             : }
     516             : 
     517             : 
     518             : 
     519           0 : void SvxTableController::onInsert( sal_uInt16 nSId, const SfxItemSet* pArgs )
     520             : {
     521           0 :     sdr::table::SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( mxTableObj.get() );
     522           0 :     if( !pTableObj )
     523           0 :         return;
     524             : 
     525           0 :     if( mxTable.is() ) try
     526             :     {
     527             : 
     528           0 :         bool bInsertAfter = true;
     529           0 :         sal_uInt16 nCount = 0;
     530           0 :         if( pArgs )
     531             :         {
     532           0 :             const SfxPoolItem* pItem = 0;
     533           0 :             pArgs->GetItemState(nSId, false, &pItem);
     534           0 :             if (pItem)
     535             :             {
     536           0 :                 nCount = static_cast<const SfxInt16Item*>(pItem)->GetValue();
     537           0 :                 if(SfxItemState::SET == pArgs->GetItemState(SID_TABLE_PARAM_INSERT_AFTER, true, &pItem))
     538           0 :                     bInsertAfter = static_cast<const SfxBoolItem*>(pItem)->GetValue();
     539             :             }
     540             :         }
     541             : 
     542           0 :         CellPos aStart, aEnd;
     543           0 :         if( hasSelectedCells() )
     544             :         {
     545           0 :             getSelectedCells( aStart, aEnd );
     546             :         }
     547             :         else
     548             :         {
     549           0 :             if( bInsertAfter )
     550             :             {
     551           0 :                 aStart.mnCol = mxTable->getColumnCount() - 1;
     552           0 :                 aStart.mnRow = mxTable->getRowCount() - 1;
     553           0 :                 aEnd = aStart;
     554             :             }
     555             :         }
     556             : 
     557           0 :         if( pTableObj->IsTextEditActive() )
     558           0 :             mpView->SdrEndTextEdit(true);
     559             : 
     560           0 :         RemoveSelection();
     561             : 
     562           0 :         const OUString sSize( "Size" );
     563             : 
     564           0 :         const bool bUndo = mpModel && mpModel->IsUndoEnabled();
     565             : 
     566           0 :         switch( nSId )
     567             :         {
     568             :         case SID_TABLE_INSERT_COL:
     569             :         {
     570           0 :             TableModelNotifyGuard aGuard( mxTable.get() );
     571             : 
     572           0 :             if( bUndo )
     573             :             {
     574           0 :                 mpModel->BegUndo( ImpGetResStr(STR_TABLE_INSCOL) );
     575           0 :                 mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
     576             :             }
     577             : 
     578           0 :             Reference< XTableColumns > xCols( mxTable->getColumns() );
     579           0 :             const sal_Int32 nNewColumns = (nCount == 0) ? (aEnd.mnCol - aStart.mnCol + 1) : nCount;
     580           0 :             const sal_Int32 nNewStartColumn = aEnd.mnCol + (bInsertAfter ? 1 : 0);
     581           0 :             xCols->insertByIndex( nNewStartColumn, nNewColumns );
     582             : 
     583           0 :             for( sal_Int32 nOffset = 0; nOffset < nNewColumns; nOffset++ )
     584             :             {
     585             :                 // Resolves fdo#61540
     586             :                 // On Insert before, the reference column whose size is going to be
     587             :                 // used for newly created column(s) is wrong. As the new columns are
     588             :                 // inserted before the reference column, the reference column moved
     589             :                 // to the new position by no., of new columns i.e (earlier+newcolumns).
     590           0 :                 Reference< XPropertySet >(xCols->getByIndex(nNewStartColumn+nOffset), UNO_QUERY_THROW )->
     591             :                     setPropertyValue( sSize,
     592           0 :                         Reference< XPropertySet >(xCols->getByIndex( bInsertAfter?nNewStartColumn-1:nNewStartColumn+nNewColumns ), UNO_QUERY_THROW )->
     593           0 :                             getPropertyValue( sSize ) );
     594             :             }
     595             : 
     596             :             // Copy cell properties
     597           0 :             sal_Int32 nPropSrcCol = (bInsertAfter ? aEnd.mnCol : aStart.mnCol + nNewColumns);
     598           0 :             sal_Int32 nRowSpan = 0;
     599           0 :             bool bNewSpan = false;
     600             : 
     601           0 :             for( sal_Int32 nRow = 0; nRow < mxTable->getRowCount(); ++nRow )
     602             :             {
     603           0 :                 CellRef xSourceCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nPropSrcCol, nRow ).get() ) );
     604             : 
     605             :                 // When we insert new COLUMNs, we want to copy ROW spans.
     606           0 :                 if (xSourceCell.is() && nRowSpan == 0)
     607             :                 {
     608             :                     // we are not in a span yet. Let's find out if the current cell is in a span.
     609           0 :                     sal_Int32 nColSpan = sal_Int32();
     610           0 :                     sal_Int32 nSpanInfoCol = sal_Int32();
     611             : 
     612           0 :                     if( xSourceCell->getRowSpan() > 1 )
     613             :                     {
     614             :                         // The current cell is the top-left cell in a span.
     615             :                         // Get the span info and propagate it to the target.
     616           0 :                         nRowSpan = xSourceCell->getRowSpan();
     617           0 :                         nColSpan = xSourceCell->getColumnSpan();
     618           0 :                         nSpanInfoCol = nPropSrcCol;
     619             :                     }
     620           0 :                     else if( xSourceCell->isMerged() )
     621             :                     {
     622             :                         // The current cell is a middle cell in a 2D span.
     623             :                         // Look for the top-left cell in the span.
     624           0 :                         for( nSpanInfoCol = nPropSrcCol - 1; nSpanInfoCol >= 0; --nSpanInfoCol )
     625             :                         {
     626           0 :                             CellRef xMergeInfoCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nSpanInfoCol, nRow ).get() ) );
     627           0 :                             if (xMergeInfoCell.is() && !xMergeInfoCell->isMerged())
     628             :                             {
     629           0 :                                 nRowSpan = xMergeInfoCell->getRowSpan();
     630           0 :                                 nColSpan = xMergeInfoCell->getColumnSpan();
     631           0 :                                 break;
     632             :                             }
     633           0 :                         }
     634           0 :                         if( nRowSpan == 1 )
     635           0 :                             nRowSpan = 0;
     636             :                     }
     637             : 
     638             :                     // The target colomns are outside the span; Start a new span.
     639           0 :                     if( nRowSpan > 0 && ( nNewStartColumn < nSpanInfoCol || nSpanInfoCol + nColSpan <= nNewStartColumn ) )
     640           0 :                         bNewSpan = true;
     641             :                 }
     642             : 
     643             :                 // Now copy the properties from the source to the targets
     644           0 :                 for( sal_Int32 nOffset = 0; nOffset < nNewColumns; nOffset++ )
     645             :                 {
     646           0 :                     CellRef xTargetCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nNewStartColumn + nOffset, nRow ).get() ) );
     647           0 :                     if( xTargetCell.is() )
     648             :                     {
     649           0 :                         if( nRowSpan > 0 )
     650             :                         {
     651           0 :                             if( bNewSpan )
     652           0 :                                 xTargetCell->merge( 1, nRowSpan );
     653             :                             else
     654           0 :                                 xTargetCell->setMerged();
     655             :                         }
     656           0 :                         xTargetCell->copyFormatFrom( xSourceCell );
     657             :                     }
     658           0 :                 }
     659             : 
     660           0 :                 if( nRowSpan > 0 )
     661             :                 {
     662           0 :                     --nRowSpan;
     663           0 :                     bNewSpan = false;
     664             :                 }
     665           0 :             }
     666             : 
     667           0 :             if( bUndo )
     668           0 :                 mpModel->EndUndo();
     669             : 
     670           0 :             aStart.mnCol = nNewStartColumn;
     671           0 :             aStart.mnRow = 0;
     672           0 :             aEnd.mnCol = aStart.mnCol + nNewColumns - 1;
     673           0 :             aEnd.mnRow = mxTable->getRowCount() - 1;
     674           0 :             break;
     675             :         }
     676             : 
     677             :         case SID_TABLE_INSERT_ROW:
     678             :         {
     679           0 :             TableModelNotifyGuard aGuard( mxTable.get() );
     680             : 
     681           0 :             if( bUndo )
     682             :             {
     683           0 :                 mpModel->BegUndo( ImpGetResStr(STR_TABLE_INSROW ) );
     684           0 :                 mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
     685             :             }
     686             : 
     687           0 :             Reference< XTableRows > xRows( mxTable->getRows() );
     688           0 :             const sal_Int32 nNewRows = (nCount == 0) ? (aEnd.mnRow - aStart.mnRow + 1) : nCount;
     689           0 :             const sal_Int32 nNewRowStart = aEnd.mnRow + (bInsertAfter ? 1 : 0);
     690           0 :             xRows->insertByIndex( nNewRowStart, nNewRows );
     691             : 
     692           0 :             for( sal_Int32 nOffset = 0; nOffset < nNewRows; nOffset++ )
     693             :             {
     694           0 :                 Reference< XPropertySet >( xRows->getByIndex( aEnd.mnRow + nOffset + 1 ), UNO_QUERY_THROW )->
     695             :                     setPropertyValue( sSize,
     696           0 :                         Reference< XPropertySet >( xRows->getByIndex( aStart.mnRow + nOffset ), UNO_QUERY_THROW )->
     697           0 :                             getPropertyValue( sSize ) );
     698             :             }
     699             : 
     700             :             // Copy the cell properties
     701           0 :             sal_Int32 nPropSrcRow = (bInsertAfter ? aEnd.mnRow : aStart.mnRow + nNewRows);
     702           0 :             sal_Int32 nColSpan = 0;
     703           0 :             bool bNewSpan = false;
     704             : 
     705           0 :             for( sal_Int32 nCol = 0; nCol < mxTable->getColumnCount(); ++nCol )
     706             :             {
     707           0 :                 CellRef xSourceCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nPropSrcRow ).get() ) );
     708             : 
     709           0 :                 if (!xSourceCell.is())
     710           0 :                     continue;
     711             : 
     712             :                 // When we insert new ROWs, we want to copy COLUMN spans.
     713           0 :                 if( nColSpan == 0 )
     714             :                 {
     715             :                     // we are not in a span yet. Let's find out if the current cell is in a span.
     716           0 :                     sal_Int32 nRowSpan = sal_Int32();
     717           0 :                     sal_Int32 nSpanInfoRow = sal_Int32();
     718             : 
     719           0 :                     if( xSourceCell->getColumnSpan() > 1 )
     720             :                     {
     721             :                         // The current cell is the top-left cell in a span.
     722             :                         // Get the span info and propagate it to the target.
     723           0 :                         nColSpan = xSourceCell->getColumnSpan();
     724           0 :                         nRowSpan = xSourceCell->getRowSpan();
     725           0 :                         nSpanInfoRow = nPropSrcRow;
     726             :                     }
     727           0 :                     else if( xSourceCell->isMerged() )
     728             :                     {
     729             :                         // The current cell is a middle cell in a 2D span.
     730             :                         // Look for the top-left cell in the span.
     731           0 :                         for( nSpanInfoRow = nPropSrcRow - 1; nSpanInfoRow >= 0; --nSpanInfoRow )
     732             :                         {
     733           0 :                             CellRef xMergeInfoCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nSpanInfoRow ).get() ) );
     734           0 :                             if (xMergeInfoCell.is() && !xMergeInfoCell->isMerged())
     735             :                             {
     736           0 :                                 nColSpan = xMergeInfoCell->getColumnSpan();
     737           0 :                                 nRowSpan = xMergeInfoCell->getRowSpan();
     738           0 :                                 break;
     739             :                             }
     740           0 :                         }
     741           0 :                         if( nColSpan == 1 )
     742           0 :                             nColSpan = 0;
     743             :                     }
     744             : 
     745             :                     // Inserted rows are outside the span; Start a new span.
     746           0 :                     if( nColSpan > 0 && ( nNewRowStart < nSpanInfoRow || nSpanInfoRow + nRowSpan <= nNewRowStart ) )
     747           0 :                         bNewSpan = true;
     748             :                 }
     749             : 
     750             :                 // Now copy the properties from the source to the targets
     751           0 :                 for( sal_Int32 nOffset = 0; nOffset < nNewRows; ++nOffset )
     752             :                 {
     753           0 :                     CellRef xTargetCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nNewRowStart + nOffset ).get() ) );
     754           0 :                     if( xTargetCell.is() )
     755             :                     {
     756           0 :                         if( nColSpan > 0 )
     757             :                         {
     758           0 :                             if( bNewSpan )
     759           0 :                                 xTargetCell->merge( nColSpan, 1 );
     760             :                             else
     761           0 :                                 xTargetCell->setMerged();
     762             :                         }
     763           0 :                         xTargetCell->copyFormatFrom( xSourceCell );
     764             :                     }
     765           0 :                 }
     766             : 
     767           0 :                 if( nColSpan > 0 )
     768             :                 {
     769           0 :                     --nColSpan;
     770           0 :                     bNewSpan = false;
     771             :                 }
     772           0 :             }
     773             : 
     774           0 :             if( bUndo )
     775           0 :                 mpModel->EndUndo();
     776             : 
     777           0 :             aStart.mnCol = 0;
     778           0 :             aStart.mnRow = nNewRowStart;
     779           0 :             aEnd.mnCol = mxTable->getColumnCount() - 1;
     780           0 :             aEnd.mnRow = aStart.mnRow + nNewRows - 1;
     781           0 :             break;
     782             :         }
     783             :         }
     784             : 
     785           0 :         StartSelection( aStart );
     786           0 :         UpdateSelection( aEnd );
     787             :     }
     788           0 :     catch( Exception& )
     789             :     {
     790             :         OSL_FAIL("svx::SvxTableController::onInsert(), exception caught!");
     791             :     }
     792             : }
     793             : 
     794             : 
     795             : 
     796           0 : void SvxTableController::onDelete( sal_uInt16 nSId )
     797             : {
     798           0 :     sdr::table::SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( mxTableObj.get() );
     799           0 :     if( !pTableObj )
     800           0 :         return;
     801             : 
     802           0 :     if( mxTable.is() && hasSelectedCells() )
     803             :     {
     804           0 :         CellPos aStart, aEnd;
     805           0 :         getSelectedCells( aStart, aEnd );
     806             : 
     807           0 :         if( pTableObj->IsTextEditActive() )
     808           0 :             mpView->SdrEndTextEdit(true);
     809             : 
     810           0 :         RemoveSelection();
     811             : 
     812           0 :         bool bDeleteTable = false;
     813           0 :         switch( nSId )
     814             :         {
     815             :         case SID_TABLE_DELETE_COL:
     816             :         {
     817           0 :             const sal_Int32 nRemovedColumns = aEnd.mnCol - aStart.mnCol + 1;
     818           0 :             if( nRemovedColumns == mxTable->getColumnCount() )
     819             :             {
     820           0 :                 bDeleteTable = true;
     821             :             }
     822             :             else
     823             :             {
     824           0 :                 Reference< XTableColumns > xCols( mxTable->getColumns() );
     825           0 :                 xCols->removeByIndex( aStart.mnCol, nRemovedColumns );
     826             :             }
     827           0 :             break;
     828             :         }
     829             : 
     830             :         case SID_TABLE_DELETE_ROW:
     831             :         {
     832           0 :             const sal_Int32 nRemovedRows = aEnd.mnRow - aStart.mnRow + 1;
     833           0 :             if( nRemovedRows == mxTable->getRowCount() )
     834             :             {
     835           0 :                 bDeleteTable = true;
     836             :             }
     837             :             else
     838             :             {
     839           0 :                 Reference< XTableRows > xRows( mxTable->getRows() );
     840           0 :                 xRows->removeByIndex( aStart.mnRow, nRemovedRows );
     841             :             }
     842           0 :             break;
     843             :         }
     844             :         }
     845             : 
     846           0 :         if( bDeleteTable )
     847           0 :             mpView->DeleteMarkedObj();
     848             :         else
     849           0 :             UpdateTableShape();
     850             :     }
     851             : }
     852             : 
     853             : 
     854             : 
     855           0 : void SvxTableController::onSelect( sal_uInt16 nSId )
     856             : {
     857           0 :     if( mxTable.is() )
     858             :     {
     859           0 :         const sal_Int32 nRowCount = mxTable->getRowCount();
     860           0 :         const sal_Int32 nColCount = mxTable->getColumnCount();
     861           0 :         if( nRowCount && nColCount )
     862             :         {
     863           0 :             CellPos aStart, aEnd;
     864           0 :             getSelectedCells( aStart, aEnd );
     865             : 
     866           0 :             switch( nSId )
     867             :             {
     868             :             case SID_TABLE_SELECT_ALL:
     869           0 :                 aEnd.mnCol = 0; aEnd.mnRow = 0;
     870           0 :                 aStart.mnCol = nColCount - 1; aStart.mnRow = nRowCount - 1;
     871           0 :                 break;
     872             :             case SID_TABLE_SELECT_COL:
     873           0 :                 aEnd.mnRow = nRowCount - 1;
     874           0 :                 aStart.mnRow = 0;
     875           0 :                 break;
     876             :             case SID_TABLE_SELECT_ROW:
     877           0 :                 aEnd.mnCol = nColCount - 1;
     878           0 :                 aStart.mnCol = 0;
     879           0 :                 break;
     880             :             }
     881             : 
     882           0 :             StartSelection( aEnd );
     883           0 :             gotoCell( aStart, true, 0 );
     884             :         }
     885             :     }
     886           0 : }
     887             : 
     888             : namespace
     889             : {
     890           0 :     SvxBoxItem mergeDrawinglayerTextDistancesAndSvxBoxItem(const SfxItemSet& rAttrSet)
     891             :     {
     892             :         // merge drawing layer text distance items into SvxBoxItem used by the dialog
     893           0 :         SvxBoxItem aBoxItem( static_cast< const SvxBoxItem& >( rAttrSet.Get( SDRATTR_TABLE_BORDER ) ) );
     894           0 :         aBoxItem.SetDistance( sal::static_int_cast< sal_uInt16 >( static_cast<const SdrMetricItem&>(rAttrSet.Get(SDRATTR_TEXT_LEFTDIST)).GetValue()), SvxBoxItemLine::LEFT );
     895           0 :         aBoxItem.SetDistance( sal::static_int_cast< sal_uInt16 >( static_cast<const SdrMetricItem&>(rAttrSet.Get(SDRATTR_TEXT_RIGHTDIST)).GetValue()), SvxBoxItemLine::RIGHT );
     896           0 :         aBoxItem.SetDistance( sal::static_int_cast< sal_uInt16 >( static_cast<const SdrMetricItem&>(rAttrSet.Get(SDRATTR_TEXT_UPPERDIST)).GetValue()), SvxBoxItemLine::TOP );
     897           0 :         aBoxItem.SetDistance( sal::static_int_cast< sal_uInt16 >( static_cast<const SdrMetricItem&>(rAttrSet.Get(SDRATTR_TEXT_LOWERDIST)).GetValue()), SvxBoxItemLine::BOTTOM );
     898           0 :         return aBoxItem;
     899             :     }
     900             : }
     901             : 
     902           0 : void SvxTableController::onFormatTable( SfxRequest& rReq )
     903             : {
     904           0 :     sdr::table::SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( mxTableObj.get() );
     905           0 :     if( !pTableObj )
     906           0 :         return;
     907             : 
     908           0 :     const SfxItemSet* pArgs = rReq.GetArgs();
     909             : 
     910           0 :     if( !pArgs && pTableObj->GetModel() )
     911             :     {
     912           0 :         SfxItemSet aNewAttr( pTableObj->GetModel()->GetItemPool() );
     913             : 
     914             :         // merge drawing layer text distance items into SvxBoxItem used by the dialog
     915           0 :         SvxBoxItem aBoxItem(mergeDrawinglayerTextDistancesAndSvxBoxItem(aNewAttr));
     916             : 
     917           0 :         SvxBoxInfoItem aBoxInfoItem( static_cast< const SvxBoxInfoItem& >( aNewAttr.Get( SDRATTR_TABLE_BORDER_INNER ) ) );
     918             : 
     919           0 :         MergeAttrFromSelectedCells(aNewAttr, false);
     920           0 :         FillCommonBorderAttrFromSelectedCells( aBoxItem, aBoxInfoItem );
     921           0 :         aNewAttr.Put( aBoxItem );
     922           0 :         aNewAttr.Put( aBoxInfoItem );
     923             : 
     924           0 :         SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
     925           0 :         std::unique_ptr< SfxAbstractTabDialog > xDlg( pFact ? pFact->CreateSvxFormatCellsDialog( NULL, &aNewAttr, pTableObj->GetModel(), pTableObj) : 0 );
     926             :         // Even Cancel Button is returning positive(101) value,
     927           0 :         if (xDlg.get() && xDlg->Execute() == RET_OK)
     928             :         {
     929           0 :             SfxItemSet aNewSet(*(xDlg->GetOutputItemSet()));
     930             : 
     931             :             //Only properties that were unchanged by the dialog appear in this
     932             :             //itemset.  We had constructed these two properties from other
     933             :             //ones, so if they were not changed, then forcible set them back to
     934             :             //their originals in the new result set so we can decompose that
     935             :             //unchanged state back to their input properties
     936           0 :             if (aNewSet.GetItemState(SDRATTR_TABLE_BORDER, false) != SfxItemState::SET)
     937             :             {
     938           0 :                 aNewSet.Put(aBoxItem);
     939             :             }
     940           0 :             if (aNewSet.GetItemState(SDRATTR_TABLE_BORDER_INNER, false) != SfxItemState::SET)
     941             :             {
     942           0 :                 aNewSet.Put(aBoxInfoItem);
     943             :             }
     944             : 
     945           0 :             SvxBoxItem aNewBoxItem( static_cast< const SvxBoxItem& >( aNewSet.Get( SDRATTR_TABLE_BORDER ) ) );
     946             : 
     947           0 :             if( aNewBoxItem.GetDistance( SvxBoxItemLine::LEFT ) != aBoxItem.GetDistance( SvxBoxItemLine::LEFT ) )
     948           0 :                 aNewSet.Put(makeSdrTextLeftDistItem( aNewBoxItem.GetDistance( SvxBoxItemLine::LEFT ) ) );
     949             : 
     950           0 :             if( aNewBoxItem.GetDistance( SvxBoxItemLine::RIGHT ) != aBoxItem.GetDistance( SvxBoxItemLine::RIGHT ) )
     951           0 :                 aNewSet.Put(makeSdrTextRightDistItem( aNewBoxItem.GetDistance( SvxBoxItemLine::RIGHT ) ) );
     952             : 
     953           0 :             if( aNewBoxItem.GetDistance( SvxBoxItemLine::TOP ) != aBoxItem.GetDistance( SvxBoxItemLine::TOP ) )
     954           0 :                 aNewSet.Put(makeSdrTextUpperDistItem( aNewBoxItem.GetDistance( SvxBoxItemLine::TOP ) ) );
     955             : 
     956           0 :             if( aNewBoxItem.GetDistance( SvxBoxItemLine::BOTTOM ) != aBoxItem.GetDistance( SvxBoxItemLine::BOTTOM ) )
     957           0 :                 aNewSet.Put(makeSdrTextLowerDistItem( aNewBoxItem.GetDistance( SvxBoxItemLine::BOTTOM ) ) );
     958             : 
     959           0 :             SetAttrToSelectedCells(aNewSet, false);
     960           0 :         }
     961             :     }
     962             : }
     963             : 
     964           0 : void SvxTableController::Execute( SfxRequest& rReq )
     965             : {
     966           0 :     const sal_uInt16 nSId = rReq.GetSlot();
     967           0 :     switch( nSId )
     968             :     {
     969             :     case SID_TABLE_INSERT_ROW:
     970             :     case SID_TABLE_INSERT_COL:
     971           0 :         onInsert( nSId, rReq.GetArgs() );
     972           0 :         break;
     973             :     case SID_TABLE_DELETE_ROW:
     974             :     case SID_TABLE_DELETE_COL:
     975           0 :         onDelete( nSId );
     976           0 :         break;
     977             :     case SID_TABLE_SELECT_ALL:
     978             :     case SID_TABLE_SELECT_COL:
     979             :     case SID_TABLE_SELECT_ROW:
     980           0 :         onSelect( nSId );
     981           0 :         break;
     982             :     case SID_FORMAT_TABLE_DLG:
     983           0 :         onFormatTable( rReq );
     984           0 :         break;
     985             : 
     986             :     case SID_FRAME_LINESTYLE:
     987             :     case SID_FRAME_LINECOLOR:
     988             :     case SID_ATTR_BORDER:
     989             :         {
     990           0 :             const SfxItemSet* pArgs = rReq.GetArgs();
     991           0 :             if( pArgs )
     992           0 :                 ApplyBorderAttr( *pArgs );
     993             :         }
     994           0 :         break;
     995             : 
     996             :     case SID_ATTR_FILL_STYLE:
     997             :         {
     998           0 :             const SfxItemSet* pArgs = rReq.GetArgs();
     999           0 :             if( pArgs )
    1000           0 :                 SetAttributes( *pArgs, false );
    1001             :         }
    1002           0 :         break;
    1003             : 
    1004             :     case SID_TABLE_MERGE_CELLS:
    1005           0 :         MergeMarkedCells();
    1006           0 :         break;
    1007             : 
    1008             :     case SID_TABLE_SPLIT_CELLS:
    1009           0 :         SplitMarkedCells();
    1010           0 :         break;
    1011             : 
    1012             :     case SID_TABLE_DISTRIBUTE_COLUMNS:
    1013           0 :         DistributeColumns();
    1014           0 :         break;
    1015             : 
    1016             :     case SID_TABLE_DISTRIBUTE_ROWS:
    1017           0 :         DistributeRows();
    1018           0 :         break;
    1019             : 
    1020             :     case SID_TABLE_VERT_BOTTOM:
    1021             :     case SID_TABLE_VERT_CENTER:
    1022             :     case SID_TABLE_VERT_NONE:
    1023           0 :         SetVertical( nSId );
    1024           0 :         break;
    1025             : 
    1026             :     case SID_AUTOFORMAT:
    1027             :     case SID_TABLE_SORT_DIALOG:
    1028             :     case SID_TABLE_AUTOSUM:
    1029             :     default:
    1030           0 :         break;
    1031             : 
    1032             :     case SID_TABLE_STYLE:
    1033           0 :         SetTableStyle( rReq.GetArgs() );
    1034           0 :         break;
    1035             : 
    1036             :     case SID_TABLE_STYLE_SETTINGS:
    1037           0 :         SetTableStyleSettings( rReq.GetArgs() );
    1038           0 :         break;
    1039             :     }
    1040           0 : }
    1041             : 
    1042           0 : void SvxTableController::SetTableStyle( const SfxItemSet* pArgs )
    1043             : {
    1044           0 :     SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( mxTableObj.get() );
    1045           0 :     SdrModel* pModel = pTableObj ? pTableObj->GetModel() : 0;
    1046             : 
    1047           0 :     if( !pTableObj || !pModel || !pArgs || (SfxItemState::SET != pArgs->GetItemState(SID_TABLE_STYLE, false)) )
    1048           0 :         return;
    1049             : 
    1050           0 :     const SfxStringItem* pArg = dynamic_cast< const SfxStringItem* >( &pArgs->Get( SID_TABLE_STYLE ) );
    1051           0 :     if( pArg && mxTable.is() ) try
    1052             :     {
    1053           0 :         Reference< XStyleFamiliesSupplier > xSFS( pModel->getUnoModel(), UNO_QUERY_THROW );
    1054           0 :         Reference< XNameAccess > xFamilyNameAccess( xSFS->getStyleFamilies(), UNO_QUERY_THROW );
    1055           0 :         const OUString sFamilyName( "table" );
    1056           0 :         Reference< XNameAccess > xTableFamilyAccess( xFamilyNameAccess->getByName( sFamilyName ), UNO_QUERY_THROW );
    1057             : 
    1058           0 :         if( xTableFamilyAccess->hasByName( pArg->GetValue() ) )
    1059             :         {
    1060             :             // found table style with the same name
    1061           0 :             Reference< XIndexAccess > xNewTableStyle( xTableFamilyAccess->getByName( pArg->GetValue() ), UNO_QUERY_THROW );
    1062             : 
    1063           0 :             const bool bUndo = pModel->IsUndoEnabled();
    1064             : 
    1065           0 :             if( bUndo )
    1066             :             {
    1067           0 :                 pModel->BegUndo( ImpGetResStr(STR_TABLE_STYLE) );
    1068           0 :                 pModel->AddUndo( new TableStyleUndo( *pTableObj ) );
    1069             :             }
    1070             : 
    1071           0 :             pTableObj->setTableStyle( xNewTableStyle );
    1072             : 
    1073           0 :             const sal_Int32 nRowCount = mxTable->getRowCount();
    1074           0 :             const sal_Int32 nColCount = mxTable->getColumnCount();
    1075           0 :             for( sal_Int32 nRow = 0; nRow < nRowCount; nRow++ )
    1076             :             {
    1077           0 :                 for( sal_Int32 nCol = 0; nCol < nColCount; nCol++ ) try
    1078             :                 {
    1079           0 :                     CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
    1080           0 :                     if( xCell.is() )
    1081             :                     {
    1082           0 :                         SfxItemSet aSet( xCell->GetItemSet() );
    1083           0 :                         bool bChanges = false;
    1084           0 :                         const SfxItemSet& rStyleAttribs = xCell->GetStyleSheet()->GetItemSet();
    1085             : 
    1086           0 :                         for ( sal_uInt16 nWhich = SDRATTR_START; nWhich <= SDRATTR_TABLE_LAST; nWhich++ )
    1087             :                         {
    1088           0 :                             if( (rStyleAttribs.GetItemState( nWhich ) == SfxItemState::SET) && (aSet.GetItemState( nWhich ) == SfxItemState::SET) )
    1089             :                             {
    1090           0 :                                 aSet.ClearItem( nWhich );
    1091           0 :                                 bChanges = true;
    1092             :                             }
    1093             :                         }
    1094             : 
    1095           0 :                         if( bChanges )
    1096             :                         {
    1097           0 :                             if( bUndo )
    1098           0 :                                 xCell->AddUndo();
    1099             : 
    1100           0 :                             xCell->SetMergedItemSetAndBroadcast( aSet, true );
    1101           0 :                         }
    1102           0 :                     }
    1103             :                 }
    1104           0 :                 catch( Exception& )
    1105             :                 {
    1106             :                     OSL_FAIL( "svx::SvxTableController::SetTableStyle(), exception caught!" );
    1107             :                 }
    1108             :             }
    1109             : 
    1110           0 :             if( bUndo )
    1111           0 :                 pModel->EndUndo();
    1112           0 :         }
    1113             :     }
    1114           0 :     catch( Exception& )
    1115             :     {
    1116             :         OSL_FAIL( "svx::SvxTableController::SetTableStyle(), exception caught!" );
    1117             :     }
    1118             : }
    1119             : 
    1120           0 : void SvxTableController::SetTableStyleSettings( const SfxItemSet* pArgs )
    1121             : {
    1122           0 :     SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( mxTableObj.get() );
    1123           0 :     SdrModel* pModel = pTableObj ? pTableObj->GetModel() : 0;
    1124             : 
    1125           0 :     if( !pTableObj || !pModel )
    1126           0 :         return;
    1127             : 
    1128           0 :     TableStyleSettings aSettings( pTableObj->getTableStyleSettings() );
    1129             : 
    1130           0 :     const SfxPoolItem *pPoolItem=NULL;
    1131             : 
    1132           0 :     if( (SfxItemState::SET == pArgs->GetItemState(ID_VAL_USEFIRSTROWSTYLE, false,&pPoolItem)) )
    1133           0 :         aSettings.mbUseFirstRow = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
    1134             : 
    1135           0 :     if( (SfxItemState::SET == pArgs->GetItemState(ID_VAL_USELASTROWSTYLE, false,&pPoolItem)) )
    1136           0 :         aSettings.mbUseLastRow = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
    1137             : 
    1138           0 :     if( (SfxItemState::SET == pArgs->GetItemState(ID_VAL_USEBANDINGROWSTYLE, false,&pPoolItem)) )
    1139           0 :         aSettings.mbUseRowBanding = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
    1140             : 
    1141           0 :     if( (SfxItemState::SET == pArgs->GetItemState(ID_VAL_USEFIRSTCOLUMNSTYLE, false,&pPoolItem)) )
    1142           0 :         aSettings.mbUseFirstColumn = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
    1143             : 
    1144           0 :     if( (SfxItemState::SET == pArgs->GetItemState(ID_VAL_USELASTCOLUMNSTYLE, false,&pPoolItem)) )
    1145           0 :         aSettings.mbUseLastColumn = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
    1146             : 
    1147           0 :     if( (SfxItemState::SET == pArgs->GetItemState(ID_VAL_USEBANDINGCOLUMNSTYLE, false,&pPoolItem)) )
    1148           0 :         aSettings.mbUseColumnBanding = static_cast< const SfxBoolItem* >(pPoolItem)->GetValue();
    1149             : 
    1150           0 :     if( aSettings == pTableObj->getTableStyleSettings() )
    1151           0 :         return;
    1152             : 
    1153           0 :     const bool bUndo = pModel->IsUndoEnabled();
    1154             : 
    1155           0 :     if( bUndo )
    1156             :     {
    1157           0 :         pModel->BegUndo( ImpGetResStr(STR_TABLE_STYLE_SETTINGS) );
    1158           0 :         pModel->AddUndo( new TableStyleUndo( *pTableObj ) );
    1159             :     }
    1160             : 
    1161           0 :     pTableObj->setTableStyleSettings( aSettings );
    1162             : 
    1163           0 :     if( bUndo )
    1164           0 :         pModel->EndUndo();
    1165             : }
    1166             : 
    1167           0 : void SvxTableController::SetVertical( sal_uInt16 nSId )
    1168             : {
    1169           0 :     SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( mxTableObj.get() );
    1170           0 :     if( mxTable.is() && pTableObj )
    1171             :     {
    1172           0 :         TableModelNotifyGuard aGuard( mxTable.get() );
    1173             : 
    1174           0 :         CellPos aStart, aEnd;
    1175           0 :         getSelectedCells( aStart, aEnd );
    1176             : 
    1177           0 :         SdrTextVertAdjust eAdj = SDRTEXTVERTADJUST_TOP;
    1178             : 
    1179           0 :         switch( nSId )
    1180             :         {
    1181             :             case SID_TABLE_VERT_BOTTOM:
    1182           0 :                 eAdj = SDRTEXTVERTADJUST_BOTTOM;
    1183           0 :                 break;
    1184             :             case SID_TABLE_VERT_CENTER:
    1185           0 :                 eAdj = SDRTEXTVERTADJUST_CENTER;
    1186           0 :                 break;
    1187             :             //case SID_TABLE_VERT_NONE:
    1188             :             default:
    1189           0 :                 break;
    1190             :         }
    1191             : 
    1192           0 :         SdrTextVertAdjustItem aItem( eAdj );
    1193             : 
    1194           0 :         for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
    1195             :         {
    1196           0 :             for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
    1197             :             {
    1198           0 :                 CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
    1199           0 :                 if( xCell.is() )
    1200           0 :                     xCell->SetMergedItem(aItem);
    1201           0 :             }
    1202             :         }
    1203             : 
    1204           0 :         UpdateTableShape();
    1205             :     }
    1206           0 : }
    1207             : 
    1208           0 : void SvxTableController::MergeMarkedCells()
    1209             : {
    1210           0 :     CellPos aStart, aEnd;
    1211           0 :     getSelectedCells( aStart, aEnd );
    1212           0 :     SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( mxTableObj.get() );
    1213           0 :     if( pTableObj )
    1214             :     {
    1215           0 :         if( pTableObj->IsTextEditActive() )
    1216           0 :             mpView->SdrEndTextEdit(true);
    1217             : 
    1218           0 :         TableModelNotifyGuard aGuard( mxTable.get() );
    1219           0 :         MergeRange( aStart.mnCol, aStart.mnRow, aEnd.mnCol, aEnd.mnRow );
    1220             :     }
    1221           0 : }
    1222             : 
    1223           0 : void SvxTableController::SplitMarkedCells()
    1224             : {
    1225           0 :     if( mxTable.is() )
    1226             :     {
    1227           0 :         CellPos aStart, aEnd;
    1228           0 :         getSelectedCells( aStart, aEnd );
    1229             : 
    1230           0 :         SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
    1231           0 :         std::unique_ptr< SvxAbstractSplittTableDialog > xDlg( pFact ? pFact->CreateSvxSplittTableDialog( NULL, false, 99, 99 ) : 0 );
    1232           0 :         if( xDlg.get() && xDlg->Execute() )
    1233             :         {
    1234           0 :             const sal_Int32 nCount = xDlg->GetCount() - 1;
    1235           0 :             if( nCount < 1 )
    1236           0 :                 return;
    1237             : 
    1238           0 :             getSelectedCells( aStart, aEnd );
    1239             : 
    1240           0 :             Reference< XMergeableCellRange > xRange( mxTable->createCursorByRange( mxTable->getCellRangeByPosition( aStart.mnCol, aStart.mnRow, aEnd.mnCol, aEnd.mnRow ) ), UNO_QUERY_THROW );
    1241             : 
    1242           0 :             const sal_Int32 nRowCount = mxTable->getRowCount();
    1243           0 :             const sal_Int32 nColCount = mxTable->getColumnCount();
    1244             : 
    1245             : 
    1246           0 :             SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
    1247           0 :             if( pTableObj )
    1248             :             {
    1249           0 :                 if( pTableObj->IsTextEditActive() )
    1250           0 :                     mpView->SdrEndTextEdit(true);
    1251             : 
    1252           0 :                 TableModelNotifyGuard aGuard( mxTable.get() );
    1253             : 
    1254           0 :                 const bool bUndo = mpModel && mpModel->IsUndoEnabled();
    1255           0 :                 if( bUndo )
    1256             :                 {
    1257           0 :                     mpModel->BegUndo( ImpGetResStr(STR_TABLE_SPLIT) );
    1258           0 :                     mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
    1259             :                 }
    1260             : 
    1261           0 :                 if( xDlg->IsHorizontal() )
    1262             :                 {
    1263           0 :                     xRange->split( 0, nCount );
    1264             :                 }
    1265             :                 else
    1266             :                 {
    1267           0 :                     xRange->split( nCount, 0 );
    1268             :                 }
    1269             : 
    1270           0 :                 if( bUndo )
    1271           0 :                     mpModel->EndUndo();
    1272             :             }
    1273           0 :             aEnd.mnRow += mxTable->getRowCount() - nRowCount;
    1274           0 :             aEnd.mnCol += mxTable->getColumnCount() - nColCount;
    1275             : 
    1276           0 :             setSelectedCells( aStart, aEnd );
    1277           0 :         }
    1278             :     }
    1279             : }
    1280             : 
    1281           0 : void SvxTableController::DistributeColumns()
    1282             : {
    1283           0 :     SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
    1284           0 :     if( pTableObj )
    1285             :     {
    1286           0 :         const bool bUndo = mpModel && mpModel->IsUndoEnabled();
    1287           0 :         if( bUndo )
    1288             :         {
    1289           0 :             mpModel->BegUndo( ImpGetResStr(STR_TABLE_DISTRIBUTE_COLUMNS) );
    1290           0 :             mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
    1291             :         }
    1292             : 
    1293           0 :         CellPos aStart, aEnd;
    1294           0 :         getSelectedCells( aStart, aEnd );
    1295           0 :         pTableObj->DistributeColumns( aStart.mnCol, aEnd.mnCol );
    1296             : 
    1297           0 :         if( bUndo )
    1298           0 :             mpModel->EndUndo();
    1299             :     }
    1300           0 : }
    1301             : 
    1302           0 : void SvxTableController::DistributeRows()
    1303             : {
    1304           0 :     SdrTableObj* pTableObj = dynamic_cast< SdrTableObj* >( mxTableObj.get() );
    1305           0 :     if( pTableObj )
    1306             :     {
    1307           0 :         const bool bUndo = mpModel && mpModel->IsUndoEnabled();
    1308           0 :         if( bUndo )
    1309             :         {
    1310           0 :             mpModel->BegUndo( ImpGetResStr(STR_TABLE_DISTRIBUTE_ROWS) );
    1311           0 :             mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*pTableObj) );
    1312             :         }
    1313             : 
    1314           0 :         CellPos aStart, aEnd;
    1315           0 :         getSelectedCells( aStart, aEnd );
    1316           0 :         pTableObj->DistributeRows( aStart.mnRow, aEnd.mnRow );
    1317             : 
    1318           0 :         if( bUndo )
    1319           0 :             mpModel->EndUndo();
    1320             :     }
    1321           0 : }
    1322             : 
    1323           0 : bool SvxTableController::DeleteMarked()
    1324             : {
    1325           0 :     if( mbCellSelectionMode )
    1326             :     {
    1327           0 :         if( mxTable.is() )
    1328             :         {
    1329           0 :             CellPos aStart, aEnd;
    1330           0 :             getSelectedCells( aStart, aEnd );
    1331           0 :             for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
    1332             :             {
    1333           0 :                 for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
    1334             :                 {
    1335           0 :                     CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
    1336           0 :                     if( xCell.is() )
    1337           0 :                         xCell->SetOutlinerParaObject( 0 );
    1338           0 :                 }
    1339             :             }
    1340             : 
    1341           0 :             UpdateTableShape();
    1342           0 :             return true;
    1343             :         }
    1344             :     }
    1345             : 
    1346           0 :     return false;
    1347             : }
    1348             : 
    1349           0 : bool SvxTableController::GetStyleSheet( SfxStyleSheet*& rpStyleSheet ) const
    1350             : {
    1351           0 :     if( hasSelectedCells() )
    1352             :     {
    1353           0 :         rpStyleSheet = 0;
    1354             : 
    1355           0 :         if( mxTable.is() )
    1356             :         {
    1357           0 :             SfxStyleSheet* pRet=0;
    1358           0 :             bool b1st=true;
    1359             : 
    1360           0 :             CellPos aStart, aEnd;
    1361           0 :             const_cast<SvxTableController&>(*this).getSelectedCells( aStart, aEnd );
    1362             : 
    1363           0 :             for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
    1364             :             {
    1365           0 :                 for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
    1366             :                 {
    1367           0 :                     CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
    1368           0 :                     if( xCell.is() )
    1369             :                     {
    1370           0 :                         SfxStyleSheet* pSS=xCell->GetStyleSheet();
    1371           0 :                         if(b1st)
    1372             :                         {
    1373           0 :                             pRet=pSS;
    1374             :                         }
    1375           0 :                         else if(pRet != pSS)
    1376             :                         {
    1377           0 :                             return true;
    1378             :                         }
    1379           0 :                         b1st=false;
    1380             :                     }
    1381           0 :                 }
    1382             :             }
    1383           0 :             rpStyleSheet = pRet;
    1384           0 :             return true;
    1385             :         }
    1386             :     }
    1387           0 :     return false;
    1388             : }
    1389             : 
    1390           0 : bool SvxTableController::SetStyleSheet( SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr )
    1391             : {
    1392           0 :     if( hasSelectedCells() && (!pStyleSheet || pStyleSheet->GetFamily() == SFX_STYLE_FAMILY_FRAME) )
    1393             :     {
    1394           0 :         if( mxTable.is() )
    1395             :         {
    1396           0 :             CellPos aStart, aEnd;
    1397           0 :             getSelectedCells( aStart, aEnd );
    1398             : 
    1399           0 :             for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
    1400             :             {
    1401           0 :                 for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
    1402             :                 {
    1403           0 :                     CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
    1404           0 :                     if( xCell.is() )
    1405           0 :                         xCell->SetStyleSheet(pStyleSheet,bDontRemoveHardAttr);
    1406           0 :                 }
    1407             :             }
    1408             : 
    1409           0 :             UpdateTableShape();
    1410           0 :             return true;
    1411             :         }
    1412             :     }
    1413           0 :     return false;
    1414             : }
    1415             : 
    1416             : 
    1417             : // internals
    1418             : 
    1419             : 
    1420           0 : bool SvxTableController::checkTableObject()
    1421             : {
    1422           0 :     return mxTableObj.is();
    1423             : }
    1424             : 
    1425             : 
    1426             : 
    1427           0 : sal_uInt16 SvxTableController::getKeyboardAction( const KeyEvent& rKEvt, vcl::Window* /*pWindow*/ )
    1428             : {
    1429           0 :     const bool bMod1 = rKEvt.GetKeyCode().IsMod1(); // ctrl
    1430           0 :     const bool bMod2 = rKEvt.GetKeyCode().IsMod2(); // Alt
    1431             : 
    1432           0 :     const bool bTextEdit = mpView->IsTextEdit();
    1433             : 
    1434           0 :     sal_uInt16 nAction = ACTION_HANDLED_BY_VIEW;
    1435             : 
    1436           0 :     sdr::table::SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( mxTableObj.get() );
    1437           0 :     if( !pTableObj )
    1438           0 :         return nAction;
    1439             : 
    1440             :     // handle special keys
    1441           0 :     const sal_Int16 nCode = rKEvt.GetKeyCode().GetCode();
    1442           0 :     switch( nCode )
    1443             :     {
    1444             :     case awt::Key::ESCAPE:          // handle escape
    1445             :     {
    1446           0 :         if( bTextEdit )
    1447             :         {
    1448             :             // escape during text edit ends text edit
    1449           0 :             nAction = ACTION_STOP_TEXT_EDIT;
    1450             :         }
    1451           0 :         if( mbCellSelectionMode )
    1452             :         {
    1453             :             // escape with selected cells removes selection
    1454           0 :             nAction = ACTION_REMOVE_SELECTION;
    1455             :         }
    1456           0 :         break;
    1457             :     }
    1458             :     case awt::Key::RETURN:      // handle return
    1459             :     {
    1460           0 :         if( !bMod1 && !bMod2 && !bTextEdit )
    1461             :         {
    1462             :             // when not already editing, return starts text edit
    1463           0 :             setSelectionStart( SdrTableObj::getFirstCell() );
    1464           0 :             nAction = ACTION_EDIT_CELL;
    1465             :         }
    1466           0 :         break;
    1467             :     }
    1468             :     case awt::Key::F2:          // f2 toggles text edit
    1469             :     {
    1470           0 :         if( bMod1 || bMod2 )    // f2 with modifiers is handled by the view
    1471             :         {
    1472             :         }
    1473           0 :         else if( bTextEdit )
    1474             :         {
    1475             :             // f2 during text edit stops text edit
    1476           0 :             nAction = ACTION_STOP_TEXT_EDIT;
    1477             :         }
    1478           0 :         else if( mbCellSelectionMode )
    1479             :         {
    1480             :             // f2 with selected cells removes selection
    1481           0 :             nAction = ACTION_REMOVE_SELECTION;
    1482             :         }
    1483             :         else
    1484             :         {
    1485             :             // f2 with no selection and no text edit starts text edit
    1486           0 :             setSelectionStart( SdrTableObj::getFirstCell() );
    1487           0 :             nAction = ACTION_EDIT_CELL;
    1488             :         }
    1489           0 :         break;
    1490             :     }
    1491             :     case awt::Key::HOME:
    1492             :     case awt::Key::NUM7:
    1493             :     {
    1494           0 :         if( (bMod1 ||  bMod2) && (bTextEdit || mbCellSelectionMode) )
    1495             :         {
    1496           0 :             if( bMod1 && !bMod2 )
    1497             :             {
    1498             :                 // ctrl + home jumps to first cell
    1499           0 :                 nAction = ACTION_GOTO_FIRST_CELL;
    1500             :             }
    1501           0 :             else if( !bMod1 && bMod2 )
    1502             :             {
    1503             :                 // alt + home jumps to first column
    1504           0 :                 nAction = ACTION_GOTO_FIRST_COLUMN;
    1505             :             }
    1506             :         }
    1507           0 :         break;
    1508             :     }
    1509             :     case awt::Key::END:
    1510             :     case awt::Key::NUM1:
    1511             :     {
    1512           0 :         if( (bMod1 ||  bMod2) && (bTextEdit || mbCellSelectionMode) )
    1513             :         {
    1514           0 :             if( bMod1 && !bMod2 )
    1515             :             {
    1516             :                 // ctrl + end jumps to last cell
    1517           0 :                 nAction = ACTION_GOTO_LAST_CELL;
    1518             :             }
    1519           0 :             else if( !bMod1 && bMod2 )
    1520             :             {
    1521             :                 // alt + home jumps to last column
    1522           0 :                 nAction = ACTION_GOTO_LAST_COLUMN;
    1523             :             }
    1524             :         }
    1525           0 :         break;
    1526             :     }
    1527             : 
    1528             :     case awt::Key::TAB:
    1529             :     {
    1530           0 :         if( bTextEdit || mbCellSelectionMode )
    1531           0 :             nAction = ACTION_TAB;
    1532           0 :         break;
    1533             :     }
    1534             : 
    1535             :     case awt::Key::UP:
    1536             :     case awt::Key::NUM8:
    1537             :     case awt::Key::DOWN:
    1538             :     case awt::Key::NUM2:
    1539             :     case awt::Key::LEFT:
    1540             :     case awt::Key::NUM4:
    1541             :     case awt::Key::RIGHT:
    1542             :     case awt::Key::NUM6:
    1543             :     {
    1544           0 :         bool bTextMove = false;
    1545             : 
    1546           0 :         if( !bMod1 && bMod2 )
    1547             :         {
    1548           0 :             if( (nCode == awt::Key::UP) || (nCode == awt::Key::NUM8) )
    1549             :             {
    1550           0 :                 nAction = ACTION_GOTO_LEFT_CELL;
    1551             :             }
    1552           0 :             else if( (nCode == awt::Key::DOWN) || (nCode == awt::Key::NUM2) )
    1553             :             {
    1554           0 :                 nAction = ACTION_GOTO_RIGHT_CELL;
    1555             :             }
    1556           0 :             break;
    1557             :         }
    1558             : 
    1559           0 :         if( !bTextMove )
    1560             :         {
    1561           0 :             OutlinerView* pOLV = mpView->GetTextEditOutlinerView();
    1562           0 :             if( pOLV )
    1563             :             {
    1564           0 :                 RemoveSelection();
    1565             :                 // during text edit, check if we navigate out of the cell
    1566           0 :                 ESelection aOldSelection = pOLV->GetSelection();
    1567           0 :                 pOLV->PostKeyEvent(rKEvt);
    1568           0 :                 bTextMove = pOLV && ( aOldSelection.IsEqual(pOLV->GetSelection()) );
    1569           0 :                 if( !bTextMove )
    1570             :                 {
    1571           0 :                     nAction = ACTION_NONE;
    1572             :                 }
    1573             :             }
    1574             :         }
    1575             : 
    1576           0 :         if( mbCellSelectionMode || bTextMove )
    1577             :         {
    1578             :             // no text edit, navigate in cells if selection active
    1579           0 :             switch( nCode )
    1580             :             {
    1581             :             case awt::Key::LEFT:
    1582             :             case awt::Key::NUM4:
    1583           0 :                 nAction = ACTION_GOTO_LEFT_CELL;
    1584           0 :                 break;
    1585             :             case awt::Key::RIGHT:
    1586             :             case awt::Key::NUM6:
    1587           0 :                 nAction = ACTION_GOTO_RIGHT_CELL;
    1588           0 :                 break;
    1589             :             case awt::Key::DOWN:
    1590             :             case awt::Key::NUM2:
    1591           0 :                 nAction = ACTION_GOTO_DOWN_CELL;
    1592           0 :                 break;
    1593             :             case awt::Key::UP:
    1594             :             case awt::Key::NUM8:
    1595           0 :                 nAction = ACTION_GOTO_UP_CELL;
    1596           0 :                 break;
    1597             :             }
    1598             :         }
    1599           0 :         break;
    1600             :     }
    1601             :     case awt::Key::PAGEUP:
    1602           0 :         if( bMod2 )
    1603           0 :             nAction = ACTION_GOTO_FIRST_ROW;
    1604           0 :         break;
    1605             : 
    1606             :     case awt::Key::PAGEDOWN:
    1607           0 :         if( bMod2 )
    1608           0 :             nAction = ACTION_GOTO_LAST_ROW;
    1609           0 :         break;
    1610             :     }
    1611           0 :     return nAction;
    1612             : }
    1613             : 
    1614           0 : bool SvxTableController::executeAction( sal_uInt16 nAction, bool bSelect, vcl::Window* pWindow )
    1615             : {
    1616           0 :     sdr::table::SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( mxTableObj.get() );
    1617           0 :     if( !pTableObj )
    1618           0 :         return false;
    1619             : 
    1620           0 :     switch( nAction )
    1621             :     {
    1622             :     case ACTION_GOTO_FIRST_CELL:
    1623             :     {
    1624           0 :         gotoCell( SdrTableObj::getFirstCell(), bSelect, pWindow, nAction );
    1625           0 :         break;
    1626             :     }
    1627             : 
    1628             :     case ACTION_GOTO_LEFT_CELL:
    1629             :     {
    1630           0 :         gotoCell( pTableObj->getLeftCell( getSelectionEnd(), !bSelect ), bSelect, pWindow, nAction );
    1631           0 :         break;
    1632             :     }
    1633             : 
    1634             :     case ACTION_GOTO_RIGHT_CELL:
    1635             :     {
    1636           0 :         gotoCell( pTableObj->getRightCell( getSelectionEnd(), !bSelect ), bSelect, pWindow, nAction);
    1637           0 :         break;
    1638             :     }
    1639             : 
    1640             :     case ACTION_GOTO_LAST_CELL:
    1641             :     {
    1642           0 :         gotoCell( pTableObj->getLastCell(), bSelect, pWindow, nAction );
    1643           0 :         break;
    1644             :     }
    1645             : 
    1646             :     case ACTION_GOTO_FIRST_COLUMN:
    1647             :     {
    1648           0 :         CellPos aPos( SdrTableObj::getFirstCell().mnCol, getSelectionEnd().mnRow );
    1649           0 :         gotoCell( aPos, bSelect, pWindow, nAction );
    1650           0 :         break;
    1651             :     }
    1652             : 
    1653             :     case ACTION_GOTO_LAST_COLUMN:
    1654             :     {
    1655           0 :         CellPos aPos( pTableObj->getLastCell().mnCol, getSelectionEnd().mnRow );
    1656           0 :         gotoCell( aPos, bSelect, pWindow, nAction );
    1657           0 :         break;
    1658             :     }
    1659             : 
    1660             :     case ACTION_GOTO_FIRST_ROW:
    1661             :     {
    1662           0 :         CellPos aPos( getSelectionEnd().mnCol, SdrTableObj::getFirstCell().mnRow );
    1663           0 :         gotoCell( aPos, bSelect, pWindow, nAction );
    1664           0 :         break;
    1665             :     }
    1666             : 
    1667             :     case ACTION_GOTO_UP_CELL:
    1668             :     {
    1669           0 :         gotoCell( pTableObj->getUpCell(getSelectionEnd(), !bSelect), bSelect, pWindow, nAction );
    1670           0 :         break;
    1671             :     }
    1672             : 
    1673             :     case ACTION_GOTO_DOWN_CELL:
    1674             :     {
    1675           0 :         gotoCell( pTableObj->getDownCell(getSelectionEnd(), !bSelect), bSelect, pWindow, nAction );
    1676           0 :         break;
    1677             :     }
    1678             : 
    1679             :     case ACTION_GOTO_LAST_ROW:
    1680             :     {
    1681           0 :         CellPos aPos( getSelectionEnd().mnCol, pTableObj->getLastCell().mnRow );
    1682           0 :         gotoCell( aPos, bSelect, pWindow, nAction );
    1683           0 :         break;
    1684             :     }
    1685             : 
    1686             :     case ACTION_EDIT_CELL:
    1687           0 :         EditCell( getSelectionStart(), pWindow, 0, nAction );
    1688           0 :         break;
    1689             : 
    1690             :     case ACTION_STOP_TEXT_EDIT:
    1691           0 :         StopTextEdit();
    1692           0 :         break;
    1693             : 
    1694             :     case ACTION_REMOVE_SELECTION:
    1695           0 :         RemoveSelection();
    1696           0 :         break;
    1697             : 
    1698             :     case ACTION_START_SELECTION:
    1699           0 :         StartSelection( getSelectionStart() );
    1700           0 :         break;
    1701             : 
    1702             :     case ACTION_TAB:
    1703             :     {
    1704           0 :         if( bSelect )
    1705           0 :             gotoCell( pTableObj->getPreviousCell( getSelectionEnd(), true ), false, pWindow, nAction );
    1706             :         else
    1707             :         {
    1708           0 :             CellPos aSelectionEnd( getSelectionEnd() );
    1709           0 :             CellPos aNextCell( pTableObj->getNextCell( aSelectionEnd, true ) );
    1710           0 :             if( aSelectionEnd == aNextCell )
    1711             :             {
    1712           0 :                 onInsert( SID_TABLE_INSERT_ROW, 0 );
    1713           0 :                 aNextCell = pTableObj->getNextCell( aSelectionEnd, true );
    1714             :             }
    1715           0 :             gotoCell( aNextCell, false, pWindow, nAction );
    1716             :         }
    1717           0 :         break;
    1718             :     }
    1719             :     }
    1720             : 
    1721           0 :     return nAction != ACTION_HANDLED_BY_VIEW;
    1722             : }
    1723             : 
    1724             : 
    1725             : 
    1726           0 : void SvxTableController::gotoCell( const CellPos& rPos, bool bSelect, vcl::Window* pWindow, sal_uInt16 nAction )
    1727             : {
    1728           0 :     if( mxTableObj.is() && static_cast<SdrTableObj*>(mxTableObj.get())->IsTextEditActive() )
    1729           0 :         mpView->SdrEndTextEdit(true);
    1730             : 
    1731           0 :     if( bSelect )
    1732             :     {
    1733           0 :         maCursorLastPos = rPos;
    1734           0 :         if( mxTableObj.is() )
    1735           0 :             static_cast< SdrTableObj* >( mxTableObj.get() )->setActiveCell( rPos );
    1736             : 
    1737           0 :         if( !mbCellSelectionMode )
    1738             :         {
    1739           0 :             setSelectedCells( maCursorFirstPos, rPos );
    1740             :         }
    1741             :         else
    1742             :         {
    1743           0 :             UpdateSelection( rPos );
    1744             :         }
    1745             :     }
    1746             :     else
    1747             :     {
    1748           0 :         RemoveSelection();
    1749           0 :         EditCell( rPos, pWindow, 0, nAction );
    1750             :     }
    1751           0 : }
    1752             : 
    1753             : 
    1754             : 
    1755           0 : const CellPos& SvxTableController::getSelectionStart()
    1756             : {
    1757           0 :     checkCell( maCursorFirstPos );
    1758           0 :     return maCursorFirstPos;
    1759             : }
    1760             : 
    1761             : 
    1762             : 
    1763           0 : void SvxTableController::setSelectionStart( const CellPos& rPos )
    1764             : {
    1765           0 :     maCursorFirstPos = rPos;
    1766           0 : }
    1767             : 
    1768             : 
    1769             : 
    1770           0 : const CellPos& SvxTableController::getSelectionEnd()
    1771             : {
    1772           0 :     checkCell( maCursorLastPos );
    1773           0 :     return maCursorLastPos;
    1774             : }
    1775             : 
    1776             : 
    1777             : 
    1778           0 : void SvxTableController::MergeRange( sal_Int32 nFirstCol, sal_Int32 nFirstRow, sal_Int32 nLastCol, sal_Int32 nLastRow )
    1779             : {
    1780           0 :     if( mxTable.is() ) try
    1781             :     {
    1782           0 :         Reference< XMergeableCellRange > xRange( mxTable->createCursorByRange( mxTable->getCellRangeByPosition( nFirstCol, nFirstRow,nLastCol, nLastRow ) ), UNO_QUERY_THROW );
    1783           0 :         if( xRange->isMergeable() )
    1784             :         {
    1785           0 :             const bool bUndo = mpModel && mpModel->IsUndoEnabled();
    1786           0 :             if( bUndo )
    1787             :             {
    1788           0 :                 mpModel->BegUndo( ImpGetResStr(STR_TABLE_MERGE) );
    1789           0 :                 mpModel->AddUndo( mpModel->GetSdrUndoFactory().CreateUndoGeoObject(*mxTableObj.get()) );
    1790             :             }
    1791             : 
    1792           0 :             xRange->merge();
    1793             : 
    1794           0 :             if( bUndo )
    1795           0 :                 mpModel->EndUndo();
    1796           0 :         }
    1797             :     }
    1798           0 :     catch( Exception& )
    1799             :     {
    1800             :         DBG_ASSERT( false, "sdr::table::SvxTableController::MergeRange(), exception caught!" );
    1801             :     }
    1802           0 : }
    1803             : 
    1804             : 
    1805             : 
    1806             : 
    1807             : 
    1808           0 : void SvxTableController::checkCell( CellPos& rPos )
    1809             : {
    1810           0 :     if( mxTable.is() ) try
    1811             :     {
    1812           0 :         if( rPos.mnCol >= mxTable->getColumnCount() )
    1813           0 :             rPos.mnCol = mxTable->getColumnCount()-1;
    1814             : 
    1815           0 :         if( rPos.mnRow >= mxTable->getRowCount() )
    1816           0 :             rPos.mnRow = mxTable->getRowCount()-1;
    1817             :     }
    1818           0 :     catch( Exception& )
    1819             :     {
    1820             :         OSL_FAIL("sdr::table::SvxTableController::checkCell(), exception caught!" );
    1821             :     }
    1822           0 : }
    1823             : 
    1824             : 
    1825             : 
    1826           0 : void SvxTableController::findMergeOrigin( CellPos& rPos )
    1827             : {
    1828           0 :     if( mxTable.is() ) try
    1829             :     {
    1830           0 :         Reference< XMergeableCell > xCell( mxTable->getCellByPosition( rPos.mnCol, rPos.mnRow ), UNO_QUERY_THROW );
    1831           0 :         if( xCell.is() && xCell->isMerged() )
    1832             :         {
    1833           0 :             ::findMergeOrigin( mxTable, rPos.mnCol, rPos.mnRow, rPos.mnCol, rPos.mnRow );
    1834           0 :         }
    1835             :     }
    1836           0 :     catch( Exception& )
    1837             :     {
    1838             :         OSL_FAIL("sdr::table::SvxTableController::findMergeOrigin(), exception caught!" );
    1839             :     }
    1840           0 : }
    1841             : 
    1842             : 
    1843             : 
    1844           0 : void SvxTableController::EditCell( const CellPos& rPos, vcl::Window* pWindow, const awt::MouseEvent* pMouseEvent /*= 0*/, sal_uInt16 nAction /*= ACTION_NONE */ )
    1845             : {
    1846           0 :     SdrPageView* pPV = mpView->GetSdrPageView();
    1847             : 
    1848           0 :     sdr::table::SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( mxTableObj.get() );
    1849           0 :     if( pTableObj && pTableObj->GetPage() == pPV->GetPage() )
    1850             :     {
    1851           0 :         bool bEmptyOutliner = false;
    1852             : 
    1853           0 :         if(!pTableObj->GetOutlinerParaObject() && mpView->GetTextEditOutliner())
    1854             :         {
    1855           0 :             ::Outliner* pOutl = mpView->GetTextEditOutliner();
    1856           0 :             sal_Int32 nParaAnz = pOutl->GetParagraphCount();
    1857           0 :             Paragraph* p1stPara = pOutl->GetParagraph( 0 );
    1858             : 
    1859           0 :             if(nParaAnz==1 && p1stPara)
    1860             :             {
    1861             :                 // Bei nur einem Pararaph
    1862           0 :                 if (pOutl->GetText(p1stPara).isEmpty())
    1863             :                 {
    1864           0 :                     bEmptyOutliner = true;
    1865             :                 }
    1866             :             }
    1867             :         }
    1868             : 
    1869           0 :         CellPos aPos( rPos );
    1870           0 :         findMergeOrigin( aPos );
    1871             : 
    1872           0 :         if( pTableObj != mpView->GetTextEditObject() || bEmptyOutliner || !pTableObj->IsTextEditActive( aPos ) )
    1873             :         {
    1874           0 :             if( pTableObj->IsTextEditActive() )
    1875           0 :                 mpView->SdrEndTextEdit(true);
    1876             : 
    1877           0 :             pTableObj->setActiveCell( aPos );
    1878             : 
    1879             :             // create new outliner, owner will be the SdrObjEditView
    1880           0 :             SdrOutliner* pOutl = mpModel ? SdrMakeOutliner(OUTLINERMODE_OUTLINEOBJECT, *mpModel) : NULL;
    1881           0 :             if (pOutl && pTableObj->IsVerticalWriting())
    1882           0 :                 pOutl->SetVertical( true );
    1883             : 
    1884           0 :             if (mpView->SdrBeginTextEdit(pTableObj, pPV, pWindow, true, pOutl))
    1885             :             {
    1886           0 :                 maCursorLastPos = maCursorFirstPos = rPos;
    1887             : 
    1888           0 :                 OutlinerView* pOLV = mpView->GetTextEditOutlinerView();
    1889             : 
    1890           0 :                 bool bNoSel = true;
    1891             : 
    1892           0 :                 if( pMouseEvent )
    1893             :                 {
    1894           0 :                     ::MouseEvent aMEvt( *pMouseEvent );
    1895             : 
    1896           0 :                     SdrViewEvent aVEvt;
    1897           0 :                     SdrHitKind eHit = mpView->PickAnything(aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
    1898             : 
    1899           0 :                     if (eHit == SDRHIT_TEXTEDIT)
    1900             :                     {
    1901             :                         // Text getroffen
    1902           0 :                         pOLV->MouseButtonDown(aMEvt);
    1903           0 :                         pOLV->MouseMove(aMEvt);
    1904           0 :                         pOLV->MouseButtonUp(aMEvt);
    1905             : //                      pOLV->MouseButtonDown(aMEvt);
    1906           0 :                         bNoSel = false;
    1907             :                     }
    1908             :                     else
    1909             :                     {
    1910           0 :                         nAction = ACTION_GOTO_LEFT_CELL;
    1911           0 :                     }
    1912             :                 }
    1913             : 
    1914           0 :                 if( bNoSel )
    1915             :                 {
    1916             :                     // Move cursor to end of text
    1917           0 :                     ESelection aNewSelection;
    1918             : 
    1919           0 :                     const WritingMode eMode = pTableObj->GetWritingMode();
    1920           0 :                     if( ((nAction == ACTION_GOTO_LEFT_CELL) || (nAction == ACTION_GOTO_RIGHT_CELL)) && (eMode != WritingMode_TB_RL) )
    1921             :                     {
    1922           0 :                         const bool bLast = ((nAction == ACTION_GOTO_LEFT_CELL) && (eMode == WritingMode_LR_TB)) ||
    1923           0 :                                              ((nAction == ACTION_GOTO_RIGHT_CELL) && (eMode == WritingMode_RL_TB));
    1924             : 
    1925           0 :                         if( bLast )
    1926           0 :                             aNewSelection = ESelection(EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND, EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND);
    1927             :                     }
    1928           0 :                     pOLV->SetSelection(aNewSelection);
    1929             :                 }
    1930             :             }
    1931             :         }
    1932             :     }
    1933           0 : }
    1934             : 
    1935             : 
    1936             : 
    1937           0 : bool SvxTableController::StopTextEdit()
    1938             : {
    1939           0 :     if(mpView->IsTextEdit())
    1940             :     {
    1941           0 :         mpView->SdrEndTextEdit();
    1942           0 :         mpView->SetCurrentObj(OBJ_TABLE);
    1943           0 :         mpView->SetEditMode(SDREDITMODE_EDIT);
    1944           0 :         return true;
    1945             :     }
    1946             :     else
    1947             :     {
    1948           0 :         return false;
    1949             :     }
    1950             : }
    1951             : 
    1952             : 
    1953             : 
    1954           0 : void SvxTableController::getSelectedCells( CellPos& rFirst, CellPos& rLast )
    1955             : {
    1956           0 :     if( mbCellSelectionMode )
    1957             :     {
    1958           0 :         checkCell( maCursorFirstPos );
    1959           0 :         checkCell( maCursorLastPos );
    1960             : 
    1961           0 :         rFirst.mnCol = std::min( maCursorFirstPos.mnCol, maCursorLastPos.mnCol );
    1962           0 :         rFirst.mnRow = std::min( maCursorFirstPos.mnRow, maCursorLastPos.mnRow );
    1963           0 :         rLast.mnCol = std::max( maCursorFirstPos.mnCol, maCursorLastPos.mnCol );
    1964           0 :         rLast.mnRow = std::max( maCursorFirstPos.mnRow, maCursorLastPos.mnRow );
    1965             : 
    1966           0 :         bool bExt = false;
    1967           0 :         if( mxTable.is() ) do
    1968             :         {
    1969           0 :             bExt = false;
    1970           0 :             for( sal_Int32 nRow = rFirst.mnRow; nRow <= rLast.mnRow && !bExt; nRow++ )
    1971             :             {
    1972           0 :                 for( sal_Int32 nCol = rFirst.mnCol; nCol <= rLast.mnCol && !bExt; nCol++ )
    1973             :                 {
    1974           0 :                     Reference< XMergeableCell > xCell( mxTable->getCellByPosition( nCol, nRow ), UNO_QUERY );
    1975           0 :                     if( !xCell.is() )
    1976           0 :                         continue;
    1977             : 
    1978           0 :                     if( xCell->isMerged() )
    1979             :                     {
    1980           0 :                         CellPos aPos( nCol, nRow );
    1981           0 :                         findMergeOrigin( aPos );
    1982           0 :                         if( (aPos.mnCol < rFirst.mnCol) || (aPos.mnRow < rFirst.mnRow) )
    1983             :                         {
    1984           0 :                             rFirst.mnCol = std::min( rFirst.mnCol, aPos.mnCol );
    1985           0 :                             rFirst.mnRow = std::min( rFirst.mnRow, aPos.mnRow );
    1986           0 :                             bExt = true;
    1987             :                         }
    1988             :                     }
    1989             :                     else
    1990             :                     {
    1991           0 :                         if( ((nCol + xCell->getColumnSpan() - 1) > rLast.mnCol) || (nRow + xCell->getRowSpan() - 1 ) > rLast.mnRow )
    1992             :                         {
    1993           0 :                             rLast.mnCol = std::max( rLast.mnCol, nCol + xCell->getColumnSpan() - 1 );
    1994           0 :                             rLast.mnRow = std::max( rLast.mnRow, nRow + xCell->getRowSpan() - 1 );
    1995           0 :                             bExt = true;
    1996             :                         }
    1997             :                     }
    1998           0 :                 }
    1999             :             }
    2000             :         }
    2001             :         while(bExt);
    2002             :     }
    2003           0 :     else if( mpView && mpView->IsTextEdit() )
    2004             :     {
    2005           0 :         rFirst = getSelectionStart();
    2006           0 :         findMergeOrigin( rFirst );
    2007           0 :         rLast = rFirst;
    2008             : 
    2009           0 :         if( mxTable.is() )
    2010             :         {
    2011           0 :             Reference< XMergeableCell > xCell( mxTable->getCellByPosition( rLast.mnCol, rLast.mnRow ), UNO_QUERY );
    2012           0 :             if( xCell.is() )
    2013             :             {
    2014           0 :                 rLast.mnCol += xCell->getColumnSpan() - 1;
    2015           0 :                 rLast.mnRow += xCell->getRowSpan() - 1;
    2016           0 :             }
    2017             :         }
    2018             :     }
    2019             :     else
    2020             :     {
    2021           0 :         rFirst.mnCol = 0;
    2022           0 :         rFirst.mnRow = 0;
    2023           0 :         if( mxTable.is() )
    2024             :         {
    2025           0 :             rLast.mnRow = mxTable->getRowCount()-1;
    2026           0 :             rLast.mnCol = mxTable->getColumnCount()-1;
    2027             :         }
    2028             :         else
    2029             :         {
    2030           0 :             rLast.mnRow = 0;
    2031           0 :             rLast.mnCol = 0;
    2032             :         }
    2033             :     }
    2034           0 : }
    2035             : 
    2036             : 
    2037             : 
    2038           0 : void SvxTableController::StartSelection( const CellPos& rPos )
    2039             : {
    2040           0 :     StopTextEdit();
    2041           0 :     mbCellSelectionMode = true;
    2042           0 :     maCursorLastPos = maCursorFirstPos = rPos;
    2043           0 :     mpView->MarkListHasChanged();
    2044           0 : }
    2045             : 
    2046             : 
    2047             : 
    2048           0 : void SvxTableController::setSelectedCells( const CellPos& rStart, const CellPos& rEnd )
    2049             : {
    2050           0 :     StopTextEdit();
    2051           0 :     mbCellSelectionMode = true;
    2052           0 :     maCursorFirstPos = rStart;
    2053           0 :     UpdateSelection( rEnd );
    2054           0 : }
    2055             : 
    2056             : 
    2057             : 
    2058           0 : void SvxTableController::UpdateSelection( const CellPos& rPos )
    2059             : {
    2060           0 :     maCursorLastPos = rPos;
    2061           0 :     mpView->MarkListHasChanged();
    2062           0 : }
    2063             : 
    2064             : 
    2065             : 
    2066           0 : void SvxTableController::clearSelection()
    2067             : {
    2068           0 :     RemoveSelection();
    2069           0 : }
    2070             : 
    2071             : 
    2072             : 
    2073           0 : void SvxTableController::selectAll()
    2074             : {
    2075           0 :     if( mxTable.is() )
    2076             :     {
    2077           0 :         CellPos aPos1, aPos2( mxTable->getColumnCount()-1, mxTable->getRowCount()-1 );
    2078           0 :         if( (aPos2.mnCol >= 0) && (aPos2.mnRow >= 0) )
    2079             :         {
    2080           0 :             setSelectedCells( aPos1, aPos2 );
    2081             :         }
    2082             :     }
    2083           0 : }
    2084             : 
    2085             : 
    2086             : 
    2087           0 : void SvxTableController::RemoveSelection()
    2088             : {
    2089           0 :     if( mbCellSelectionMode )
    2090             :     {
    2091           0 :         mbCellSelectionMode = false;
    2092           0 :         mpView->MarkListHasChanged();
    2093             :     }
    2094           0 : }
    2095             : 
    2096             : 
    2097             : 
    2098           0 : void SvxTableController::onTableModified()
    2099             : {
    2100           0 :     if( mnUpdateEvent == 0 )
    2101           0 :         mnUpdateEvent = Application::PostUserEvent( LINK( this, SvxTableController, UpdateHdl ) );
    2102           0 : }
    2103             : 
    2104             : 
    2105           0 : void SvxTableController::updateSelectionOverlay()
    2106             : {
    2107           0 :     destroySelectionOverlay();
    2108           0 :     if( mbCellSelectionMode )
    2109             :     {
    2110           0 :         sdr::table::SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( mxTableObj.get() );
    2111           0 :         if( pTableObj )
    2112             :         {
    2113           0 :             sdr::overlay::OverlayObjectCell::RangeVector aRanges;
    2114             : 
    2115           0 :             Rectangle aStartRect, aEndRect;
    2116           0 :             CellPos aStart,aEnd;
    2117           0 :             getSelectedCells( aStart, aEnd );
    2118           0 :             pTableObj->getCellBounds( aStart, aStartRect );
    2119             : 
    2120           0 :             basegfx::B2DRange a2DRange( basegfx::B2DPoint(aStartRect.Left(), aStartRect.Top()) );
    2121           0 :             a2DRange.expand( basegfx::B2DPoint(aStartRect.Right(), aStartRect.Bottom()) );
    2122             : 
    2123           0 :             findMergeOrigin( aEnd );
    2124           0 :             pTableObj->getCellBounds( aEnd, aEndRect );
    2125           0 :             a2DRange.expand( basegfx::B2DPoint(aEndRect.Left(), aEndRect.Top()) );
    2126           0 :             a2DRange.expand( basegfx::B2DPoint(aEndRect.Right(), aEndRect.Bottom()) );
    2127           0 :             aRanges.push_back( a2DRange );
    2128             : 
    2129           0 :             ::Color aHighlight( COL_BLUE );
    2130           0 :             OutputDevice* pOutDev = mpView->GetFirstOutputDevice();
    2131           0 :             if( pOutDev )
    2132           0 :                 aHighlight = pOutDev->GetSettings().GetStyleSettings().GetHighlightColor();
    2133             : 
    2134           0 :             const sal_uInt32 nCount = mpView->PaintWindowCount();
    2135           0 :             for( sal_uInt32 nIndex = 0; nIndex < nCount; nIndex++ )
    2136             :             {
    2137           0 :                 SdrPaintWindow* pPaintWindow = mpView->GetPaintWindow(nIndex);
    2138           0 :                 if( pPaintWindow )
    2139             :                 {
    2140           0 :                     rtl::Reference < sdr::overlay::OverlayManager > xOverlayManager = pPaintWindow->GetOverlayManager();
    2141           0 :                     if( xOverlayManager.is() )
    2142             :                     {
    2143             :                         // sdr::overlay::CellOverlayType eType = sdr::overlay::CELL_OVERLAY_INVERT;
    2144           0 :                         sdr::overlay::CellOverlayType eType = sdr::overlay::CELL_OVERLAY_TRANSPARENT;
    2145             : 
    2146           0 :                         sdr::overlay::OverlayObjectCell* pOverlay = new sdr::overlay::OverlayObjectCell( eType, aHighlight, aRanges );
    2147             : 
    2148           0 :                         xOverlayManager->add(*pOverlay);
    2149           0 :                         mpSelectionOverlay = new sdr::overlay::OverlayObjectList;
    2150           0 :                         mpSelectionOverlay->append(*pOverlay);
    2151           0 :                     }
    2152             :                 }
    2153             :             }
    2154             : 
    2155             :             // If tiled rendering, emit callbacks for sdr table selection.
    2156           0 :             if (pOutDev && pTableObj->GetModel()->isTiledRendering())
    2157             :             {
    2158             :                 // Left edge of aStartRect.
    2159           0 :                 Rectangle aSelectionStart(aStartRect.Left(), aStartRect.Top(), aStartRect.Left(), aStartRect.Bottom());
    2160             :                 // Right edge of aEndRect.
    2161           0 :                 Rectangle aSelectionEnd(aEndRect.Right(), aEndRect.Top(), aEndRect.Right(), aEndRect.Bottom());
    2162           0 :                 Rectangle aSelection(a2DRange.getMinX(), a2DRange.getMinY(), a2DRange.getMaxX(), a2DRange.getMaxY());
    2163             : 
    2164           0 :                 if (pOutDev->GetMapMode().GetMapUnit() == MAP_100TH_MM)
    2165             :                 {
    2166           0 :                     aSelectionStart = OutputDevice::LogicToLogic(aSelectionStart, MAP_100TH_MM, MAP_TWIP);
    2167           0 :                     aSelectionEnd = OutputDevice::LogicToLogic(aSelectionEnd, MAP_100TH_MM, MAP_TWIP);
    2168           0 :                     aSelection = OutputDevice::LogicToLogic(aSelection, MAP_100TH_MM, MAP_TWIP);
    2169             :                 }
    2170             : 
    2171           0 :                 pTableObj->GetModel()->libreOfficeKitCallback(LOK_CALLBACK_TEXT_SELECTION_START, aSelectionStart.toString().getStr());
    2172           0 :                 pTableObj->GetModel()->libreOfficeKitCallback(LOK_CALLBACK_TEXT_SELECTION_END, aSelectionEnd.toString().getStr());
    2173           0 :                 pTableObj->GetModel()->libreOfficeKitCallback(LOK_CALLBACK_TEXT_SELECTION, aSelection.toString().getStr());
    2174           0 :             }
    2175             :         }
    2176             :     }
    2177           0 : }
    2178             : 
    2179             : 
    2180             : 
    2181           0 : void SvxTableController::destroySelectionOverlay()
    2182             : {
    2183           0 :     if( mpSelectionOverlay )
    2184             :     {
    2185           0 :         delete mpSelectionOverlay;
    2186           0 :         mpSelectionOverlay = 0;
    2187             : 
    2188           0 :         if (mxTableObj->GetModel()->isTiledRendering())
    2189             :         {
    2190             :             // Clear the LOK text selection so far provided by this table.
    2191           0 :             mxTableObj->GetModel()->libreOfficeKitCallback(LOK_CALLBACK_TEXT_SELECTION_START, "EMPTY");
    2192           0 :             mxTableObj->GetModel()->libreOfficeKitCallback(LOK_CALLBACK_TEXT_SELECTION_END, "EMPTY");
    2193           0 :             mxTableObj->GetModel()->libreOfficeKitCallback(LOK_CALLBACK_TEXT_SELECTION, "EMPTY");
    2194             :         }
    2195             :     }
    2196           0 : }
    2197             : 
    2198             : 
    2199             : 
    2200           0 : void SvxTableController::MergeAttrFromSelectedCells(SfxItemSet& rAttr, bool bOnlyHardAttr) const
    2201             : {
    2202           0 :     if( mxTable.is() )
    2203             :     {
    2204           0 :         CellPos aStart, aEnd;
    2205           0 :         const_cast<SvxTableController&>(*this).getSelectedCells( aStart, aEnd );
    2206             : 
    2207           0 :         for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
    2208             :         {
    2209           0 :             for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
    2210             :             {
    2211           0 :                 CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
    2212           0 :                 if( xCell.is() && !xCell->isMerged() )
    2213             :                 {
    2214           0 :                     const SfxItemSet& rSet = xCell->GetItemSet();
    2215           0 :                     SfxWhichIter aIter(rSet);
    2216           0 :                     sal_uInt16 nWhich(aIter.FirstWhich());
    2217           0 :                     while(nWhich)
    2218             :                     {
    2219           0 :                         if(!bOnlyHardAttr)
    2220             :                         {
    2221           0 :                             if(SfxItemState::DONTCARE == rSet.GetItemState(nWhich, false))
    2222           0 :                                 rAttr.InvalidateItem(nWhich);
    2223             :                             else
    2224           0 :                                 rAttr.MergeValue(rSet.Get(nWhich), true);
    2225             :                         }
    2226           0 :                         else if(SfxItemState::SET == rSet.GetItemState(nWhich, false))
    2227             :                         {
    2228           0 :                             const SfxPoolItem& rItem = rSet.Get(nWhich);
    2229           0 :                             rAttr.MergeValue(rItem, true);
    2230             :                         }
    2231             : 
    2232           0 :                         nWhich = aIter.NextWhich();
    2233           0 :                     }
    2234             :                 }
    2235           0 :             }
    2236             :         }
    2237             :     }
    2238           0 : }
    2239             : 
    2240             : 
    2241             : 
    2242             : const sal_uInt16 CELL_BEFORE = 0x0001;
    2243             : const sal_uInt16 CELL_LEFT   = 0x0002;
    2244             : const sal_uInt16 CELL_RIGHT  = 0x0004;
    2245             : const sal_uInt16 CELL_AFTER  = 0x0008;
    2246             : 
    2247             : const sal_uInt16 CELL_UPPER  = 0x0010;
    2248             : const sal_uInt16 CELL_TOP    = 0x0020;
    2249             : const sal_uInt16 CELL_BOTTOM = 0x0040;
    2250             : const sal_uInt16 CELL_LOWER  = 0x0080;
    2251             : 
    2252             : 
    2253             : 
    2254           0 : static void ImplSetLinePreserveColor( SvxBoxItem& rNewFrame, const SvxBorderLine* pNew, SvxBoxItemLine nLine )
    2255             : {
    2256           0 :     if( pNew )
    2257             :     {
    2258           0 :         const SvxBorderLine* pOld = rNewFrame.GetLine(nLine);
    2259           0 :         if( pOld )
    2260             :         {
    2261           0 :             SvxBorderLine aNewLine( *pNew );
    2262           0 :             aNewLine.SetColor( pOld->GetColor() );
    2263           0 :             rNewFrame.SetLine( &aNewLine, nLine );
    2264           0 :             return;
    2265             :         }
    2266             :     }
    2267           0 :     rNewFrame.SetLine( pNew, nLine );
    2268             : }
    2269             : 
    2270             : 
    2271             : 
    2272           0 : static void ImplApplyBoxItem( sal_uInt16 nCellFlags, const SvxBoxItem* pBoxItem, const SvxBoxInfoItem* pBoxInfoItem, SvxBoxItem& rNewFrame )
    2273             : {
    2274           0 :     if( (nCellFlags & (CELL_BEFORE|CELL_AFTER|CELL_UPPER|CELL_LOWER)) != 0 )
    2275             :     {
    2276             :         // current cell is outside the selection
    2277             : 
    2278           0 :         if( (nCellFlags & ( CELL_BEFORE|CELL_AFTER)) == 0 ) // check if its not nw or ne corner
    2279             :         {
    2280           0 :             if( nCellFlags & CELL_UPPER )
    2281             :             {
    2282           0 :                 if( pBoxInfoItem->IsValid(SvxBoxInfoItemValidFlags::TOP) )
    2283           0 :                     rNewFrame.SetLine(0, SvxBoxItemLine::BOTTOM );
    2284             :             }
    2285           0 :             else if( nCellFlags & CELL_LOWER )
    2286             :             {
    2287           0 :                 if( pBoxInfoItem->IsValid(SvxBoxInfoItemValidFlags::BOTTOM) )
    2288           0 :                     rNewFrame.SetLine( 0, SvxBoxItemLine::TOP );
    2289             :             }
    2290             :         }
    2291           0 :         else if( (nCellFlags & ( CELL_UPPER|CELL_LOWER)) == 0 ) // check if its not sw or se corner
    2292             :         {
    2293           0 :             if( nCellFlags & CELL_BEFORE )
    2294             :             {
    2295           0 :                 if( pBoxInfoItem->IsValid(SvxBoxInfoItemValidFlags::LEFT) )
    2296           0 :                     rNewFrame.SetLine( 0, SvxBoxItemLine::RIGHT );
    2297             :             }
    2298           0 :             else if( nCellFlags & CELL_AFTER )
    2299             :             {
    2300           0 :                 if( pBoxInfoItem->IsValid(SvxBoxInfoItemValidFlags::RIGHT) )
    2301           0 :                     rNewFrame.SetLine( 0, SvxBoxItemLine::LEFT );
    2302             :             }
    2303             :         }
    2304             :     }
    2305             :     else
    2306             :     {
    2307             :         // current cell is inside the selection
    2308             : 
    2309           0 :         if( (nCellFlags & CELL_LEFT) ? pBoxInfoItem->IsValid(SvxBoxInfoItemValidFlags::LEFT) : pBoxInfoItem->IsValid(SvxBoxInfoItemValidFlags::VERT) )
    2310           0 :             rNewFrame.SetLine( (nCellFlags & CELL_LEFT) ? pBoxItem->GetLeft() : pBoxInfoItem->GetVert(), SvxBoxItemLine::LEFT );
    2311             : 
    2312           0 :         if( (nCellFlags & CELL_RIGHT) ? pBoxInfoItem->IsValid(SvxBoxInfoItemValidFlags::RIGHT) : pBoxInfoItem->IsValid(SvxBoxInfoItemValidFlags::VERT) )
    2313           0 :             rNewFrame.SetLine( (nCellFlags & CELL_RIGHT) ? pBoxItem->GetRight() : pBoxInfoItem->GetVert(), SvxBoxItemLine::RIGHT );
    2314             : 
    2315           0 :         if( (nCellFlags & CELL_TOP) ? pBoxInfoItem->IsValid(SvxBoxInfoItemValidFlags::TOP) : pBoxInfoItem->IsValid(SvxBoxInfoItemValidFlags::HORI) )
    2316           0 :             rNewFrame.SetLine( (nCellFlags & CELL_TOP) ? pBoxItem->GetTop() : pBoxInfoItem->GetHori(), SvxBoxItemLine::TOP );
    2317             : 
    2318           0 :         if( (nCellFlags & CELL_BOTTOM) ? pBoxInfoItem->IsValid(SvxBoxInfoItemValidFlags::BOTTOM) : pBoxInfoItem->IsValid(SvxBoxInfoItemValidFlags::HORI) )
    2319           0 :             rNewFrame.SetLine( (nCellFlags & CELL_BOTTOM) ? pBoxItem->GetBottom() : pBoxInfoItem->GetHori(), SvxBoxItemLine::BOTTOM );
    2320             : 
    2321             :         // apply distance to borders
    2322           0 :         if( pBoxInfoItem->IsValid( SvxBoxInfoItemValidFlags::DISTANCE ) )
    2323           0 :             for( SvxBoxItemLine nLine : o3tl::enumrange<SvxBoxItemLine>() )
    2324           0 :                 rNewFrame.SetDistance( pBoxItem->GetDistance( nLine ), nLine );
    2325             :     }
    2326           0 : }
    2327             : 
    2328             : 
    2329             : 
    2330           0 : static void ImplSetLineColor( SvxBoxItem& rNewFrame, SvxBoxItemLine nLine, const Color& rColor )
    2331             : {
    2332           0 :     const SvxBorderLine* pSourceLine = rNewFrame.GetLine( nLine );
    2333           0 :     if( pSourceLine )
    2334             :     {
    2335           0 :         SvxBorderLine aLine( *pSourceLine );
    2336           0 :         aLine.SetColor( rColor );
    2337           0 :         rNewFrame.SetLine( &aLine, nLine );
    2338             :     }
    2339           0 : }
    2340             : 
    2341             : 
    2342             : 
    2343           0 : static void ImplApplyLineColorItem( sal_uInt16 nCellFlags, const SvxColorItem* pLineColorItem, SvxBoxItem& rNewFrame )
    2344             : {
    2345           0 :     const Color aColor( pLineColorItem->GetValue() );
    2346             : 
    2347           0 :     if( (nCellFlags & (CELL_LOWER|CELL_BEFORE|CELL_AFTER)) == 0 )
    2348           0 :         ImplSetLineColor( rNewFrame, SvxBoxItemLine::BOTTOM, aColor );
    2349             : 
    2350           0 :     if( (nCellFlags & (CELL_UPPER|CELL_BEFORE|CELL_AFTER)) == 0 )
    2351           0 :         ImplSetLineColor( rNewFrame, SvxBoxItemLine::TOP, aColor );
    2352             : 
    2353           0 :     if( (nCellFlags & (CELL_UPPER|CELL_LOWER|CELL_AFTER)) == 0 )
    2354           0 :         ImplSetLineColor( rNewFrame, SvxBoxItemLine::RIGHT, aColor );
    2355             : 
    2356           0 :     if( (nCellFlags & (CELL_UPPER|CELL_LOWER|CELL_BEFORE)) == 0 )
    2357           0 :         ImplSetLineColor( rNewFrame, SvxBoxItemLine::LEFT, aColor );
    2358           0 : }
    2359             : 
    2360             : 
    2361             : 
    2362           0 : static void ImplApplyBorderLineItem( sal_uInt16 nCellFlags, const SvxBorderLine* pBorderLineItem, SvxBoxItem& rNewFrame )
    2363             : {
    2364           0 :     if( (nCellFlags & ( CELL_BEFORE|CELL_AFTER|CELL_UPPER|CELL_LOWER)) != 0 )
    2365             :     {
    2366           0 :         if( (nCellFlags & ( CELL_BEFORE|CELL_AFTER)) == 0 ) // check if its not nw or ne corner
    2367             :         {
    2368           0 :             if( nCellFlags & CELL_UPPER )
    2369             :             {
    2370           0 :                 if( rNewFrame.GetBottom() )
    2371           0 :                     ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, SvxBoxItemLine::BOTTOM );
    2372             :             }
    2373           0 :             else if( nCellFlags & CELL_LOWER )
    2374             :             {
    2375           0 :                 if( rNewFrame.GetTop() )
    2376           0 :                     ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, SvxBoxItemLine::TOP );
    2377             :             }
    2378             :         }
    2379           0 :         else if( (nCellFlags & ( CELL_UPPER|CELL_LOWER)) == 0 ) // check if its not sw or se corner
    2380             :         {
    2381           0 :             if( nCellFlags & CELL_BEFORE )
    2382             :             {
    2383           0 :                 if( rNewFrame.GetRight() )
    2384           0 :                     ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, SvxBoxItemLine::RIGHT );
    2385             :             }
    2386           0 :             else if( nCellFlags & CELL_AFTER )
    2387             :             {
    2388           0 :                 if( rNewFrame.GetLeft() )
    2389           0 :                     ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, SvxBoxItemLine::LEFT );
    2390             :             }
    2391             :         }
    2392             :     }
    2393             :     else
    2394             :     {
    2395           0 :         if( rNewFrame.GetBottom() )
    2396           0 :             ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, SvxBoxItemLine::BOTTOM );
    2397           0 :         if( rNewFrame.GetTop() )
    2398           0 :             ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, SvxBoxItemLine::TOP );
    2399           0 :         if( rNewFrame.GetRight() )
    2400           0 :             ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, SvxBoxItemLine::RIGHT );
    2401           0 :         if( rNewFrame.GetLeft() )
    2402           0 :             ImplSetLinePreserveColor( rNewFrame, pBorderLineItem, SvxBoxItemLine::LEFT );
    2403             :     }
    2404           0 : }
    2405             : 
    2406             : 
    2407             : 
    2408           0 : void SvxTableController::ApplyBorderAttr( const SfxItemSet& rAttr )
    2409             : {
    2410           0 :     if( mxTable.is() )
    2411             :     {
    2412           0 :         const sal_Int32 nRowCount = mxTable->getRowCount();
    2413           0 :         const sal_Int32 nColCount = mxTable->getColumnCount();
    2414           0 :         if( nRowCount && nColCount )
    2415             :         {
    2416           0 :             const SvxBoxItem* pBoxItem = 0;
    2417           0 :             if(SfxItemState::SET == rAttr.GetItemState(SDRATTR_TABLE_BORDER, false) )
    2418           0 :                 pBoxItem = dynamic_cast< const SvxBoxItem* >( &rAttr.Get( SDRATTR_TABLE_BORDER ) );
    2419             : 
    2420           0 :             const SvxBoxInfoItem* pBoxInfoItem = 0;
    2421           0 :             if(SfxItemState::SET == rAttr.GetItemState(SDRATTR_TABLE_BORDER_INNER, false) )
    2422           0 :                 pBoxInfoItem = dynamic_cast< const SvxBoxInfoItem* >( &rAttr.Get( SDRATTR_TABLE_BORDER_INNER ) );
    2423             : 
    2424           0 :             const SvxColorItem* pLineColorItem = 0;
    2425           0 :             if(SfxItemState::SET == rAttr.GetItemState(SID_FRAME_LINECOLOR, false) )
    2426           0 :                 pLineColorItem = dynamic_cast< const SvxColorItem* >( &rAttr.Get( SID_FRAME_LINECOLOR ) );
    2427             : 
    2428           0 :             const SvxBorderLine* pBorderLineItem = 0;
    2429           0 :             if(SfxItemState::SET == rAttr.GetItemState(SID_FRAME_LINESTYLE, false) )
    2430           0 :                 pBorderLineItem = static_cast<const SvxLineItem&>(rAttr.Get( SID_FRAME_LINESTYLE )).GetLine();
    2431             : 
    2432           0 :             if( pBoxInfoItem && !pBoxItem )
    2433             :             {
    2434           0 :                 const static SvxBoxItem gaEmptyBoxItem( SDRATTR_TABLE_BORDER );
    2435           0 :                 pBoxItem = &gaEmptyBoxItem;
    2436             :             }
    2437           0 :             else if( pBoxItem && !pBoxInfoItem )
    2438             :             {
    2439           0 :                 const static SvxBoxInfoItem gaEmptyBoxInfoItem( SDRATTR_TABLE_BORDER_INNER );
    2440           0 :                 pBoxInfoItem = &gaEmptyBoxInfoItem;
    2441             :             }
    2442             : 
    2443           0 :             CellPos aStart, aEnd;
    2444           0 :             getSelectedCells( aStart, aEnd );
    2445             : 
    2446           0 :             const sal_Int32 nLastRow = std::min( aEnd.mnRow + 2, nRowCount );
    2447           0 :             const sal_Int32 nLastCol = std::min( aEnd.mnCol + 2, nColCount );
    2448             : 
    2449           0 :             for( sal_Int32 nRow = std::max( aStart.mnRow - 1, (sal_Int32)0 ); nRow < nLastRow; nRow++ )
    2450             :             {
    2451           0 :                 sal_uInt16 nRowFlags = 0;
    2452           0 :                 nRowFlags |= (nRow == aStart.mnRow) ? CELL_TOP : 0;
    2453           0 :                 nRowFlags |= (nRow == aEnd.mnRow)   ? CELL_BOTTOM : 0;
    2454           0 :                 nRowFlags |= (nRow < aStart.mnRow)  ? CELL_UPPER : 0;
    2455           0 :                 nRowFlags |= (nRow > aEnd.mnRow)    ? CELL_LOWER : 0;
    2456             : 
    2457           0 :                 for( sal_Int32 nCol = std::max( aStart.mnCol - 1, (sal_Int32)0 ); nCol < nLastCol; nCol++ )
    2458             :                 {
    2459           0 :                     CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
    2460           0 :                     if( !xCell.is() )
    2461           0 :                         continue;
    2462             : 
    2463           0 :                     const SfxItemSet& rSet = xCell->GetItemSet();
    2464           0 :                     const SvxBoxItem* pOldOuter = static_cast<const SvxBoxItem*>(&rSet.Get( SDRATTR_TABLE_BORDER ));
    2465             : 
    2466           0 :                     SvxBoxItem aNewFrame( *pOldOuter );
    2467             : 
    2468           0 :                     sal_uInt16 nCellFlags = nRowFlags;
    2469           0 :                     nCellFlags |= (nCol == aStart.mnCol) ? CELL_LEFT : 0;
    2470           0 :                     nCellFlags |= (nCol == aEnd.mnCol)   ? CELL_RIGHT : 0;
    2471           0 :                     nCellFlags |= (nCol < aStart.mnCol)  ? CELL_BEFORE : 0;
    2472           0 :                     nCellFlags |= (nCol > aEnd.mnCol)    ? CELL_AFTER : 0;
    2473             : 
    2474           0 :                     if( pBoxItem && pBoxInfoItem )
    2475           0 :                         ImplApplyBoxItem( nCellFlags, pBoxItem, pBoxInfoItem, aNewFrame );
    2476             : 
    2477           0 :                     if( pLineColorItem )
    2478           0 :                         ImplApplyLineColorItem( nCellFlags, pLineColorItem, aNewFrame );
    2479             : 
    2480           0 :                     if( pBorderLineItem )
    2481           0 :                         ImplApplyBorderLineItem( nCellFlags, pBorderLineItem, aNewFrame );
    2482             : 
    2483           0 :                     if (aNewFrame != *pOldOuter)
    2484             :                     {
    2485           0 :                         SfxItemSet aAttr(*rSet.GetPool(), rSet.GetRanges());
    2486           0 :                         aAttr.Put(aNewFrame);
    2487           0 :                         xCell->SetMergedItemSetAndBroadcast( aAttr, false );
    2488             :                     }
    2489           0 :                 }
    2490             :             }
    2491             :         }
    2492             :     }
    2493           0 : }
    2494             : 
    2495             : 
    2496             : 
    2497           0 : void SvxTableController::UpdateTableShape()
    2498             : {
    2499           0 :     SdrObject* pTableObj = mxTableObj.get();
    2500           0 :     if( pTableObj )
    2501             :     {
    2502           0 :         pTableObj->ActionChanged();
    2503           0 :         pTableObj->BroadcastObjectChange();
    2504             :     }
    2505           0 :     updateSelectionOverlay();
    2506           0 : }
    2507             : 
    2508             : 
    2509             : 
    2510             : 
    2511           0 : void SvxTableController::SetAttrToSelectedCells(const SfxItemSet& rAttr, bool bReplaceAll)
    2512             : {
    2513           0 :     if( mxTable.is() )
    2514             :     {
    2515           0 :         const bool bUndo = mpModel && mpModel->IsUndoEnabled();
    2516             : 
    2517           0 :         if( bUndo )
    2518           0 :             mpModel->BegUndo( ImpGetResStr(STR_TABLE_NUMFORMAT) );
    2519             : 
    2520           0 :         CellPos aStart, aEnd;
    2521           0 :         getSelectedCells( aStart, aEnd );
    2522             : 
    2523           0 :         SfxItemSet aAttr(*rAttr.GetPool(), rAttr.GetRanges());
    2524           0 :         aAttr.Put(rAttr, true);
    2525             : 
    2526           0 :         const bool bFrame = (rAttr.GetItemState( SDRATTR_TABLE_BORDER ) == SfxItemState::SET) || (rAttr.GetItemState( SDRATTR_TABLE_BORDER_INNER ) == SfxItemState::SET);
    2527             : 
    2528           0 :         if( bFrame )
    2529             :         {
    2530           0 :             aAttr.ClearItem( SDRATTR_TABLE_BORDER );
    2531           0 :             aAttr.ClearItem( SDRATTR_TABLE_BORDER_INNER );
    2532             :         }
    2533             : 
    2534           0 :         for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
    2535             :         {
    2536           0 :             for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
    2537             :             {
    2538           0 :                 CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
    2539           0 :                 if( xCell.is() )
    2540             :                 {
    2541           0 :                     if( bUndo )
    2542           0 :                         xCell->AddUndo();
    2543           0 :                     xCell->SetMergedItemSetAndBroadcast(aAttr, bReplaceAll);
    2544             :                 }
    2545           0 :             }
    2546             :         }
    2547             : 
    2548           0 :         if( bFrame )
    2549             :         {
    2550           0 :             ApplyBorderAttr( rAttr );
    2551             :         }
    2552             : 
    2553           0 :         UpdateTableShape();
    2554             : 
    2555           0 :         if( bUndo )
    2556           0 :             mpModel->EndUndo();
    2557             : 
    2558             :     }
    2559           0 : }
    2560             : 
    2561             : 
    2562             : 
    2563           0 : bool SvxTableController::GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr) const
    2564             : {
    2565           0 :     if( mxTableObj.is() && hasSelectedCells() )
    2566             :     {
    2567           0 :         MergeAttrFromSelectedCells( rTargetSet, bOnlyHardAttr );
    2568             : 
    2569           0 :         if( mpView->IsTextEdit() )
    2570             :         {
    2571           0 :             if( mxTableObj->GetOutlinerParaObject() )
    2572           0 :                 rTargetSet.Put( SvxScriptTypeItem( mxTableObj->GetOutlinerParaObject()->GetTextObject().GetScriptType() ) );
    2573             : 
    2574           0 :             OutlinerView* pTextEditOutlinerView = mpView->GetTextEditOutlinerView();
    2575           0 :             if(pTextEditOutlinerView)
    2576             :             {
    2577             :                 // FALSE= InvalidItems nicht al Default, sondern als "Loecher" betrachten
    2578           0 :                 rTargetSet.Put(pTextEditOutlinerView->GetAttribs(), false);
    2579           0 :                 rTargetSet.Put( SvxScriptTypeItem( pTextEditOutlinerView->GetSelectedScriptType() ) );
    2580             :             }
    2581             :         }
    2582             : 
    2583           0 :         return true;
    2584             :     }
    2585             :     else
    2586             :     {
    2587           0 :         return false;
    2588             :     }
    2589             : }
    2590             : 
    2591             : 
    2592             : 
    2593           0 : bool SvxTableController::SetAttributes(const SfxItemSet& rSet, bool bReplaceAll)
    2594             : {
    2595           0 :     if( mbCellSelectionMode || mpView->IsTextEdit()  )
    2596             :     {
    2597           0 :         SetAttrToSelectedCells( rSet, bReplaceAll );
    2598           0 :         return true;
    2599             :     }
    2600           0 :     return false;
    2601             : }
    2602             : 
    2603             : 
    2604             : 
    2605           0 : bool SvxTableController::GetMarkedObjModel( SdrPage* pNewPage )
    2606             : {
    2607           0 :     if( mxTableObj.is() && mbCellSelectionMode && pNewPage ) try
    2608             :     {
    2609           0 :         sdr::table::SdrTableObj& rTableObj = *static_cast< sdr::table::SdrTableObj* >( mxTableObj.get() );
    2610             : 
    2611           0 :         CellPos aStart, aEnd;
    2612           0 :         getSelectedCells( aStart, aEnd );
    2613             : 
    2614           0 :         SdrTableObj* pNewTableObj = rTableObj.CloneRange( aStart, aEnd );
    2615             : 
    2616           0 :         pNewTableObj->SetPage( pNewPage );
    2617           0 :         pNewTableObj->SetModel( pNewPage->GetModel() );
    2618             : 
    2619           0 :         SdrInsertReason aReason(SDRREASON_VIEWCALL);
    2620           0 :         pNewPage->InsertObject(pNewTableObj, SAL_MAX_SIZE, &aReason);
    2621             : 
    2622           0 :         return true;
    2623             :     }
    2624           0 :     catch( Exception& )
    2625             :     {
    2626             :         OSL_FAIL( "svx::SvxTableController::GetMarkedObjModel(), exception caught!" );
    2627             :     }
    2628           0 :     return false;
    2629             : }
    2630             : 
    2631             : 
    2632             : 
    2633           0 : bool SvxTableController::PasteObjModel( const SdrModel& rModel )
    2634             : {
    2635           0 :     if( mxTableObj.is() && mpView && (rModel.GetPageCount() >= 1) )
    2636             :     {
    2637           0 :         const SdrPage* pPastePage = rModel.GetPage(0);
    2638           0 :         if( pPastePage && pPastePage->GetObjCount() == 1 )
    2639             :         {
    2640           0 :             SdrTableObj* pPasteTableObj = dynamic_cast< SdrTableObj* >( pPastePage->GetObj(0) );
    2641           0 :             if( pPasteTableObj )
    2642             :             {
    2643           0 :                 return PasteObject( pPasteTableObj );
    2644             :             }
    2645             :         }
    2646             :     }
    2647             : 
    2648           0 :     return false;
    2649             : }
    2650             : 
    2651             : 
    2652             : 
    2653           0 : bool SvxTableController::PasteObject( SdrTableObj* pPasteTableObj )
    2654             : {
    2655           0 :     if( !pPasteTableObj )
    2656           0 :         return false;
    2657             : 
    2658           0 :     Reference< XTable > xPasteTable( pPasteTableObj->getTable() );
    2659           0 :     if( !xPasteTable.is() )
    2660           0 :         return false;
    2661             : 
    2662           0 :     if( !mxTable.is() )
    2663           0 :         return false;
    2664             : 
    2665           0 :     sal_Int32 nPasteColumns = xPasteTable->getColumnCount();
    2666           0 :     sal_Int32 nPasteRows = xPasteTable->getRowCount();
    2667             : 
    2668           0 :     CellPos aStart, aEnd;
    2669           0 :     getSelectedCells( aStart, aEnd );
    2670             : 
    2671           0 :     if( mpView->IsTextEdit() )
    2672           0 :         mpView->SdrEndTextEdit(true);
    2673             : 
    2674           0 :     sal_Int32 nColumns = mxTable->getColumnCount();
    2675           0 :     sal_Int32 nRows = mxTable->getRowCount();
    2676             : 
    2677           0 :     const sal_Int32 nMissing = nPasteRows - ( nRows - aStart.mnRow );
    2678           0 :     if( nMissing > 0 )
    2679             :     {
    2680           0 :         Reference< XTableRows > xRows( mxTable->getRows() );
    2681           0 :         xRows->insertByIndex( nRows, nMissing );
    2682           0 :         nRows = mxTable->getRowCount();
    2683             :     }
    2684             : 
    2685           0 :     nPasteRows = std::min( nPasteRows, nRows - aStart.mnRow );
    2686           0 :     nPasteColumns = std::min( nPasteColumns, nColumns - aStart.mnCol );
    2687             : 
    2688             :     // copy cell contents
    2689           0 :     for( sal_Int32 nRow = 0; nRow < nPasteRows; ++nRow )
    2690             :     {
    2691           0 :         for( sal_Int32 nCol = 0; nCol < nPasteColumns; ++nCol )
    2692             :         {
    2693           0 :             CellRef xTargetCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( aStart.mnCol + nCol, aStart.mnRow + nRow ).get() ) );
    2694           0 :             if( xTargetCell.is() && !xTargetCell->isMerged() )
    2695             :             {
    2696           0 :                 xTargetCell->AddUndo();
    2697           0 :                 xTargetCell->cloneFrom( dynamic_cast< Cell* >( xPasteTable->getCellByPosition( nCol, nRow ).get() ) );
    2698           0 :                 nCol += xTargetCell->getColumnSpan() - 1;
    2699             :             }
    2700           0 :         }
    2701             :     }
    2702             : 
    2703           0 :     UpdateTableShape();
    2704             : 
    2705           0 :     return true;
    2706             : }
    2707             : 
    2708           0 : bool SvxTableController::TakeFormatPaintBrush( std::shared_ptr< SfxItemSet >& /*rFormatSet*/  )
    2709             : {
    2710             :     // SdrView::TakeFormatPaintBrush() is enough
    2711           0 :     return false;
    2712             : }
    2713             : 
    2714           0 : bool SvxTableController::ApplyFormatPaintBrush( SfxItemSet& rFormatSet, bool bNoCharacterFormats, bool bNoParagraphFormats )
    2715             : {
    2716           0 :     if( mbCellSelectionMode )
    2717             :     {
    2718           0 :         SdrTextObj* pTableObj = dynamic_cast<SdrTextObj*>( mxTableObj.get() );
    2719           0 :         if( !pTableObj )
    2720           0 :             return false;
    2721             : 
    2722           0 :         const bool bUndo = mpModel && mpModel->IsUndoEnabled();
    2723             : 
    2724           0 :         if( bUndo )
    2725           0 :             mpModel->BegUndo( ImpGetResStr(STR_TABLE_NUMFORMAT) );
    2726             : 
    2727           0 :         CellPos aStart, aEnd;
    2728           0 :         getSelectedCells( aStart, aEnd );
    2729             : 
    2730           0 :         SfxItemSet aAttr(*rFormatSet.GetPool(), rFormatSet.GetRanges());
    2731           0 :         aAttr.Put(rFormatSet, true);
    2732             : 
    2733           0 :         const bool bFrame = (rFormatSet.GetItemState( SDRATTR_TABLE_BORDER ) == SfxItemState::SET) || (rFormatSet.GetItemState( SDRATTR_TABLE_BORDER_INNER ) == SfxItemState::SET);
    2734             : 
    2735           0 :         if( bFrame )
    2736             :         {
    2737           0 :             aAttr.ClearItem( SDRATTR_TABLE_BORDER );
    2738           0 :             aAttr.ClearItem( SDRATTR_TABLE_BORDER_INNER );
    2739             :         }
    2740             : 
    2741           0 :         const sal_uInt16* pRanges = rFormatSet.GetRanges();
    2742           0 :         bool bTextOnly = true;
    2743             : 
    2744           0 :         while( *pRanges )
    2745             :         {
    2746           0 :             if( (*pRanges != EE_PARA_START) && (*pRanges != EE_CHAR_START) )
    2747             :             {
    2748           0 :                 bTextOnly = false;
    2749           0 :                 break;
    2750             :             }
    2751           0 :             pRanges += 2;
    2752             :         }
    2753             : 
    2754           0 :         const bool bReplaceAll = false;
    2755           0 :         for( sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++ )
    2756             :         {
    2757           0 :             for( sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++ )
    2758             :             {
    2759           0 :                 CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
    2760           0 :                 if( xCell.is() )
    2761             :                 {
    2762           0 :                     if( bUndo )
    2763           0 :                         xCell->AddUndo();
    2764           0 :                     if( !bTextOnly )
    2765           0 :                         xCell->SetMergedItemSetAndBroadcast(aAttr, bReplaceAll);
    2766             : 
    2767           0 :                     SdrText* pText = static_cast< SdrText* >( xCell.get() );
    2768           0 :                     SdrObjEditView::ApplyFormatPaintBrushToText( rFormatSet, *pTableObj, pText, bNoCharacterFormats, bNoParagraphFormats );
    2769             :                 }
    2770           0 :             }
    2771             :         }
    2772             : 
    2773           0 :         if( bFrame )
    2774             :         {
    2775           0 :             ApplyBorderAttr( rFormatSet );
    2776             :         }
    2777             : 
    2778           0 :         UpdateTableShape();
    2779             : 
    2780           0 :         if( bUndo )
    2781           0 :             mpModel->EndUndo();
    2782             : 
    2783           0 :         return true;
    2784             : 
    2785             :     }
    2786           0 :     return false;
    2787             : }
    2788             : 
    2789             : 
    2790             : 
    2791             : 
    2792           0 : IMPL_LINK_NOARG(SvxTableController, UpdateHdl)
    2793             : {
    2794           0 :     mnUpdateEvent = 0;
    2795             : 
    2796           0 :     if( mbCellSelectionMode )
    2797             :     {
    2798           0 :         CellPos aStart( maCursorFirstPos );
    2799           0 :         CellPos aEnd( maCursorLastPos );
    2800           0 :         checkCell(aStart);
    2801           0 :         checkCell(aEnd);
    2802           0 :         if( aStart != maCursorFirstPos  || aEnd != maCursorLastPos )
    2803             :         {
    2804           0 :             setSelectedCells( aStart, aEnd );
    2805             :         }
    2806             :     }
    2807           0 :     updateSelectionOverlay();
    2808             : 
    2809           0 :     return 0;
    2810             : }
    2811             : 
    2812             : namespace
    2813             : {
    2814             : 
    2815             : struct LinesState
    2816             : {
    2817           0 :     LinesState(SvxBoxItem& rBoxItem_, SvxBoxInfoItem& rBoxInfoItem_)
    2818             :         : rBoxItem(rBoxItem_)
    2819             :         , rBoxInfoItem(rBoxInfoItem_)
    2820           0 :         , bDistanceIndeterminate(false)
    2821             :     {
    2822           0 :         aBorderSet.fill(false);
    2823           0 :         aInnerLineSet.fill(false);
    2824           0 :         aBorderIndeterminate.fill(false);
    2825           0 :         aInnerLineIndeterminate.fill(false);
    2826           0 :         aDistanceSet.fill(false);
    2827           0 :         aDistance.fill(0);
    2828           0 :     }
    2829             : 
    2830             :     SvxBoxItem& rBoxItem;
    2831             :     SvxBoxInfoItem& rBoxInfoItem;
    2832             :     o3tl::enumarray<SvxBoxItemLine, bool>       aBorderSet;
    2833             :     o3tl::enumarray<SvxBoxInfoItemLine, bool>   aInnerLineSet;
    2834             :     o3tl::enumarray<SvxBoxItemLine, bool>       aBorderIndeterminate;
    2835             :     o3tl::enumarray<SvxBoxInfoItemLine, bool>   aInnerLineIndeterminate;
    2836             :     o3tl::enumarray<SvxBoxItemLine, bool>       aDistanceSet;
    2837             :     o3tl::enumarray<SvxBoxItemLine, sal_uInt16> aDistance;
    2838             :     bool bDistanceIndeterminate;
    2839             : };
    2840             : 
    2841             : class BoxItemWrapper
    2842             : {
    2843             : public:
    2844             :     BoxItemWrapper(SvxBoxItem& rBoxItem, SvxBoxInfoItem& rBoxInfoItem, SvxBoxItemLine nBorderLine, SvxBoxInfoItemLine nInnerLine, bool bBorder);
    2845             : 
    2846             :     const SvxBorderLine* getLine() const;
    2847             :     void setLine(const SvxBorderLine* pLine);
    2848             : 
    2849             : private:
    2850             :     SvxBoxItem& m_rBoxItem;
    2851             :     SvxBoxInfoItem& m_rBoxInfoItem;
    2852             :     const SvxBoxItemLine m_nBorderLine;
    2853             :     const SvxBoxInfoItemLine m_nInnerLine;
    2854             :     const bool m_bBorder;
    2855             : };
    2856             : 
    2857           0 : BoxItemWrapper::BoxItemWrapper(
    2858             :         SvxBoxItem& rBoxItem, SvxBoxInfoItem& rBoxInfoItem,
    2859             :         const SvxBoxItemLine nBorderLine, const SvxBoxInfoItemLine nInnerLine, const bool bBorder)
    2860             :     : m_rBoxItem(rBoxItem)
    2861             :     , m_rBoxInfoItem(rBoxInfoItem)
    2862             :     , m_nBorderLine(nBorderLine)
    2863             :     , m_nInnerLine(nInnerLine)
    2864           0 :     , m_bBorder(bBorder)
    2865             : {
    2866           0 : }
    2867             : 
    2868           0 : const SvxBorderLine* BoxItemWrapper::getLine() const
    2869             : {
    2870           0 :     if (m_bBorder)
    2871           0 :         return m_rBoxItem.GetLine(m_nBorderLine);
    2872             :     else
    2873           0 :         return (m_nInnerLine == SvxBoxInfoItemLine::HORI) ? m_rBoxInfoItem.GetHori() : m_rBoxInfoItem.GetVert();
    2874             : }
    2875             : 
    2876           0 : void BoxItemWrapper::setLine(const SvxBorderLine* pLine)
    2877             : {
    2878           0 :     if (m_bBorder)
    2879           0 :         m_rBoxItem.SetLine(pLine, m_nBorderLine);
    2880             :     else
    2881           0 :         m_rBoxInfoItem.SetLine(pLine, m_nInnerLine);
    2882           0 : }
    2883             : 
    2884           0 : void lcl_MergeBorderLine(
    2885             :         LinesState& rLinesState, const SvxBorderLine* const pLine, const SvxBoxItemLine nLine,
    2886             :         SvxBoxInfoItemValidFlags nValidFlag, const bool bBorder = true)
    2887             : {
    2888           0 :     const SvxBoxInfoItemLine nInnerLine(bBorder ? SvxBoxInfoItemLine::HORI : ((nValidFlag & SvxBoxInfoItemValidFlags::HORI) ? SvxBoxInfoItemLine::HORI : SvxBoxInfoItemLine::VERT));
    2889           0 :     BoxItemWrapper aBoxItem(rLinesState.rBoxItem, rLinesState.rBoxInfoItem, nLine, nInnerLine, bBorder);
    2890           0 :     bool& rbSet(bBorder ? rLinesState.aBorderSet[nLine] : rLinesState.aInnerLineSet[nInnerLine]);
    2891             : 
    2892           0 :     if (rbSet)
    2893             :     {
    2894           0 :         bool& rbIndeterminate(bBorder ? rLinesState.aBorderIndeterminate[nLine] : rLinesState.aInnerLineIndeterminate[nInnerLine]);
    2895           0 :         if (!rbIndeterminate)
    2896             :         {
    2897           0 :             const SvxBorderLine* const pMergedLine(aBoxItem.getLine());
    2898           0 :             if ((pLine && !pMergedLine) || (!pLine && pMergedLine) || (pLine && (*pLine != *pMergedLine)))
    2899             :             {
    2900           0 :                 aBoxItem.setLine(0);
    2901           0 :                 rbIndeterminate = true;
    2902             :             }
    2903             :         }
    2904             :     }
    2905             :     else
    2906             :     {
    2907           0 :         aBoxItem.setLine(pLine);
    2908           0 :         rbSet = true;
    2909             :     }
    2910           0 : }
    2911             : 
    2912           0 : void lcl_MergeBorderOrInnerLine(
    2913             :         LinesState& rLinesState, const SvxBorderLine* const pLine, const SvxBoxItemLine nLine,
    2914             :         SvxBoxInfoItemValidFlags nValidFlag, const bool bBorder)
    2915             : {
    2916           0 :     if (bBorder)
    2917           0 :         lcl_MergeBorderLine(rLinesState, pLine, nLine, nValidFlag);
    2918             :     else
    2919             :     {
    2920           0 :         const bool bVertical = (nLine == SvxBoxItemLine::LEFT) || (nLine == SvxBoxItemLine::RIGHT);
    2921           0 :         lcl_MergeBorderLine(rLinesState, pLine, nLine, bVertical ? SvxBoxInfoItemValidFlags::VERT : SvxBoxInfoItemValidFlags::HORI, false);
    2922             :     }
    2923           0 : }
    2924             : 
    2925           0 : void lcl_MergeDistance(
    2926             :         LinesState& rLinesState, const SvxBoxItemLine nIndex, const sal_uInt16 nDistance)
    2927             : {
    2928           0 :     if (rLinesState.aDistanceSet[nIndex])
    2929             :     {
    2930           0 :         if (!rLinesState.bDistanceIndeterminate)
    2931           0 :             rLinesState.bDistanceIndeterminate = nDistance != rLinesState.aDistance[nIndex];
    2932             :     }
    2933             :     else
    2934             :     {
    2935           0 :         rLinesState.aDistance[nIndex] = nDistance;
    2936           0 :         rLinesState.aDistanceSet[nIndex] = true;
    2937             :     }
    2938           0 : }
    2939             : 
    2940           0 : void lcl_MergeCommonBorderAttr(LinesState& rLinesState, const SvxBoxItem& rCellBoxItem, const sal_Int32 nCellFlags)
    2941             : {
    2942           0 :     if( (nCellFlags & (CELL_BEFORE|CELL_AFTER|CELL_UPPER|CELL_LOWER)) != 0 )
    2943             :     {
    2944             :         // current cell is outside the selection
    2945             : 
    2946           0 :         if( (nCellFlags & ( CELL_BEFORE|CELL_AFTER)) == 0 ) // check if its not nw or ne corner
    2947             :         {
    2948           0 :             if( nCellFlags & CELL_UPPER )
    2949           0 :                 lcl_MergeBorderLine(rLinesState, rCellBoxItem.GetBottom(), SvxBoxItemLine::TOP, SvxBoxInfoItemValidFlags::TOP);
    2950           0 :             else if( nCellFlags & CELL_LOWER )
    2951           0 :                 lcl_MergeBorderLine(rLinesState, rCellBoxItem.GetTop(), SvxBoxItemLine::BOTTOM, SvxBoxInfoItemValidFlags::BOTTOM);
    2952             :         }
    2953           0 :         else if( (nCellFlags & ( CELL_UPPER|CELL_LOWER)) == 0 ) // check if its not sw or se corner
    2954             :         {
    2955           0 :             if( nCellFlags & CELL_BEFORE )
    2956           0 :                 lcl_MergeBorderLine(rLinesState, rCellBoxItem.GetRight(), SvxBoxItemLine::LEFT, SvxBoxInfoItemValidFlags::LEFT);
    2957           0 :             else if( nCellFlags & CELL_AFTER )
    2958           0 :                 lcl_MergeBorderLine(rLinesState, rCellBoxItem.GetLeft(), SvxBoxItemLine::RIGHT, SvxBoxInfoItemValidFlags::RIGHT);
    2959             :         }
    2960             : 
    2961             :         // NOTE: inner distances for cells outside the selected range
    2962             :         // are not relevant -> we ignore them.
    2963             :     }
    2964             :     else
    2965             :     {
    2966             :         // current cell is inside the selection
    2967             : 
    2968           0 :         lcl_MergeBorderOrInnerLine(rLinesState, rCellBoxItem.GetTop(), SvxBoxItemLine::TOP, SvxBoxInfoItemValidFlags::TOP, (nCellFlags & CELL_TOP) != 0);
    2969           0 :         lcl_MergeBorderOrInnerLine(rLinesState, rCellBoxItem.GetBottom(), SvxBoxItemLine::BOTTOM, SvxBoxInfoItemValidFlags::BOTTOM, (nCellFlags & CELL_BOTTOM) != 0);
    2970           0 :         lcl_MergeBorderOrInnerLine(rLinesState, rCellBoxItem.GetLeft(), SvxBoxItemLine::LEFT, SvxBoxInfoItemValidFlags::LEFT, (nCellFlags & CELL_LEFT) != 0);
    2971           0 :         lcl_MergeBorderOrInnerLine(rLinesState, rCellBoxItem.GetRight(), SvxBoxItemLine::RIGHT, SvxBoxInfoItemValidFlags::RIGHT, (nCellFlags & CELL_RIGHT) != 0);
    2972             : 
    2973           0 :         lcl_MergeDistance(rLinesState, SvxBoxItemLine::TOP, rCellBoxItem.GetDistance(SvxBoxItemLine::TOP));
    2974           0 :         lcl_MergeDistance(rLinesState, SvxBoxItemLine::BOTTOM, rCellBoxItem.GetDistance(SvxBoxItemLine::BOTTOM));
    2975           0 :         lcl_MergeDistance(rLinesState, SvxBoxItemLine::LEFT, rCellBoxItem.GetDistance(SvxBoxItemLine::LEFT));
    2976           0 :         lcl_MergeDistance(rLinesState, SvxBoxItemLine::RIGHT, rCellBoxItem.GetDistance(SvxBoxItemLine::RIGHT));
    2977             :     }
    2978           0 : }
    2979             : 
    2980             : }
    2981             : 
    2982           0 : void SvxTableController::FillCommonBorderAttrFromSelectedCells( SvxBoxItem& rBoxItem, SvxBoxInfoItem& rBoxInfoItem ) const
    2983             : {
    2984           0 :     if( mxTable.is() )
    2985             :     {
    2986           0 :         const sal_Int32 nRowCount = mxTable->getRowCount();
    2987           0 :         const sal_Int32 nColCount = mxTable->getColumnCount();
    2988           0 :         if( nRowCount && nColCount )
    2989             :         {
    2990           0 :             CellPos aStart, aEnd;
    2991           0 :             const_cast< SvxTableController* >( this )->getSelectedCells( aStart, aEnd );
    2992             : 
    2993             :             // We are adding one more row/column around the block of selected cells.
    2994             :             // We will be checking the adjoining border of these too.
    2995           0 :             const sal_Int32 nLastRow = std::min( aEnd.mnRow + 2, nRowCount );
    2996           0 :             const sal_Int32 nLastCol = std::min( aEnd.mnCol + 2, nColCount );
    2997             : 
    2998           0 :             rBoxInfoItem.SetValid( SvxBoxInfoItemValidFlags::ALL, false );
    2999           0 :             LinesState aLinesState( rBoxItem, rBoxInfoItem );
    3000             : 
    3001             :             /* Here we go through all the selected cells (enhanced by
    3002             :              * the adjoining row/column on each side) and determine the
    3003             :              * lines for presentation. The algorithm is simple:
    3004             :              * 1. if a border or inner line is set (or unset) in all
    3005             :              *    cells to the same value, it will be used.
    3006             :              * 2. if a border or inner line is set only in some cells,
    3007             :              *    it will be set to indeterminate state (SetValid() on
    3008             :              *    rBoxInfoItem).
    3009             :              */
    3010           0 :             for( sal_Int32 nRow = std::max( aStart.mnRow - 1, (sal_Int32)0 ); nRow < nLastRow; nRow++ )
    3011             :             {
    3012           0 :                 sal_uInt16 nRowFlags = 0;
    3013           0 :                 nRowFlags |= (nRow == aStart.mnRow) ? CELL_TOP : 0;
    3014           0 :                 nRowFlags |= (nRow == aEnd.mnRow)   ? CELL_BOTTOM : 0;
    3015           0 :                 nRowFlags |= (nRow < aStart.mnRow)  ? CELL_UPPER : 0;
    3016           0 :                 nRowFlags |= (nRow > aEnd.mnRow)    ? CELL_LOWER : 0;
    3017             : 
    3018           0 :                 for( sal_Int32 nCol = std::max( aStart.mnCol - 1, (sal_Int32)0 ); nCol < nLastCol; nCol++ )
    3019             :                 {
    3020           0 :                     CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
    3021           0 :                     if( !xCell.is() )
    3022           0 :                         continue;
    3023             : 
    3024           0 :                     sal_uInt16 nCellFlags = nRowFlags;
    3025           0 :                     nCellFlags |= (nCol == aStart.mnCol) ? CELL_LEFT : 0;
    3026           0 :                     nCellFlags |= (nCol == aEnd.mnCol)   ? CELL_RIGHT : 0;
    3027           0 :                     nCellFlags |= (nCol < aStart.mnCol)  ? CELL_BEFORE : 0;
    3028           0 :                     nCellFlags |= (nCol > aEnd.mnCol)    ? CELL_AFTER : 0;
    3029             : 
    3030           0 :                     const SfxItemSet& rSet = xCell->GetItemSet();
    3031           0 :                     SvxBoxItem aCellBoxItem(mergeDrawinglayerTextDistancesAndSvxBoxItem(rSet));
    3032           0 :                     lcl_MergeCommonBorderAttr( aLinesState, aCellBoxItem, nCellFlags );
    3033           0 :                 }
    3034             :             }
    3035             : 
    3036           0 :             if (!aLinesState.aBorderIndeterminate[SvxBoxItemLine::TOP])
    3037           0 :                 aLinesState.rBoxInfoItem.SetValid(SvxBoxInfoItemValidFlags::TOP);
    3038           0 :             if (!aLinesState.aBorderIndeterminate[SvxBoxItemLine::BOTTOM])
    3039           0 :                 aLinesState.rBoxInfoItem.SetValid(SvxBoxInfoItemValidFlags::BOTTOM);
    3040           0 :             if (!aLinesState.aBorderIndeterminate[SvxBoxItemLine::LEFT])
    3041           0 :                 aLinesState.rBoxInfoItem.SetValid(SvxBoxInfoItemValidFlags::LEFT);
    3042           0 :             if (!aLinesState.aBorderIndeterminate[SvxBoxItemLine::RIGHT])
    3043           0 :                 aLinesState.rBoxInfoItem.SetValid(SvxBoxInfoItemValidFlags::RIGHT);
    3044           0 :             if (!aLinesState.aInnerLineIndeterminate[SvxBoxInfoItemLine::HORI])
    3045           0 :                 aLinesState.rBoxInfoItem.SetValid(SvxBoxInfoItemValidFlags::HORI);
    3046           0 :             if (!aLinesState.aInnerLineIndeterminate[SvxBoxInfoItemLine::VERT])
    3047           0 :                 aLinesState.rBoxInfoItem.SetValid(SvxBoxInfoItemValidFlags::VERT);
    3048             : 
    3049           0 :             if (!aLinesState.bDistanceIndeterminate)
    3050             :             {
    3051           0 :                 if (aLinesState.aDistanceSet[SvxBoxItemLine::TOP])
    3052           0 :                     aLinesState.rBoxItem.SetDistance(aLinesState.aDistance[SvxBoxItemLine::TOP], SvxBoxItemLine::TOP);
    3053           0 :                 if (aLinesState.aDistanceSet[SvxBoxItemLine::BOTTOM])
    3054           0 :                     aLinesState.rBoxItem.SetDistance(aLinesState.aDistance[SvxBoxItemLine::BOTTOM], SvxBoxItemLine::BOTTOM);
    3055           0 :                 if (aLinesState.aDistanceSet[SvxBoxItemLine::LEFT])
    3056           0 :                     aLinesState.rBoxItem.SetDistance(aLinesState.aDistance[SvxBoxItemLine::LEFT], SvxBoxItemLine::LEFT);
    3057           0 :                 if (aLinesState.aDistanceSet[SvxBoxItemLine::RIGHT])
    3058           0 :                     aLinesState.rBoxItem.SetDistance(aLinesState.aDistance[SvxBoxItemLine::RIGHT], SvxBoxItemLine::RIGHT);
    3059           0 :                 aLinesState.rBoxInfoItem.SetValid(SvxBoxInfoItemValidFlags::DISTANCE);
    3060             :             }
    3061             :         }
    3062             :     }
    3063           0 : }
    3064             : 
    3065           0 : bool SvxTableController::selectRow( sal_Int32 row )
    3066             : {
    3067           0 :     if( !mxTable.is() )
    3068           0 :         return false;
    3069           0 :     CellPos aStart( 0, row ), aEnd( mxTable->getColumnCount() - 1, row );
    3070           0 :     StartSelection( aEnd );
    3071           0 :     gotoCell( aStart, true, 0 );
    3072           0 :     return true;
    3073             : }
    3074             : 
    3075           0 : bool SvxTableController::selectColumn( sal_Int32 column )
    3076             : {
    3077           0 :     if( !mxTable.is() )
    3078           0 :         return false;
    3079           0 :     CellPos aStart( column, 0 ), aEnd( column, mxTable->getRowCount() - 1 );
    3080           0 :     StartSelection( aEnd );
    3081           0 :     gotoCell( aStart, true, 0 );
    3082           0 :     return true;
    3083             : }
    3084             : 
    3085           0 : bool SvxTableController::deselectRow( sal_Int32 row )
    3086             : {
    3087           0 :     if( !mxTable.is() )
    3088           0 :         return false;
    3089           0 :     CellPos aStart( 0, row ), aEnd( mxTable->getColumnCount() - 1, row );
    3090           0 :     StartSelection( aEnd );
    3091           0 :     gotoCell( aStart, false, 0 );
    3092           0 :     return true;
    3093             : }
    3094             : 
    3095           0 : bool SvxTableController::deselectColumn( sal_Int32 column )
    3096             : {
    3097           0 :     if( !mxTable.is() )
    3098           0 :         return false;
    3099           0 :     CellPos aStart( column, 0 ), aEnd( column, mxTable->getRowCount() - 1 );
    3100           0 :     StartSelection( aEnd );
    3101           0 :     gotoCell( aStart, false, 0 );
    3102           0 :     return true;
    3103             : }
    3104             : 
    3105           0 : bool SvxTableController::isRowSelected( sal_Int32 nRow )
    3106             : {
    3107           0 :     if( hasSelectedCells() )
    3108             :     {
    3109           0 :         CellPos aFirstPos, aLastPos;
    3110           0 :         getSelectedCells( aFirstPos, aLastPos );
    3111           0 :         if( (aFirstPos.mnCol == 0) && (nRow >= aFirstPos.mnRow && nRow <= aLastPos.mnRow) && (mxTable->getColumnCount() - 1 == aLastPos.mnCol) )
    3112           0 :             return true;
    3113             :     }
    3114           0 :     return false;
    3115             : }
    3116             : 
    3117           0 : bool SvxTableController::isColumnSelected( sal_Int32 nColumn )
    3118             : {
    3119           0 :     if( hasSelectedCells() )
    3120             :     {
    3121           0 :         CellPos aFirstPos, aLastPos;
    3122           0 :         getSelectedCells( aFirstPos, aLastPos );
    3123           0 :         if( (aFirstPos.mnRow == 0) && (nColumn >= aFirstPos.mnCol && nColumn <= aLastPos.mnCol) && (mxTable->getRowCount() - 1 == aLastPos.mnRow) )
    3124           0 :             return true;
    3125             :     }
    3126           0 :     return false;
    3127             : }
    3128             : 
    3129           0 : bool SvxTableController::isRowHeader()
    3130             : {
    3131           0 :     SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( mxTableObj.get() );
    3132           0 :     SdrModel* pModel = pTableObj ? pTableObj->GetModel() : 0;
    3133             : 
    3134           0 :     if( !pTableObj || !pModel )
    3135           0 :         return false;
    3136             : 
    3137           0 :     TableStyleSettings aSettings( pTableObj->getTableStyleSettings() );
    3138             : 
    3139           0 :     return aSettings.mbUseFirstRow;
    3140             : }
    3141             : 
    3142           0 : bool SvxTableController::isColumnHeader()
    3143             : {
    3144           0 :     SdrTableObj* pTableObj = dynamic_cast< sdr::table::SdrTableObj* >( mxTableObj.get() );
    3145           0 :     SdrModel* pModel = pTableObj ? pTableObj->GetModel() : 0;
    3146             : 
    3147           0 :     if( !pTableObj || !pModel )
    3148           0 :         return false;
    3149             : 
    3150           0 :     TableStyleSettings aSettings( pTableObj->getTableStyleSettings() );
    3151             : 
    3152           0 :     return aSettings.mbUseFirstColumn;
    3153             : }
    3154             : 
    3155           0 : bool SvxTableController::setCursorLogicPosition(const Point& rPosition, bool bPoint)
    3156             : {
    3157           0 :     if (mxTableObj->GetObjIdentifier() != OBJ_TABLE)
    3158           0 :         return false;
    3159             : 
    3160           0 :     SdrTableObj* pTableObj = static_cast<SdrTableObj*>(mxTableObj.get());
    3161           0 :     CellPos aCellPos;
    3162           0 :     if (pTableObj->CheckTableHit(rPosition, aCellPos.mnCol, aCellPos.mnRow, 0) != SDRTABLEHIT_NONE)
    3163             :     {
    3164             :         // Position is a table cell.
    3165           0 :         if (mbCellSelectionMode)
    3166             :         {
    3167             :             // We have a table selection already: adjust the point or the mark.
    3168           0 :             if (bPoint)
    3169           0 :                 setSelectedCells(maCursorFirstPos, aCellPos);
    3170             :             else
    3171           0 :                 setSelectedCells(aCellPos, maCursorLastPos);
    3172           0 :             return true;
    3173             :         }
    3174           0 :         else if (aCellPos != maMouseDownPos)
    3175             :         {
    3176             :             // No selection, but rPosition is at an other cell: start table selection.
    3177           0 :             StartSelection(maMouseDownPos);
    3178             :             // Update graphic selection, should be hidden now.
    3179           0 :             mpView->AdjustMarkHdl();
    3180             :         }
    3181             :     }
    3182             : 
    3183           0 :     return false;
    3184             : }
    3185             : 
    3186         435 : } }
    3187             : 
    3188             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11