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