1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
22 #include <com/sun/star/container/XNamed.hpp>
23 #include <com/sun/star/container/XNameAccess.hpp>
24 #include <com/sun/star/container/XIndexAccess.hpp>
25 #include <comphelper/configuration.hxx>
26 #include <vcl/canvastools.hxx>
27 #include <vcl/ptrstyle.hxx>
28 #include <com/sun/star/style/XStyle.hpp>
29 #include <com/sun/star/beans/XPropertySet.hpp>
30 #include <basegfx/polygon/b2dpolygontools.hxx>
31 #include <basegfx/polygon/b2dpolypolygon.hxx>
32 #include <basegfx/polygon/b2dpolygon.hxx>
33 #include <svl/style.hxx>
34 #include <editeng/editstat.hxx>
35 #include <editeng/outlobj.hxx>
36 #include <sdr/properties/textproperties.hxx>
37 #include <svx/svdmodel.hxx>
38 #include <svx/svdotable.hxx>
39 #include <svx/svdhdl.hxx>
40 #include "viewcontactoftableobj.hxx"
41 #include <svx/svdoutl.hxx>
42 #include <svx/svddrag.hxx>
43 #include <tablemodel.hxx>
45 #include "tablelayouter.hxx"
46 #include "tablehandles.hxx"
47 #include <svx/sdr/table/tabledesign.hxx>
48 #include <svx/svdundo.hxx>
49 #include <svx/strings.hrc>
50 #include <svx/dialmgr.hxx>
51 #include <editeng/writingmodeitem.hxx>
52 #include <editeng/frmdiritem.hxx>
53 #include <libxml/xmlwriter.h>
54 #include <comphelper/diagnose_ex.hxx>
56 #include <boost/property_tree/ptree.hpp>
58 #include "sdrtableobjimpl.hxx"
60 using ::com::sun::star::uno::Any
;
61 using ::com::sun::star::uno::Reference
;
62 using ::com::sun::star::uno::UNO_QUERY
;
63 using ::com::sun::star::uno::UNO_QUERY_THROW
;
64 using ::com::sun::star::uno::Exception
;
65 using ::com::sun::star::container::XIndexAccess
;
66 using ::com::sun::star::style::XStyle
;
67 using ::com::sun::star::table::XTableRows
;
68 using ::com::sun::star::table::XTableColumns
;
69 using ::com::sun::star::table::XTable
;
70 using ::com::sun::star::beans::XPropertySet
;
71 using ::com::sun::star::util::XModifyBroadcaster
;
72 using sdr::properties::TextProperties
;
73 using sdr::properties::BaseProperties
;
74 using namespace ::com::sun::star
;
75 using namespace ::com::sun::star::text
;
76 using namespace ::com::sun::star::container
;
77 using namespace ::com::sun::star::style
;
79 namespace sdr::table
{
83 class TableProperties
: public TextProperties
86 // create a new itemset
87 SfxItemSet
CreateObjectSpecificItemSet(SfxItemPool
& rPool
) override
;
91 explicit TableProperties(SdrObject
& rObj
);
93 // constructor for copying, but using new object
94 TableProperties(const TableProperties
& rProps
, SdrObject
& rObj
);
96 // Clone() operator, normally just calls the local copy constructor
97 std::unique_ptr
<BaseProperties
> Clone(SdrObject
& rObj
) const override
;
99 virtual void ItemChange(const sal_uInt16 nWhich
, const SfxPoolItem
* pNewItem
= nullptr) override
;
104 TableProperties::TableProperties(SdrObject
& rObj
)
105 : TextProperties(rObj
)
109 TableProperties::TableProperties(const TableProperties
& rProps
, SdrObject
& rObj
)
110 : TextProperties(rProps
, rObj
)
114 std::unique_ptr
<BaseProperties
> TableProperties::Clone(SdrObject
& rObj
) const
116 return std::unique_ptr
<BaseProperties
>(new TableProperties(*this, rObj
));
119 void TableProperties::ItemChange(const sal_uInt16 nWhich
, const SfxPoolItem
* pNewItem
)
121 if( nWhich
== SDRATTR_TEXTDIRECTION
)
122 AttributeProperties::ItemChange( nWhich
, pNewItem
);
124 TextProperties::ItemChange( nWhich
, pNewItem
);
127 // create a new itemset
128 SfxItemSet
TableProperties::CreateObjectSpecificItemSet(SfxItemPool
& rPool
)
130 return SfxItemSet(rPool
,
132 // range from SdrAttrObj
133 svl::Items
<SDRATTR_START
, SDRATTR_SHADOW_LAST
,
134 SDRATTR_MISC_FIRST
, SDRATTR_MISC_LAST
,
135 SDRATTR_TEXTDIRECTION
, SDRATTR_TEXTDIRECTION
,
137 // range for SdrTableObj
138 SDRATTR_TABLE_FIRST
, SDRATTR_TABLE_LAST
,
140 // range from SdrTextObj
141 EE_ITEMS_START
, EE_ITEMS_END
>);
146 class TableObjectGeoData
: public SdrTextObjGeoData
149 tools::Rectangle maLogicRect
;
154 TableStyleSettings::TableStyleSettings()
155 : mbUseFirstRow(true)
156 , mbUseLastRow(false)
157 , mbUseFirstColumn(false)
158 , mbUseLastColumn(false)
159 , mbUseRowBanding(true)
160 , mbUseColumnBanding(false)
164 TableStyleSettings::TableStyleSettings( const TableStyleSettings
& rStyle
)
169 TableStyleSettings
& TableStyleSettings::operator=(const TableStyleSettings
& rStyle
)
171 mbUseFirstRow
= rStyle
.mbUseFirstRow
;
172 mbUseLastRow
= rStyle
.mbUseLastRow
;
173 mbUseFirstColumn
= rStyle
.mbUseFirstColumn
;
174 mbUseLastColumn
= rStyle
.mbUseLastColumn
;
175 mbUseRowBanding
= rStyle
.mbUseRowBanding
;
176 mbUseColumnBanding
= rStyle
.mbUseColumnBanding
;
180 bool TableStyleSettings::operator==( const TableStyleSettings
& rStyle
) const
183 (mbUseFirstRow
== rStyle
.mbUseFirstRow
) &&
184 (mbUseLastRow
== rStyle
.mbUseLastRow
) &&
185 (mbUseFirstColumn
== rStyle
.mbUseFirstColumn
) &&
186 (mbUseLastColumn
== rStyle
.mbUseLastColumn
) &&
187 (mbUseRowBanding
== rStyle
.mbUseRowBanding
) &&
188 (mbUseColumnBanding
== rStyle
.mbUseColumnBanding
);
192 SdrTableObjImpl
* SdrTableObjImpl::lastLayoutTable
= nullptr;
193 tools::Rectangle
SdrTableObjImpl::lastLayoutInputRectangle
;
194 tools::Rectangle
SdrTableObjImpl::lastLayoutResultRectangle
;
195 bool SdrTableObjImpl::lastLayoutFitWidth
;
196 bool SdrTableObjImpl::lastLayoutFitHeight
;
197 WritingMode
SdrTableObjImpl::lastLayoutMode
;
198 sal_Int32
SdrTableObjImpl::lastRowCount
;
199 sal_Int32
SdrTableObjImpl::lastColCount
;
200 bool SdrTableObjImpl::rowSizeChanged
= false;
201 std::vector
<sal_Int32
> SdrTableObjImpl::lastColWidths
;
203 SdrTableObjImpl::SdrTableObjImpl()
204 : mpTableObj( nullptr )
205 , mbSkipChangeLayout(false)
210 SdrTableObjImpl::~SdrTableObjImpl()
212 if( lastLayoutTable
== this )
213 lastLayoutTable
= nullptr;
217 void SdrTableObjImpl::CropTableModelToSelection(const CellPos
& rStart
, const CellPos
& rEnd
)
224 const sal_Int32
nColumns(rEnd
.mnCol
- rStart
.mnCol
+ 1);
225 const sal_Int32
nRows(rEnd
.mnRow
- rStart
.mnRow
+ 1);
227 if(nColumns
< 1 || nRows
< 1 || nColumns
> getColumnCount() || nRows
> getRowCount())
232 // tdf#116977 First thought was to create the new TableModel, copy data to it and then exchange
233 // mxTable and dispose old one. This does *not* work, even when all stuff looks nicely referenced
234 // and safe *because* Cell::create gets handed over the current SdrTableObj, hands it to
235 // ::Cell and there the local mxTable is initialized using rTableObj.getTable() (!). Due to This,
236 // the new created Cells in a new created TableModel based on given mpTableObj *will be disposed*
237 // when the old mxTable gets disposed - ARGH!
238 // To avoid, change strategy: Remember old TableModel, reset mxTable immediately - this is the
239 // SdrTableObjImpl of the current SdrTableObj anyways. Luckily, this works as intended...
241 // remember old TableModel
242 TableModelRef
xOldTable(mxTable
);
244 // immediately create new one and initialize. This creates ::Cell's which then will use
245 // the correct TableModel (accessed through SdrTableObj, but using local mxTable)
246 mxTable
= new TableModel(mpTableObj
);
247 mxTable
->init(nColumns
, nRows
);
250 for( sal_Int32 nRow
= 0; nRow
< nRows
; ++nRow
)
252 for( sal_Int32 nCol
= 0; nCol
< nColumns
; ++nCol
) try
254 CellRef
xTargetCell( mxTable
->getCell( nCol
, nRow
) );
255 if( xTargetCell
.is() )
256 xTargetCell
->cloneFrom( xOldTable
->getCell( rStart
.mnCol
+ nCol
, rStart
.mnRow
+ nRow
) );
260 TOOLS_WARN_EXCEPTION("svx.table", "");
265 Reference
< XTableRows
> xNewRows(mxTable
->getRows(), css::uno::UNO_SET_THROW
);
266 static constexpr OUStringLiteral
sHeight( u
"Height" );
267 for( sal_Int32 nRow
= 0; nRow
< nRows
; ++nRow
)
269 Reference
< XPropertySet
> xNewSet( xNewRows
->getByIndex( nRow
), UNO_QUERY_THROW
);
270 xNewSet
->setPropertyValue( sHeight
, Any( mpLayouter
->getRowHeight( rStart
.mnRow
+ nRow
) ) );
273 // copy column widths
274 Reference
< XTableColumns
> xNewColumns( mxTable
->getColumns(), css::uno::UNO_SET_THROW
);
275 static constexpr OUStringLiteral
sWidth( u
"Width" );
276 for( sal_Int32 nCol
= 0; nCol
< nColumns
; ++nCol
)
278 Reference
< XPropertySet
> xNewSet( xNewColumns
->getByIndex( nCol
), UNO_QUERY_THROW
);
279 xNewSet
->setPropertyValue( sWidth
, Any( mpLayouter
->getColumnWidth( rStart
.mnCol
+ nCol
) ) );
282 // reset layouter which still holds a copy to old TableModel
285 // cleanup old TableModel
287 Reference
< XModifyListener
> xListener( static_cast< css::util::XModifyListener
* >(this) );
288 xOldTable
->removeModifyListener( xListener
);
289 xOldTable
->dispose();
293 // create and hand over to new TableLayouter
294 mpLayouter
.reset(new TableLayouter( mxTable
));
296 // add needed listener to react on changes
297 Reference
< XModifyListener
> xListener( static_cast< css::util::XModifyListener
* >(this) );
298 mxTable
->addModifyListener( xListener
);
300 // Apply Style to Cells
303 // layout cropped table
304 auto aRectangle
= mpTableObj
->getRectangle();
305 LayoutTable(aRectangle
, false, false);
306 mpTableObj
->setRectangle(aRectangle
);
309 void SdrTableObjImpl::init( SdrTableObj
* pTable
, sal_Int32 nColumns
, sal_Int32 nRows
)
312 mxTable
= new TableModel( pTable
);
313 mxTable
->init( nColumns
, nRows
);
314 Reference
< XModifyListener
> xListener( static_cast< css::util::XModifyListener
* >(this) );
315 mxTable
->addModifyListener( xListener
);
316 mpLayouter
.reset(new TableLayouter( mxTable
));
317 auto aRectangle
= mpTableObj
->getRectangle();
318 LayoutTable(aRectangle
, true, true);
319 mpTableObj
->setRectangle(aRectangle
);
320 mpTableObj
->maLogicRect
= aRectangle
;
324 SdrTableObjImpl
& SdrTableObjImpl::operator=( const SdrTableObjImpl
& rSource
)
331 if(nullptr == mpTableObj
|| nullptr == rSource
.mpTableObj
)
333 // error: need both SdrObjects to successfully copy data
337 // remove evtl. listeners from local
338 disconnectTableStyle();
340 // reset layouter which holds a copy
343 // cleanup local mxTable if used
346 Reference
< XModifyListener
> xListener( static_cast< css::util::XModifyListener
* >(this) );
347 mxTable
->removeModifyListener( xListener
);
352 // tdf#127481: reset active cell reference
353 mxActiveCell
.clear();
355 // copy TableStyle (short internal data)
356 maTableStyle
= rSource
.maTableStyle
;
358 // create/copy new mxTable. This will copy all needed cells, too
359 mxTable
= new TableModel( mpTableObj
, rSource
.mxTable
);
361 // create and hand over to new TableLayouter
362 mpLayouter
.reset(new TableLayouter( mxTable
));
364 // add needed listener to react on changes
365 Reference
< XModifyListener
> xListener( static_cast< css::util::XModifyListener
* >(this) );
366 mxTable
->addModifyListener( xListener
);
369 Reference
< XIndexAccess
> xNewTableStyle
;
370 SdrModel
& rSourceSdrModel(rSource
.mpTableObj
->getSdrModelFromSdrObject());
371 SdrModel
& rTargetSdrModel(mpTableObj
->getSdrModelFromSdrObject());
373 if(rSource
.mxTableStyle
.is() && &rSourceSdrModel
== &rTargetSdrModel
)
375 // source and target model the same -> keep current TableStyle
376 xNewTableStyle
= rSource
.mxTableStyle
;
379 if(!xNewTableStyle
.is() && rSource
.mxTableStyle
.is()) try
381 // search in target SdrModel for that TableStyle
382 const OUString
sStyleName( Reference
< XNamed
>( rSource
.mxTableStyle
, UNO_QUERY_THROW
)->getName() );
383 Reference
< XStyleFamiliesSupplier
> xSFS(rTargetSdrModel
.getUnoModel(), UNO_QUERY_THROW
);
384 Reference
< XNameAccess
> xFamilyNameAccess( xSFS
->getStyleFamilies(), css::uno::UNO_SET_THROW
);
385 Reference
< XNameAccess
> xTableFamilyAccess( xFamilyNameAccess
->getByName( u
"table"_ustr
), UNO_QUERY_THROW
);
387 if( xTableFamilyAccess
->hasByName( sStyleName
) )
389 // found table style with the same name
390 xTableFamilyAccess
->getByName( sStyleName
) >>= xNewTableStyle
;
394 // copy or? Not found, use 1st existing TableStyle (or none)
395 Reference
< XIndexAccess
> xIndexAccess( xTableFamilyAccess
, UNO_QUERY_THROW
);
396 xIndexAccess
->getByIndex( 0 ) >>= xNewTableStyle
;
401 TOOLS_WARN_EXCEPTION("svx.table", "");
404 // set that TableStyle
405 mxTableStyle
= std::move(xNewTableStyle
);
407 // Apply Style to Cells
411 mpTableObj
->setRectangle(mpTableObj
->maLogicRect
);
413 // layout cloned table
414 auto aRectangle
= mpTableObj
->getRectangle();
415 LayoutTable(aRectangle
, false, false);
416 mpTableObj
->setRectangle(aRectangle
);
418 // re-connect to styles (evtl. in new SdrModel)
424 void SdrTableObjImpl::ApplyCellStyles()
426 if( !mxTable
.is() || !mxTableStyle
.is() )
429 const sal_Int32 nColCount
= getColumnCount();
430 const sal_Int32 nRowCount
= getRowCount();
432 const TableStyleSettings
& rStyle
= maTableStyle
;
435 for( aPos
.mnRow
= 0; aPos
.mnRow
< nRowCount
; ++aPos
.mnRow
)
437 const bool bFirstRow
= (aPos
.mnRow
== 0) && rStyle
.mbUseFirstRow
;
438 const bool bLastRow
= (aPos
.mnRow
== nRowCount
-1) && rStyle
.mbUseLastRow
;
440 for( aPos
.mnCol
= 0; aPos
.mnCol
< nColCount
; ++aPos
.mnCol
)
442 Reference
< XStyle
> xStyle
;
444 // first and last row win first, if used and available
447 mxTableStyle
->getByIndex(first_row_style
) >>= xStyle
;
451 mxTableStyle
->getByIndex(last_row_style
) >>= xStyle
;
456 // next come first and last column, if used and available
457 if( rStyle
.mbUseFirstColumn
&& (aPos
.mnCol
== 0) )
459 mxTableStyle
->getByIndex(first_column_style
) >>= xStyle
;
461 else if( rStyle
.mbUseLastColumn
&& (aPos
.mnCol
== nColCount
-1) )
463 mxTableStyle
->getByIndex(last_column_style
) >>= xStyle
;
467 if( !xStyle
.is() && rStyle
.mbUseRowBanding
)
469 if( (aPos
.mnRow
& 1) == 0 )
471 mxTableStyle
->getByIndex(even_rows_style
) >>= xStyle
;
475 mxTableStyle
->getByIndex(odd_rows_style
) >>= xStyle
;
479 if( !xStyle
.is() && rStyle
.mbUseColumnBanding
)
481 if( (aPos
.mnCol
& 1) == 0 )
483 mxTableStyle
->getByIndex(even_columns_style
) >>= xStyle
;
487 mxTableStyle
->getByIndex(odd_columns_style
) >>= xStyle
;
493 // use default cell style if non found yet
494 mxTableStyle
->getByIndex(body_style
) >>= xStyle
;
500 SfxUnoStyleSheet
* pStyle
= SfxUnoStyleSheet::getUnoStyleSheet(xStyle
);
504 CellRef
xCell( getCell( aPos
) );
505 if( xCell
.is() && ( xCell
->GetStyleSheet() != pStyle
) )
507 xCell
->SetStyleSheet( pStyle
, true );
516 void SdrTableObjImpl::dispose()
518 disconnectTableStyle();
519 mxTableStyle
.clear();
525 Reference
< XModifyListener
> xListener( static_cast< css::util::XModifyListener
* >(this) );
526 mxTable
->removeModifyListener( xListener
);
533 void SdrTableObjImpl::DragEdge( bool mbHorizontal
, int nEdge
, sal_Int32 nOffset
)
535 if( !((nEdge
>= 0) && mxTable
.is()))
540 static constexpr OUString
sSize( u
"Size"_ustr
);
543 if (nEdge
<= getRowCount())
545 sal_Int32 nHeight
= mpLayouter
->getRowHeight( (!nEdge
)?nEdge
:(nEdge
-1) );
550 Reference
< XIndexAccess
> xRows( mxTable
->getRows(), UNO_QUERY_THROW
);
551 Reference
< XPropertySet
> xRowSet( xRows
->getByIndex( (!nEdge
)?nEdge
:(nEdge
-1) ), UNO_QUERY_THROW
);
552 xRowSet
->setPropertyValue( sSize
, Any( nHeight
) );
553 rowSizeChanged
= true;
559 fixes fdo#59889 and resizing of table in edge dragging
560 Total vertical edges in a NxN table is N+1, indexed from 0 to N and total Columns is N, indexed from 0 to N-1
561 In LTR table vertical edge responsible for dragging of column x(x=0 to N-1) is, Edge x+1
562 But in RTL table vertical edge responsible for dragging of column x(x=0 to N-1, but from right to left)is, Edge x
563 In LTR table dragging of edge 0(for RTL table edge N) does nothing.
565 //Todo: Implement Dragging functionality for leftmost edge of table.
566 if (nEdge
<= getColumnCount())
568 const bool bRTL
= mpTableObj
!= nullptr && (mpTableObj
->GetWritingMode() == WritingMode_RL_TB
);
572 nWidth
= mpLayouter
->getColumnWidth( nEdge
);
576 nWidth
= mpLayouter
->getColumnWidth( (!nEdge
)?nEdge
:(nEdge
-1) );
578 Reference
< XIndexAccess
> xCols( mxTable
->getColumns(), UNO_QUERY_THROW
);
580 if(bRTL
&& nEdge
<getColumnCount())
582 Reference
< XPropertySet
> xColSet( xCols
->getByIndex( nEdge
), UNO_QUERY_THROW
);
583 xColSet
->setPropertyValue( sSize
, Any( nWidth
) );
585 else if(!bRTL
&& nEdge
>0)
587 Reference
< XPropertySet
> xColSet( xCols
->getByIndex( nEdge
-1 ), UNO_QUERY_THROW
);
588 xColSet
->setPropertyValue( sSize
, Any( nWidth
) );
590 /* To prevent the table resizing on edge dragging */
591 if( nEdge
> 0 && nEdge
< mxTable
->getColumnCount() )
596 nWidth
= mpLayouter
->getColumnWidth(nEdge
);
597 nWidth
= std::max(static_cast<sal_Int32
>(nWidth
- nOffset
), sal_Int32(0));
599 Reference
<XPropertySet
> xColSet(xCols
->getByIndex(nEdge
), UNO_QUERY_THROW
);
600 xColSet
->setPropertyValue(sSize
, Any(nWidth
));
607 TOOLS_WARN_EXCEPTION("svx.table", "");
615 void SAL_CALL
SdrTableObjImpl::modified( const css::lang::EventObject
& aEvent
)
617 if (aEvent
.Source
== mxTableStyle
&& mpTableObj
)
618 static_cast<TextProperties
&>(mpTableObj
->GetProperties()).increaseVersion();
623 void SdrTableObjImpl::update()
625 // source can be the table model itself or the assigned table template
626 TableModelNotifyGuard
aGuard( mxTable
.get() );
630 if( (maEditPos
.mnRow
>= getRowCount()) || (maEditPos
.mnCol
>= getColumnCount()) || (getCell( maEditPos
) != mxActiveCell
) )
632 if(maEditPos
.mnRow
>= getRowCount())
633 maEditPos
.mnRow
= getRowCount()-1;
635 if(maEditPos
.mnCol
>= getColumnCount())
636 maEditPos
.mnCol
= getColumnCount()-1;
638 mpTableObj
->setActiveCell( maEditPos
);
643 mpTableObj
->setRectangle(mpTableObj
->maLogicRect
);
644 auto aRectangle
= mpTableObj
->getRectangle();
645 LayoutTable(aRectangle
, false, false);
646 mpTableObj
->setRectangle(aRectangle
);
648 mpTableObj
->SetBoundAndSnapRectsDirty();
649 mpTableObj
->ActionChanged();
650 mpTableObj
->BroadcastObjectChange();
654 void SdrTableObjImpl::connectTableStyle()
656 if( mxTableStyle
.is() )
658 Reference
< XModifyBroadcaster
> xBroadcaster( mxTableStyle
, UNO_QUERY
);
659 if( xBroadcaster
.is() )
661 Reference
< XModifyListener
> xListener( static_cast< css::util::XModifyListener
* >(this) );
662 xBroadcaster
->addModifyListener( xListener
);
668 void SdrTableObjImpl::disconnectTableStyle()
670 if( mxTableStyle
.is() )
672 Reference
< XModifyBroadcaster
> xBroadcaster( mxTableStyle
, UNO_QUERY
);
673 if( xBroadcaster
.is() )
675 Reference
< XModifyListener
> xListener( static_cast< css::util::XModifyListener
* >(this) );
676 xBroadcaster
->removeModifyListener( xListener
);
682 bool SdrTableObjImpl::isInUse()
684 return mpTableObj
&& mpTableObj
->IsInserted();
687 void SdrTableObjImpl::dumpAsXml(xmlTextWriterPtr pWriter
) const
689 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SdrTableObjImpl"));
691 mpLayouter
->dumpAsXml(pWriter
);
692 mxTable
->dumpAsXml(pWriter
);
693 (void)xmlTextWriterEndElement(pWriter
);
700 void SAL_CALL
SdrTableObjImpl::disposing( const css::lang::EventObject
& Source
)
702 assert(Source
.Source
== mxTableStyle
);
705 Reference
<XIndexAccess
> xDefaultStyle
;
708 Reference
<XStyleFamiliesSupplier
> xSupplier(mpTableObj
->getSdrModelFromSdrObject().getUnoModel(), UNO_QUERY_THROW
);
709 Reference
<XNameAccess
> xTableFamily(xSupplier
->getStyleFamilies()->getByName(u
"table"_ustr
), UNO_QUERY_THROW
);
710 xDefaultStyle
.set(xTableFamily
->getByName(u
"default"_ustr
), UNO_QUERY_THROW
);
714 TOOLS_WARN_EXCEPTION("svx.table", "");
717 mpTableObj
->setTableStyle(xDefaultStyle
);
721 CellRef
SdrTableObjImpl::getCell( const CellPos
& rPos
) const
724 if( mxTable
.is() ) try
726 xCell
= mxTable
->getCell( rPos
.mnCol
, rPos
.mnRow
);
730 TOOLS_WARN_EXCEPTION("svx.table", "");
736 sal_Int32
SdrTableObjImpl::getColumnCount() const
738 return mxTable
.is() ? mxTable
->getColumnCount() : 0;
741 std::vector
<sal_Int32
> SdrTableObjImpl::getColumnWidths() const
743 std::vector
<sal_Int32
> aRet
;
746 aRet
= mxTable
->getColumnWidths();
751 sal_Int32
SdrTableObjImpl::getRowCount() const
753 return mxTable
.is() ? mxTable
->getRowCount() : 0;
756 void SdrTableObjImpl::LayoutTable( tools::Rectangle
& rArea
, bool bFitWidth
, bool bFitHeight
)
758 if (comphelper::IsFuzzing())
763 // Optimization: SdrTableObj::SetChanged() can call this very often, repeatedly
764 // with the same settings, noticeably increasing load time. Skip if already done.
765 bool bInteractiveMightGrowBecauseTextChanged
=
766 mpTableObj
->IsReallyEdited() && (mpTableObj
->IsAutoGrowHeight() || mpTableObj
->IsAutoGrowWidth());
767 WritingMode writingMode
= mpTableObj
->GetWritingMode();
768 if( bInteractiveMightGrowBecauseTextChanged
769 || lastLayoutTable
!= this || lastLayoutInputRectangle
!= rArea
770 || lastLayoutFitWidth
!= bFitWidth
|| lastLayoutFitHeight
!= bFitHeight
771 || lastLayoutMode
!= writingMode
772 || lastRowCount
!= getRowCount()
773 || lastColCount
!= getColumnCount()
774 || lastColWidths
!= getColumnWidths()
777 lastLayoutTable
= this;
778 lastLayoutInputRectangle
= rArea
;
779 lastLayoutFitWidth
= bFitWidth
;
780 lastLayoutFitHeight
= bFitHeight
;
781 lastLayoutMode
= writingMode
;
782 lastRowCount
= getRowCount();
783 lastColCount
= getColumnCount();
784 // Column resize, when the total width and column count of the
785 // table is unchanged, but re-layout is still needed.
786 lastColWidths
= getColumnWidths();
787 TableModelNotifyGuard
aGuard( mxTable
.get() );
788 mpLayouter
->LayoutTable( rArea
, bFitWidth
, bFitHeight
);
789 lastLayoutResultRectangle
= rArea
;
790 rowSizeChanged
= false;
794 rArea
= lastLayoutResultRectangle
;
795 mpLayouter
->UpdateBorderLayout();
799 void SdrTableObjImpl::UpdateCells( tools::Rectangle
const & rArea
)
801 if( mpLayouter
&& mxTable
.is() )
803 TableModelNotifyGuard
aGuard( mxTable
.get() );
804 mpLayouter
->updateCells( rArea
);
805 mxTable
->setModified(true);
810 // BaseProperties section
813 std::unique_ptr
<sdr::properties::BaseProperties
> SdrTableObj::CreateObjectSpecificProperties()
815 return std::make_unique
<TableProperties
>(*this);
819 // DrawContact section
822 std::unique_ptr
<sdr::contact::ViewContact
> SdrTableObj::CreateObjectSpecificViewContact()
824 return std::make_unique
<sdr::contact::ViewContactOfTableObj
>(*this);
827 SdrTableObj::SdrTableObj(SdrModel
& rSdrModel
)
828 : SdrTextObj(rSdrModel
)
830 osl_atomic_increment(&m_refCount
); // other I get deleted during construction
832 osl_atomic_decrement(&m_refCount
);
835 SdrTableObj::SdrTableObj(SdrModel
& rSdrModel
, SdrTableObj
const & rSource
)
836 : SdrTextObj(rSdrModel
, rSource
)
838 osl_atomic_increment(&m_refCount
);
842 TableModelNotifyGuard
aGuard( mpImpl
.is() ? mpImpl
->mxTable
.get() : nullptr );
844 maLogicRect
= rSource
.maLogicRect
;
845 maRectangle
= rSource
.maRectangle
;
846 maGeo
= rSource
.maGeo
;
847 meTextKind
= rSource
.meTextKind
;
848 mbTextFrame
= rSource
.mbTextFrame
;
849 maTextSize
= rSource
.maTextSize
;
850 mbTextSizeDirty
= rSource
.mbTextSizeDirty
;
851 mbNoShear
= rSource
.mbNoShear
;
852 mbDisableAutoWidthOnDragging
= rSource
.mbDisableAutoWidthOnDragging
;
854 // use SdrTableObjImpl::operator= now to
855 // copy model data and other stuff (see there)
856 *mpImpl
= *rSource
.mpImpl
;
858 osl_atomic_decrement(&m_refCount
);
861 SdrTableObj::SdrTableObj(
863 const ::tools::Rectangle
& rNewRect
,
866 : SdrTextObj(rSdrModel
, rNewRect
)
867 ,maLogicRect(rNewRect
)
869 osl_atomic_increment(&m_refCount
);
877 init( nColumns
, nRows
);
879 osl_atomic_decrement(&m_refCount
);
883 void SdrTableObj::init( sal_Int32 nColumns
, sal_Int32 nRows
)
887 mpImpl
= new SdrTableObjImpl
;
888 mpImpl
->init( this, nColumns
, nRows
);
890 // Stuff done from old SetModel:
891 if( !maLogicRect
.IsEmpty() )
893 setRectangle(maLogicRect
);
894 auto aRectangle
= getRectangle();
895 mpImpl
->LayoutTable(aRectangle
, false, false);
896 setRectangle(aRectangle
);
901 SdrTableObj::~SdrTableObj()
910 Reference
< XTable
> SdrTableObj::getTable() const
912 return mpImpl
->mxTable
;
915 const rtl::Reference
< TableModel
> & SdrTableObj::getUnoTable() const
917 return mpImpl
->mxTable
;
920 bool SdrTableObj::isValid( const CellPos
& rPos
) const
922 return (rPos
.mnCol
>= 0) && (rPos
.mnCol
< mpImpl
->getColumnCount()) && (rPos
.mnRow
>= 0) && (rPos
.mnRow
< mpImpl
->getRowCount());
926 CellPos
SdrTableObj::getFirstCell()
928 return CellPos( 0,0 );
932 CellPos
SdrTableObj::getLastCell() const
935 if( mpImpl
->mxTable
.is() )
937 aPos
.mnCol
= mpImpl
->getColumnCount()-1;
938 aPos
.mnRow
= mpImpl
->getRowCount()-1;
944 CellPos
SdrTableObj::getLeftCell( const CellPos
& rPos
, bool bEdgeTravel
) const
946 switch( GetWritingMode() )
949 case WritingMode_LR_TB
:
950 return getPreviousCell( rPos
, bEdgeTravel
);
951 case WritingMode_RL_TB
:
952 return getNextCell( rPos
, bEdgeTravel
);
953 case WritingMode_TB_RL
:
954 return getPreviousRow( rPos
, bEdgeTravel
);
959 CellPos
SdrTableObj::getRightCell( const CellPos
& rPos
, bool bEdgeTravel
) const
961 switch( GetWritingMode() )
964 case WritingMode_LR_TB
:
965 return getNextCell( rPos
, bEdgeTravel
);
966 case WritingMode_RL_TB
:
967 return getPreviousCell( rPos
, bEdgeTravel
);
968 case WritingMode_TB_RL
:
969 return getNextRow( rPos
, bEdgeTravel
);
974 CellPos
SdrTableObj::getUpCell( const CellPos
& rPos
, bool bEdgeTravel
) const
976 switch( GetWritingMode() )
979 case WritingMode_LR_TB
:
980 case WritingMode_RL_TB
:
981 return getPreviousRow( rPos
, bEdgeTravel
);
982 case WritingMode_TB_RL
:
983 return getPreviousCell( rPos
, bEdgeTravel
);
988 CellPos
SdrTableObj::getDownCell( const CellPos
& rPos
, bool bEdgeTravel
) const
990 switch( GetWritingMode() )
993 case WritingMode_LR_TB
:
994 case WritingMode_RL_TB
:
995 return getNextRow( rPos
, bEdgeTravel
);
996 case WritingMode_TB_RL
:
997 return getNextCell( rPos
, bEdgeTravel
);
1002 CellPos
SdrTableObj::getPreviousCell( const CellPos
& rPos
, bool bEdgeTravel
) const
1004 CellPos
aPos( rPos
);
1007 CellRef
xCell( mpImpl
->getCell( aPos
) );
1008 if( xCell
.is() && xCell
->isMerged() )
1010 sal_Int32 nTemp
= 0;
1011 findMergeOrigin( mpImpl
->mxTable
, aPos
.mnCol
, aPos
.mnRow
, aPos
.mnCol
, nTemp
);
1014 if( aPos
.mnCol
> 0 )
1019 else if( bEdgeTravel
&& (aPos
.mnRow
> 0) )
1021 aPos
.mnCol
= mpImpl
->mxTable
->getColumnCount()-1;
1029 CellPos
SdrTableObj::getNextCell( const CellPos
& rPos
, bool bEdgeTravel
) const
1031 CellPos
aPos( rPos
);
1034 CellRef
xCell( mpImpl
->getCell( aPos
) );
1037 if( xCell
->isMerged() )
1039 findMergeOrigin( mpImpl
->mxTable
, aPos
.mnCol
, aPos
.mnRow
, aPos
.mnCol
, aPos
.mnRow
);
1041 xCell
= mpImpl
->getCell(aPos
);
1045 aPos
.mnCol
+= xCell
->getColumnSpan();
1046 aPos
.mnRow
= rPos
.mnRow
;
1051 aPos
.mnCol
+= xCell
->getColumnSpan();
1054 if( aPos
.mnCol
< mpImpl
->mxTable
->getColumnCount() )
1057 if( bEdgeTravel
&& ((aPos
.mnRow
+ 1) < mpImpl
->getRowCount()) )
1066 // last cell reached, no traveling possible
1071 CellPos
SdrTableObj::getPreviousRow( const CellPos
& rPos
, bool bEdgeTravel
) const
1073 CellPos
aPos( rPos
);
1076 CellRef
xCell( mpImpl
->getCell( aPos
) );
1077 if( xCell
.is() && xCell
->isMerged() )
1079 sal_Int32 nTemp
= 0;
1080 findMergeOrigin( mpImpl
->mxTable
, aPos
.mnCol
, aPos
.mnRow
, nTemp
, aPos
.mnRow
);
1083 if( aPos
.mnRow
> 0 )
1087 else if( bEdgeTravel
&& (aPos
.mnCol
> 0) )
1089 aPos
.mnRow
= mpImpl
->mxTable
->getRowCount()-1;
1097 CellPos
SdrTableObj::getNextRow( const CellPos
& rPos
, bool bEdgeTravel
) const
1099 CellPos
aPos( rPos
);
1103 CellRef
xCell( mpImpl
->getCell( rPos
) );
1106 if( xCell
->isMerged() )
1108 findMergeOrigin( mpImpl
->mxTable
, aPos
.mnCol
, aPos
.mnRow
, aPos
.mnCol
, aPos
.mnRow
);
1109 xCell
= mpImpl
->getCell(aPos
);
1110 aPos
.mnCol
= rPos
.mnCol
;
1114 aPos
.mnRow
+= xCell
->getRowSpan();
1116 if( aPos
.mnRow
< mpImpl
->mxTable
->getRowCount() )
1119 if( bEdgeTravel
&& (aPos
.mnCol
+ 1) < mpImpl
->mxTable
->getColumnCount() )
1124 while( aPos
.mnCol
< mpImpl
->mxTable
->getColumnCount() )
1126 xCell
= mpImpl
->getCell( aPos
);
1127 if( xCell
.is() && !xCell
->isMerged() )
1135 // last position reached, no more traveling possible
1140 const TableStyleSettings
& SdrTableObj::getTableStyleSettings() const
1144 return mpImpl
->maTableStyle
;
1148 static TableStyleSettings aTmp
;
1154 void SdrTableObj::setTableStyleSettings( const TableStyleSettings
& rStyle
)
1158 mpImpl
->maTableStyle
= rStyle
;
1164 TableHitKind
SdrTableObj::CheckTableHit( const Point
& rPos
, sal_Int32
& rnX
, sal_Int32
& rnY
, const sal_uInt16 aTol
) const
1166 if( !mpImpl
.is() || !mpImpl
->mxTable
.is() )
1167 return TableHitKind::NONE
;
1172 const sal_Int32 nColCount
= mpImpl
->getColumnCount();
1173 const sal_Int32 nRowCount
= mpImpl
->getRowCount();
1175 sal_Int32 nX
= rPos
.X() - getRectangle().Left();
1176 sal_Int32 nY
= rPos
.Y() - getRectangle().Top();
1178 if( (nX
< 0) || (nX
> getRectangle().GetWidth()) || (nY
< 0) || (nY
> getRectangle().GetHeight() ) )
1179 return TableHitKind::NONE
;
1181 // get vertical edge number and check for a hit
1182 const bool bRTL
= (GetWritingMode() == WritingMode_RL_TB
);
1183 bool bVrtHit
= false;
1186 while( rnX
<= nColCount
)
1188 if( nX
- aTol
<= 0 )
1194 if( rnX
== nColCount
)
1197 nX
-= mpImpl
->mpLayouter
->getColumnWidth( rnX
);
1208 if( nX
- aTol
<= 0 )
1218 nX
-= mpImpl
->mpLayouter
->getColumnWidth( rnX
);
1224 // rnX is now the edge number left to the pointer, if it was hit bHrzHit is also true
1226 // get vertical edge number and check for a hit
1227 bool bHrzHit
= false;
1228 while( rnY
<= nRowCount
)
1230 if( nY
- aTol
<= 0 )
1236 if( rnY
== nRowCount
)
1239 nY
-= mpImpl
->mpLayouter
->getRowHeight(rnY
);
1245 // rnY is now the edge number above the pointer, if it was hit bVrtHit is also true
1247 if( bVrtHit
&& mpImpl
->mpLayouter
->isEdgeVisible( rnX
, rnY
, false ) )
1248 return TableHitKind::VerticallBorder
;
1250 if( bHrzHit
&& mpImpl
->mpLayouter
->isEdgeVisible( rnX
, rnY
, true ) )
1251 return TableHitKind::HorizontalBorder
;
1253 CellRef
xCell( mpImpl
->getCell( CellPos( rnX
, rnY
) ) );
1254 if( xCell
.is() && xCell
->isMerged() )
1255 findMergeOrigin( mpImpl
->mxTable
, rnX
, rnY
, rnX
, rnY
);
1259 nX
+= mpImpl
->mpLayouter
->getColumnWidth( rnX
);
1260 //Fix for fdo#62673 : non-editable cell in table on cell merge
1262 while(xCell
.is() && xCell
->isMerged())
1264 nX
+= mpImpl
->mpLayouter
->getColumnWidth( rnX
+i
);
1266 if(rnX
+i
< nColCount
)
1267 xCell
=mpImpl
->getCell( CellPos( rnX
+i
, rnY
) );
1272 if( nX
< xCell
->GetTextLeftDistance() )
1273 return TableHitKind::Cell
;
1276 return TableHitKind::CellTextArea
;
1279 const SfxItemSet
& SdrTableObj::GetActiveCellItemSet() const
1281 return getActiveCell()->GetItemSet();
1284 void SdrTableObj::setTableStyle( const Reference
< XIndexAccess
>& xTableStyle
)
1286 if( mpImpl
.is() && (mpImpl
->mxTableStyle
!= xTableStyle
) )
1288 mpImpl
->disconnectTableStyle();
1289 mpImpl
->mxTableStyle
= xTableStyle
;
1290 mpImpl
->connectTableStyle();
1296 const Reference
< XIndexAccess
>& SdrTableObj::getTableStyle() const
1300 return mpImpl
->mxTableStyle
;
1304 static Reference
< XIndexAccess
> aTmp
;
1313 /** returns the currently active text. */
1314 SdrText
* SdrTableObj::getActiveText() const
1316 return getActiveCell().get();
1320 /** returns the nth available text. */
1321 SdrText
* SdrTableObj::getText( sal_Int32 nIndex
) const
1323 if( mpImpl
->mxTable
.is() )
1325 const sal_Int32 nColCount
= mpImpl
->getColumnCount();
1328 CellPos
aPos( nIndex
% nColCount
, nIndex
/ nColCount
);
1330 CellRef
xCell( mpImpl
->getCell( aPos
) );
1338 /** returns the number of texts available for this object. */
1339 sal_Int32
SdrTableObj::getTextCount() const
1341 if( mpImpl
->mxTable
.is() )
1343 const sal_Int32 nColCount
= mpImpl
->getColumnCount();
1344 const sal_Int32 nRowCount
= mpImpl
->getRowCount();
1346 return nColCount
* nRowCount
;
1355 /** changes the current active text */
1356 void SdrTableObj::setActiveText( sal_Int32 nIndex
)
1358 if( mpImpl
.is() && mpImpl
->mxTable
.is() )
1360 const sal_Int32 nColCount
= mpImpl
->mxTable
->getColumnCount();
1363 CellPos
aPos( nIndex
% nColCount
, nIndex
/ nColCount
);
1364 if( isValid( aPos
) )
1365 setActiveCell( aPos
);
1371 /** returns the index of the text that contains the given point or -1 */
1372 sal_Int32
SdrTableObj::CheckTextHit(const Point
& rPnt
) const
1374 if( mpImpl
.is() && mpImpl
->mxTable
.is() )
1377 if( CheckTableHit( rPnt
, aPos
.mnCol
, aPos
.mnRow
) == TableHitKind::CellTextArea
)
1378 return aPos
.mnRow
* mpImpl
->mxTable
->getColumnCount() + aPos
.mnCol
;
1384 SdrOutliner
* SdrTableObj::GetCellTextEditOutliner( const Cell
& rCell
) const
1386 if( mpImpl
.is() && (mpImpl
->getCell( mpImpl
->maEditPos
).get() == &rCell
) )
1387 return mpEditingOutliner
;
1392 const TableLayouter
& SdrTableObj::getTableLayouter() const
1394 assert(mpImpl
.is() && mpImpl
->mpLayouter
&& "getTableLayouter() error: no mpImpl or mpLayouter (!)");
1395 return *(mpImpl
->mpLayouter
);
1398 bool SdrTableObj::IsAutoGrowHeight() const
1403 bool SdrTableObj::IsAutoGrowWidth() const
1408 bool SdrTableObj::HasText() const
1413 bool SdrTableObj::IsTextEditActive( const CellPos
& rPos
)
1415 return mpEditingOutliner
&& mpImpl
.is() && (rPos
== mpImpl
->maEditPos
);
1419 void SdrTableObj::onEditOutlinerStatusEvent( EditStatus
* pEditStatus
)
1421 if( (pEditStatus
->GetStatusWord() & EditStatusFlags::TextHeightChanged
) && mpImpl
.is() && mpImpl
->mpLayouter
)
1423 tools::Rectangle
aRect0(getRectangle());
1424 setRectangle(maLogicRect
);
1425 auto aRectangle
= getRectangle();
1426 mpImpl
->LayoutTable(aRectangle
, false, false);
1427 setRectangle(aRectangle
);
1428 SetBoundAndSnapRectsDirty();
1430 BroadcastObjectChange();
1431 if (aRect0
!= getRectangle())
1432 SendUserCall(SdrUserCallType::Resize
,aRect0
);
1437 void SdrTableObj::TakeObjInfo(SdrObjTransformInfoRec
& rInfo
) const
1439 rInfo
.bResizeFreeAllowed
=true;
1440 rInfo
.bResizePropAllowed
=true;
1441 rInfo
.bRotateFreeAllowed
=false;
1442 rInfo
.bRotate90Allowed
=false;
1443 rInfo
.bMirrorFreeAllowed
=false;
1444 rInfo
.bMirror45Allowed
=false;
1445 rInfo
.bMirror90Allowed
=false;
1447 // allow transparence
1448 rInfo
.bTransparenceAllowed
= true;
1450 rInfo
.bShearAllowed
=false;
1451 rInfo
.bEdgeRadiusAllowed
=false;
1452 rInfo
.bCanConvToPath
=false;
1453 rInfo
.bCanConvToPoly
=false;
1454 rInfo
.bCanConvToPathLineToArea
=false;
1455 rInfo
.bCanConvToPolyLineToArea
=false;
1456 rInfo
.bCanConvToContour
= false;
1459 SdrObjKind
SdrTableObj::GetObjIdentifier() const
1461 return SdrObjKind::Table
;
1464 void SdrTableObj::TakeTextRect( SdrOutliner
& rOutliner
, tools::Rectangle
& rTextRect
, bool bNoEditText
, tools::Rectangle
* pAnchorRect
, bool /*bLineWidth*/ ) const
1467 TakeTextRect( mpImpl
->maEditPos
, rOutliner
, rTextRect
, bNoEditText
, pAnchorRect
);
1471 void SdrTableObj::TakeTextRect( const CellPos
& rPos
, SdrOutliner
& rOutliner
, tools::Rectangle
& rTextRect
, bool bNoEditText
, tools::Rectangle
* pAnchorRect
) const
1476 CellRef
xCell( mpImpl
->getCell( rPos
) );
1480 tools::Rectangle aAnkRect
;
1481 TakeTextAnchorRect( rPos
, aAnkRect
);
1483 SdrTextVertAdjust eVAdj
=xCell
->GetTextVerticalAdjust();
1485 EEControlBits nStat0
=rOutliner
.GetControlWord();
1486 nStat0
|= EEControlBits::AUTOPAGESIZE
;
1487 rOutliner
.SetControlWord(nStat0
);
1488 rOutliner
.SetMinAutoPaperSize(Size());
1489 rOutliner
.SetMaxAutoPaperSize(aAnkRect
.GetSize());
1490 rOutliner
.SetPaperSize(aAnkRect
.GetSize());
1492 // #103516# New try with _BLOCK for hor and ver after completely
1493 // supporting full width for vertical text.
1494 // if( SDRTEXTHORZADJUST_BLOCK == eHAdj && !IsVerticalWriting())
1496 rOutliner
.SetMinAutoPaperSize(Size(aAnkRect
.GetWidth(), 0));
1498 // else if(SDRTEXTVERTADJUST_BLOCK == eVAdj && IsVerticalWriting())
1500 // rOutliner.SetMinAutoPaperSize(Size(0, aAnkRect.GetHeight()));
1504 // set text at outliner, maybe from edit outliner
1505 std::optional
<OutlinerParaObject
> pPara
;
1506 if (xCell
->GetOutlinerParaObject())
1507 pPara
= *xCell
->GetOutlinerParaObject();
1508 if (mpEditingOutliner
&& !bNoEditText
&& mpImpl
->mxActiveCell
== xCell
)
1509 pPara
= mpEditingOutliner
->CreateParaObject();
1513 const bool bHitTest(&getSdrModelFromSdrObject().GetHitTestOutliner() == &rOutliner
);
1514 const SdrTextObj
* pTestObj(rOutliner
.GetTextObj());
1516 if( !pTestObj
|| !bHitTest
|| (pTestObj
!= this) || (pTestObj
->GetOutlinerParaObject() != xCell
->GetOutlinerParaObject()) )
1518 if( bHitTest
) // #i33696# take back fix #i27510#
1519 rOutliner
.SetTextObj( this );
1521 rOutliner
.SetUpdateLayout(true);
1522 rOutliner
.SetText(*pPara
);
1527 rOutliner
.SetTextObj( nullptr );
1530 rOutliner
.SetUpdateLayout(true);
1531 rOutliner
.SetControlWord(nStat0
);
1533 Point
aTextPos(aAnkRect
.TopLeft());
1534 Size
aTextSiz(rOutliner
.GetPaperSize());
1535 if (eVAdj
==SDRTEXTVERTADJUST_CENTER
|| eVAdj
==SDRTEXTVERTADJUST_BOTTOM
)
1537 tools::Long nFreeHgt
=aAnkRect
.GetHeight()-aTextSiz
.Height();
1538 if (eVAdj
==SDRTEXTVERTADJUST_CENTER
)
1539 aTextPos
.AdjustY(nFreeHgt
/2 );
1540 if (eVAdj
==SDRTEXTVERTADJUST_BOTTOM
)
1541 aTextPos
.AdjustY(nFreeHgt
);
1545 *pAnchorRect
=aAnkRect
;
1547 rTextRect
=tools::Rectangle(aTextPos
,aTextSiz
);
1550 const CellRef
& SdrTableObj::getActiveCell() const
1554 if( !mpImpl
->mxActiveCell
.is() )
1557 const_cast< SdrTableObj
* >(this)->setActiveCell( aPos
);
1559 return mpImpl
->mxActiveCell
;
1563 static CellRef xCell
;
1569 sal_Int32
SdrTableObj::getColumnCount() const
1571 return mpImpl
.is() ? mpImpl
->getColumnCount() : 0;
1574 sal_Int32
SdrTableObj::getRowCount() const
1576 return mpImpl
.is() ? mpImpl
->getRowCount() : 0;
1579 void SdrTableObj::changeEdge(bool bHorizontal
, int nEdge
, sal_Int32 nOffset
)
1582 mpImpl
->DragEdge(bHorizontal
, nEdge
, nOffset
);
1585 void SdrTableObj::setActiveCell( const CellPos
& rPos
)
1587 if( !(mpImpl
.is() && mpImpl
->mxTable
.is()) )
1592 mpImpl
->mxActiveCell
= mpImpl
->mxTable
->getCell( rPos
.mnCol
, rPos
.mnRow
);
1593 if( mpImpl
->mxActiveCell
.is() && mpImpl
->mxActiveCell
->isMerged() )
1596 findMergeOrigin( mpImpl
->mxTable
, rPos
.mnCol
, rPos
.mnRow
, aOrigin
.mnCol
, aOrigin
.mnRow
);
1597 mpImpl
->mxActiveCell
= mpImpl
->mxTable
->getCell( aOrigin
.mnCol
, aOrigin
.mnRow
);
1598 mpImpl
->maEditPos
= aOrigin
;
1602 mpImpl
->maEditPos
= rPos
;
1607 TOOLS_WARN_EXCEPTION("svx.table", "");
1612 void SdrTableObj::getActiveCellPos( CellPos
& rPos
) const
1614 rPos
= mpImpl
->maEditPos
;
1618 void SdrTableObj::getCellBounds( const CellPos
& rPos
, ::tools::Rectangle
& rCellRect
)
1622 CellRef
xCell( mpImpl
->getCell( rPos
) );
1624 rCellRect
= xCell
->getCellRect();
1629 void SdrTableObj::TakeTextAnchorRect(tools::Rectangle
& rAnchorRect
) const
1632 TakeTextAnchorRect( mpImpl
->maEditPos
, rAnchorRect
);
1636 void SdrTableObj::TakeTextAnchorRect( const CellPos
& rPos
, tools::Rectangle
& rAnchorRect
) const
1638 tools::Rectangle
aAnkRect(getRectangle());
1642 CellRef
xCell( mpImpl
->getCell( rPos
) );
1644 xCell
->TakeTextAnchorRect( aAnkRect
);
1647 ImpJustifyRect(aAnkRect
);
1648 rAnchorRect
=aAnkRect
;
1652 void SdrTableObj::TakeTextEditArea(Size
* pPaperMin
, Size
* pPaperMax
, tools::Rectangle
* pViewInit
, tools::Rectangle
* pViewMin
) const
1655 TakeTextEditArea( mpImpl
->maEditPos
, pPaperMin
, pPaperMax
, pViewInit
, pViewMin
);
1659 void SdrTableObj::TakeTextEditArea( const CellPos
& rPos
, Size
* pPaperMin
, Size
* pPaperMax
, tools::Rectangle
* pViewInit
, tools::Rectangle
* pViewMin
) const
1661 Size aPaperMin
,aPaperMax
;
1662 tools::Rectangle aViewInit
;
1663 TakeTextAnchorRect( rPos
, aViewInit
);
1665 Size
aAnkSiz(aViewInit
.GetSize());
1666 aAnkSiz
.AdjustWidth( -1 ); aAnkSiz
.AdjustHeight( -1 ); // because GetSize() increments by one
1668 Size
aMaxSiz(aAnkSiz
.Width(),1000000);
1669 Size
aTmpSiz(getSdrModelFromSdrObject().GetMaxObjSize());
1670 if (aTmpSiz
.Height()!=0)
1671 aMaxSiz
.setHeight(aTmpSiz
.Height() );
1673 CellRef
xCell( mpImpl
->getCell( rPos
) );
1674 SdrTextVertAdjust eVAdj
= xCell
.is() ? xCell
->GetTextVerticalAdjust() : SDRTEXTVERTADJUST_TOP
;
1678 aPaperMin
.setWidth( aAnkSiz
.Width() );
1680 if (pViewMin
!=nullptr)
1682 *pViewMin
=aViewInit
;
1683 tools::Long nYFree
=aAnkSiz
.Height()-aPaperMin
.Height();
1685 if (eVAdj
==SDRTEXTVERTADJUST_TOP
)
1687 pViewMin
->AdjustBottom( -nYFree
);
1689 else if (eVAdj
==SDRTEXTVERTADJUST_BOTTOM
)
1691 pViewMin
->AdjustTop(nYFree
);
1695 pViewMin
->AdjustTop(nYFree
/2 );
1696 pViewMin
->SetBottom(pViewMin
->Top()+aPaperMin
.Height() );
1701 if(IsVerticalWriting())
1702 aPaperMin
.setWidth( 0 );
1704 aPaperMin
.setHeight( 0 );
1706 if (pPaperMin
!=nullptr) *pPaperMin
=aPaperMin
;
1707 if (pPaperMax
!=nullptr) *pPaperMax
=aPaperMax
;
1708 if (pViewInit
!=nullptr) *pViewInit
=aViewInit
;
1712 EEAnchorMode
SdrTableObj::GetOutlinerViewAnchorMode() const
1714 EEAnchorMode eRet
=EEAnchorMode::TopLeft
;
1715 CellRef
xCell( getActiveCell() );
1718 SdrTextVertAdjust eV
=xCell
->GetTextVerticalAdjust();
1721 if (eV
==SDRTEXTVERTADJUST_TOP
)
1723 eRet
=EEAnchorMode::TopLeft
;
1725 else if (eV
==SDRTEXTVERTADJUST_BOTTOM
)
1727 eRet
=EEAnchorMode::BottomLeft
;
1731 eRet
=EEAnchorMode::VCenterLeft
;
1739 OUString
SdrTableObj::TakeObjNameSingul() const
1741 OUString
sName(SvxResId(STR_ObjNameSingulTable
));
1743 OUString
aName(GetName());
1744 if (!aName
.isEmpty())
1745 sName
+= " '" + aName
+ "'";
1751 OUString
SdrTableObj::TakeObjNamePlural() const
1753 return SvxResId(STR_ObjNamePluralTable
);
1757 rtl::Reference
<SdrObject
> SdrTableObj::CloneSdrObject(SdrModel
& rTargetModel
) const
1759 return new SdrTableObj(rTargetModel
, *this);
1763 const tools::Rectangle
& SdrTableObj::GetSnapRect() const
1765 return getRectangle();
1769 void SdrTableObj::NbcSetSnapRect(const tools::Rectangle
& rRect
)
1771 NbcSetLogicRect( rRect
);
1775 const tools::Rectangle
& SdrTableObj::GetLogicRect() const
1781 void SdrTableObj::RecalcSnapRect()
1786 bool SdrTableObj::BegTextEdit(SdrOutliner
& rOutl
)
1788 if( mpEditingOutliner
!= nullptr )
1791 mpEditingOutliner
=&rOutl
;
1793 mbInEditMode
= true;
1795 rOutl
.Init( OutlinerMode::TextObject
);
1796 rOutl
.SetRefDevice(getSdrModelFromSdrObject().GetRefDevice());
1798 bool bUpdateMode
= rOutl
.SetUpdateLayout(false);
1801 tools::Rectangle aEditArea
;
1802 TakeTextEditArea(&aPaperMin
,&aPaperMax
,&aEditArea
,nullptr);
1804 rOutl
.SetMinAutoPaperSize(aPaperMin
);
1805 rOutl
.SetMaxAutoPaperSize(aPaperMax
);
1806 rOutl
.SetPaperSize(aPaperMax
);
1808 if (bUpdateMode
) rOutl
.SetUpdateLayout(true);
1810 EEControlBits nStat
=rOutl
.GetControlWord();
1811 nStat
|= EEControlBits::AUTOPAGESIZE
;
1812 nStat
&=~EEControlBits::STRETCHING
;
1813 rOutl
.SetControlWord(nStat
);
1815 OutlinerParaObject
* pPara
= GetOutlinerParaObject();
1817 rOutl
.SetText(*pPara
);
1819 rOutl
.UpdateFields();
1820 rOutl
.ClearModifyFlag();
1826 void SdrTableObj::EndTextEdit(SdrOutliner
& rOutl
)
1829 if (getSdrModelFromSdrObject().IsUndoEnabled() && !mpImpl
->maUndos
.empty())
1831 // These actions should be on the undo stack after text edit.
1832 for (std::unique_ptr
<SdrUndoAction
>& pAction
: mpImpl
->maUndos
)
1833 getSdrModelFromSdrObject().AddUndo( std::move(pAction
));
1834 mpImpl
->maUndos
.clear();
1836 getSdrModelFromSdrObject().AddUndo(getSdrModelFromSdrObject().GetSdrUndoFactory().CreateUndoGeoObject(*this));
1839 if(rOutl
.IsModified())
1841 std::optional
<OutlinerParaObject
> pNewText
;
1842 Paragraph
* p1stPara
= rOutl
.GetParagraph( 0 );
1843 sal_Int32 nParaCnt
= rOutl
.GetParagraphCount();
1847 // to remove the grey field background
1848 rOutl
.UpdateFields();
1850 // create new text object
1851 pNewText
= rOutl
.CreateParaObject( 0, nParaCnt
);
1853 SetOutlinerParaObject(std::move(pNewText
));
1856 mpEditingOutliner
= nullptr;
1858 EEControlBits nStat
= rOutl
.GetControlWord();
1859 nStat
&= ~EEControlBits::AUTOPAGESIZE
;
1860 rOutl
.SetControlWord(nStat
);
1862 mbInEditMode
= false;
1866 OutlinerParaObject
* SdrTableObj::GetOutlinerParaObject() const
1868 CellRef
xCell( getActiveCell() );
1870 return xCell
->GetOutlinerParaObject();
1876 void SdrTableObj::NbcSetOutlinerParaObject( std::optional
<OutlinerParaObject
> pTextObject
, bool bAdjustTextFrameWidthAndHeight
)
1878 CellRef
xCell( getActiveCell() );
1882 // Update HitTestOutliner
1883 const SdrTextObj
* pTestObj(getSdrModelFromSdrObject().GetHitTestOutliner().GetTextObj());
1885 if(pTestObj
&& pTestObj
->GetOutlinerParaObject() == xCell
->GetOutlinerParaObject())
1887 getSdrModelFromSdrObject().GetHitTestOutliner().SetTextObj(nullptr);
1890 xCell
->SetOutlinerParaObject( std::move(pTextObject
) );
1892 if (bAdjustTextFrameWidthAndHeight
)
1893 NbcAdjustTextFrameWidthAndHeight();
1897 void SdrTableObj::NbcSetLogicRect(const tools::Rectangle
& rRect
, bool /*bAdaptTextMinSize*/)
1900 ImpJustifyRect(maLogicRect
);
1901 const bool bWidth
= maLogicRect
.getOpenWidth() != getRectangle().getOpenWidth();
1902 const bool bHeight
= maLogicRect
.getOpenHeight() != getRectangle().getOpenHeight();
1903 setRectangle(maLogicRect
);
1904 if (mpImpl
->mbSkipChangeLayout
)
1905 // Avoid distributing newly available space between existing cells.
1906 NbcAdjustTextFrameWidthAndHeight();
1908 NbcAdjustTextFrameWidthAndHeight(!bHeight
, !bWidth
);
1909 SetBoundAndSnapRectsDirty();
1913 void SdrTableObj::AdjustToMaxRect( const tools::Rectangle
& rMaxRect
, bool /* bShrinkOnly = false */ )
1915 tools::Rectangle
aAdjustRect( rMaxRect
);
1916 aAdjustRect
.setHeight( GetLogicRect().getOpenHeight() );
1917 SetLogicRect( aAdjustRect
);
1921 void SdrTableObj::NbcMove(const Size
& rSiz
)
1923 maLogicRect
.Move(rSiz
);
1924 SdrTextObj::NbcMove( rSiz
);
1926 mpImpl
->UpdateCells(getRectangle());
1930 void SdrTableObj::NbcResize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
1932 tools::Rectangle
aOldRect( maLogicRect
);
1933 ResizeRect(maLogicRect
,rRef
,xFact
,yFact
);
1935 setRectangle(maLogicRect
);
1936 NbcAdjustTextFrameWidthAndHeight( maLogicRect
.GetHeight() == aOldRect
.GetHeight(), maLogicRect
.GetWidth() == aOldRect
.GetWidth() );
1937 SetBoundAndSnapRectsDirty();
1941 bool SdrTableObj::AdjustTextFrameWidthAndHeight()
1943 tools::Rectangle
aNewRect(maLogicRect
);
1944 bool bRet
=AdjustTextFrameWidthAndHeight(aNewRect
);
1947 tools::Rectangle aBoundRect0
;
1948 if (m_pUserCall
!=nullptr)
1949 aBoundRect0
=GetLastBoundRect();
1950 setRectangle(aNewRect
);
1951 SetBoundAndSnapRectsDirty();
1953 BroadcastObjectChange();
1954 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
1960 bool SdrTableObj::AdjustTextFrameWidthAndHeight(tools::Rectangle
& rR
, bool bHeight
, bool bWidth
) const
1962 if(rR
.IsEmpty() || !mpImpl
.is() || !mpImpl
->mxTable
.is())
1965 tools::Rectangle
aRectangle( rR
);
1966 mpImpl
->LayoutTable( aRectangle
, !bWidth
, !bHeight
);
1968 if( aRectangle
!= rR
)
1980 void SdrTableObj::NbcReformatText()
1982 NbcAdjustTextFrameWidthAndHeight();
1986 bool SdrTableObj::IsVerticalWriting() const
1988 const SvxWritingModeItem
& rModeItem
= GetObjectItem( SDRATTR_TEXTDIRECTION
);
1989 return rModeItem
.GetValue() == css::text::WritingMode_TB_RL
;
1993 void SdrTableObj::SetVerticalWriting(bool bVertical
)
1995 if(bVertical
!= IsVerticalWriting() )
1997 SvxWritingModeItem
aModeItem( css::text::WritingMode_LR_TB
, SDRATTR_TEXTDIRECTION
);
1998 SetObjectItem( aModeItem
);
2003 WritingMode
SdrTableObj::GetWritingMode() const
2005 SfxStyleSheet
* pStyle
= GetStyleSheet();
2007 return WritingMode_LR_TB
;
2009 WritingMode eWritingMode
= WritingMode_LR_TB
;
2010 const SfxItemSet
&rSet
= pStyle
->GetItemSet();
2012 if ( const SvxWritingModeItem
*pItem
= rSet
.GetItemIfSet( SDRATTR_TEXTDIRECTION
))
2013 eWritingMode
= pItem
->GetValue();
2015 if ( const SvxFrameDirectionItem
*pItem
;
2016 ( eWritingMode
!= WritingMode_TB_RL
) &&
2017 ( pItem
= rSet
.GetItemIfSet( EE_PARA_WRITINGDIR
, false ) ) )
2019 if ( pItem
->GetValue() == SvxFrameDirection::Horizontal_LR_TB
)
2020 eWritingMode
= WritingMode_LR_TB
;
2022 eWritingMode
= WritingMode_RL_TB
;
2025 return eWritingMode
;
2028 void SdrTableObj::AddUndo(SdrUndoAction
* pUndo
)
2030 mpImpl
->maUndos
.push_back(std::unique_ptr
<SdrUndoAction
>(pUndo
));
2033 void SdrTableObj::SetSkipChangeLayout(bool bSkipChangeLayout
)
2035 mpImpl
->mbSkipChangeLayout
= bSkipChangeLayout
;
2038 bool SdrTableObj::IsReallyEdited() const
2040 return mpEditingOutliner
&& mpEditingOutliner
->IsModified();
2043 bool SdrTableObj::IsFontwork() const
2048 sal_uInt32
SdrTableObj::GetHdlCount() const
2050 sal_uInt32 nCount
= SdrTextObj::GetHdlCount();
2051 const sal_Int32 nRowCount
= mpImpl
->getRowCount();
2052 const sal_Int32 nColCount
= mpImpl
->getColumnCount();
2054 if( nRowCount
&& nColCount
)
2055 nCount
+= nRowCount
+ nColCount
+ 2 + 1;
2060 void SdrTableObj::AddToHdlList(SdrHdlList
& rHdlList
) const
2062 const sal_Int32 nRowCount
= mpImpl
->getRowCount();
2063 const sal_Int32 nColCount
= mpImpl
->getColumnCount();
2065 // first add row handles
2066 std::vector
<TableEdgeHdl
*> aRowEdges(nRowCount
+ 1);
2067 for (auto const & rEdge
: mpImpl
->mpLayouter
->getHorizontalEdges())
2069 Point
aPoint(getRectangle().TopLeft());
2070 aPoint
.AdjustY(rEdge
.nPosition
);
2072 std::unique_ptr
<TableEdgeHdl
> pHdl(new TableEdgeHdl(aPoint
, true, rEdge
.nMin
, rEdge
.nMax
, nColCount
+ 1));
2073 pHdl
->SetPointNum(rEdge
.nIndex
);
2074 aRowEdges
[rEdge
.nIndex
] = pHdl
.get();
2075 rHdlList
.AddHdl(std::move(pHdl
));
2078 // second add column handles
2079 std::vector
<TableEdgeHdl
*> aColEdges(nColCount
+ 1);
2080 for (auto const & rEdge
: mpImpl
->mpLayouter
->getVerticalEdges())
2082 Point
aPoint(getRectangle().TopLeft());
2083 aPoint
.AdjustX(rEdge
.nPosition
);
2085 std::unique_ptr
<TableEdgeHdl
> pHdl(new TableEdgeHdl(aPoint
, false, rEdge
.nMin
, rEdge
.nMax
, nRowCount
+ 1));
2086 pHdl
->SetPointNum(rEdge
.nIndex
);
2087 aColEdges
[rEdge
.nIndex
] = pHdl
.get();
2088 rHdlList
.AddHdl(std::move(pHdl
));
2091 // now add visible edges to row and column handles
2092 if( mpImpl
->mpLayouter
)
2094 TableLayouter
& rLayouter
= *mpImpl
->mpLayouter
;
2098 for( sal_Int32 nRow
= 0; nRow
<= nRowCount
; ++nRow
)
2100 const sal_Int32 nRowHeight
= (nRow
== nRowCount
) ? 0 : rLayouter
.getRowHeight(nRow
);
2103 for( sal_Int32 nCol
= 0; nCol
<= nColCount
; ++nCol
)
2105 const sal_Int32 nColWidth
= (nCol
== nColCount
) ? 0 : rLayouter
.getColumnWidth(nCol
);
2107 if( nRowHeight
> 0 )
2109 if( rLayouter
.isEdgeVisible( nCol
, nRow
, false ) )
2110 aColEdges
[nCol
]->SetEdge( nRow
, nY
, nY
+ nRowHeight
, (rLayouter
.getBorderLine( nCol
, nRow
, false ) == nullptr) ? Visible
: Invisible
);
2115 if( rLayouter
.isEdgeVisible( nCol
, nRow
, true ) )
2116 aRowEdges
[nRow
]->SetEdge( nCol
, nX
, nX
+ nColWidth
, (rLayouter
.getBorderLine( nCol
, nRow
, true ) == nullptr) ? Visible
: Invisible
);
2126 // add remaining handles
2127 SdrHdlList
tempList(nullptr);
2128 auto aRectangle
= getRectangle();
2129 tempList
.AddHdl( std::make_unique
<TableBorderHdl
>(aRectangle
, !IsTextEditActive() ) );
2130 tempList
.AddHdl( std::make_unique
<SdrHdl
>(aRectangle
.TopLeft(),SdrHdlKind::UpperLeft
) );
2131 tempList
.AddHdl( std::make_unique
<SdrHdl
>(aRectangle
.TopCenter(),SdrHdlKind::Upper
) );
2132 tempList
.AddHdl( std::make_unique
<SdrHdl
>(aRectangle
.TopRight(),SdrHdlKind::UpperRight
) );
2133 tempList
.AddHdl( std::make_unique
<SdrHdl
>(aRectangle
.LeftCenter(),SdrHdlKind::Left
) );
2134 tempList
.AddHdl( std::make_unique
<SdrHdl
>(aRectangle
.RightCenter(),SdrHdlKind::Right
) );
2135 tempList
.AddHdl( std::make_unique
<SdrHdl
>(aRectangle
.BottomLeft(),SdrHdlKind::LowerLeft
) );
2136 tempList
.AddHdl( std::make_unique
<SdrHdl
>(aRectangle
.BottomCenter(),SdrHdlKind::Lower
) );
2137 tempList
.AddHdl( std::make_unique
<SdrHdl
>(aRectangle
.BottomRight(),SdrHdlKind::LowerRight
) );
2138 for( size_t nHdl
= 0; nHdl
< tempList
.GetHdlCount(); ++nHdl
)
2139 tempList
.GetHdl(nHdl
)->SetMoveOutside(true);
2140 tempList
.MoveTo(rHdlList
);
2142 const size_t nHdlCount
= rHdlList
.GetHdlCount();
2143 for( size_t nHdl
= 0; nHdl
< nHdlCount
; ++nHdl
)
2144 rHdlList
.GetHdl(nHdl
)->SetObj(const_cast<SdrTableObj
*>(this));
2149 bool SdrTableObj::hasSpecialDrag() const
2154 bool SdrTableObj::beginSpecialDrag(SdrDragStat
& rDrag
) const
2156 const SdrHdl
* pHdl
= rDrag
.GetHdl();
2157 const SdrHdlKind
eHdl((pHdl
== nullptr) ? SdrHdlKind::Move
: pHdl
->GetKind());
2161 case SdrHdlKind::UpperLeft
:
2162 case SdrHdlKind::Upper
:
2163 case SdrHdlKind::UpperRight
:
2164 case SdrHdlKind::Left
:
2165 case SdrHdlKind::Right
:
2166 case SdrHdlKind::LowerLeft
:
2167 case SdrHdlKind::Lower
:
2168 case SdrHdlKind::LowerRight
:
2169 case SdrHdlKind::Move
:
2174 case SdrHdlKind::User
:
2176 rDrag
.SetEndDragChangesAttributes(false);
2190 bool SdrTableObj::applySpecialDrag(SdrDragStat
& rDrag
)
2193 const SdrHdl
* pHdl
= rDrag
.GetHdl();
2194 const SdrHdlKind
eHdl((pHdl
== nullptr) ? SdrHdlKind::Move
: pHdl
->GetKind());
2198 case SdrHdlKind::UpperLeft
:
2199 case SdrHdlKind::Upper
:
2200 case SdrHdlKind::UpperRight
:
2201 case SdrHdlKind::Left
:
2202 case SdrHdlKind::Right
:
2203 case SdrHdlKind::LowerLeft
:
2204 case SdrHdlKind::Lower
:
2205 case SdrHdlKind::LowerRight
:
2207 const tools::Rectangle
aNewRectangle(ImpDragCalcRect(rDrag
));
2209 if (aNewRectangle
!= getRectangle())
2211 NbcSetLogicRect(aNewRectangle
);
2217 case SdrHdlKind::Move
:
2219 NbcMove( Size( rDrag
.GetDX(), rDrag
.GetDY() ) );
2223 case SdrHdlKind::User
:
2225 rDrag
.SetEndDragChangesAttributes(false);
2227 const TableEdgeHdl
* pEdgeHdl
= dynamic_cast< const TableEdgeHdl
* >( pHdl
);
2233 rDrag
.SetEndDragChangesAttributes(true);
2234 rDrag
.SetEndDragChangesLayout(true);
2237 mpImpl
->DragEdge( pEdgeHdl
->IsHorizontalEdge(), pEdgeHdl
->GetPointNum(), pEdgeHdl
->GetValidDragOffset( rDrag
) );
2251 basegfx::B2DPolyPolygon
SdrTableObj::getSpecialDragPoly(const SdrDragStat
& rDrag
) const
2253 basegfx::B2DPolyPolygon aRetval
;
2254 const SdrHdl
* pHdl
= rDrag
.GetHdl();
2256 if( pHdl
&& (SdrHdlKind::User
== pHdl
->GetKind()) )
2258 const TableEdgeHdl
* pEdgeHdl
= dynamic_cast< const TableEdgeHdl
* >( pHdl
);
2262 aRetval
= pEdgeHdl
->getSpecialDragPoly( rDrag
);
2273 bool SdrTableObj::BegCreate(SdrDragStat
& rStat
)
2275 rStat
.SetOrtho4Possible();
2276 tools::Rectangle
aRect1(rStat
.GetStart(), rStat
.GetNow());
2278 rStat
.SetActionRect(aRect1
);
2279 setRectangle(aRect1
);
2284 bool SdrTableObj::MovCreate(SdrDragStat
& rStat
)
2286 tools::Rectangle aRect1
;
2287 rStat
.TakeCreateRect(aRect1
);
2288 ImpJustifyRect(aRect1
);
2289 rStat
.SetActionRect(aRect1
);
2290 setRectangle(aRect1
); // for ObjName
2291 SetBoundRectDirty();
2292 m_bSnapRectDirty
=true;
2297 bool SdrTableObj::EndCreate(SdrDragStat
& rStat
, SdrCreateCmd eCmd
)
2299 auto aRectangle
= getRectangle();
2300 rStat
.TakeCreateRect(aRectangle
);
2301 ImpJustifyRect(aRectangle
);
2302 setRectangle(aRectangle
);
2303 return (eCmd
==SdrCreateCmd::ForceEnd
|| rStat
.GetPointCount()>=2);
2306 void SdrTableObj::BrkCreate(SdrDragStat
& /*rStat*/)
2311 bool SdrTableObj::BckCreate(SdrDragStat
& /*rStat*/)
2317 basegfx::B2DPolyPolygon
SdrTableObj::TakeCreatePoly(const SdrDragStat
& rDrag
) const
2319 tools::Rectangle aRect1
;
2320 rDrag
.TakeCreateRect(aRect1
);
2323 basegfx::B2DPolyPolygon aRetval
;
2324 const basegfx::B2DRange aRange
= vcl::unotools::b2DRectangleFromRectangle(aRect1
);
2325 aRetval
.append(basegfx::utils::createPolygonFromRect(aRange
));
2330 PointerStyle
SdrTableObj::GetCreatePointer() const
2332 return PointerStyle::Cross
;
2336 void SdrTableObj::createCell( CellRef
& xNewCell
)
2338 xNewCell
= Cell::create( *this );
2342 std::unique_ptr
<SdrObjGeoData
> SdrTableObj::NewGeoData() const
2344 return std::make_unique
<TableObjectGeoData
>();
2348 void SdrTableObj::SaveGeoData(SdrObjGeoData
& rGeo
) const
2350 DBG_ASSERT( dynamic_cast< TableObjectGeoData
* >( &rGeo
), "svx::SdrTableObj::SaveGeoData(), illegal geo data!" );
2351 SdrTextObj::SaveGeoData (rGeo
);
2353 static_cast<TableObjectGeoData
&>(rGeo
).maLogicRect
= maLogicRect
;
2357 void SdrTableObj::RestoreGeoData(const SdrObjGeoData
& rGeo
)
2359 DBG_ASSERT( dynamic_cast< const TableObjectGeoData
* >( &rGeo
), "svx::SdrTableObj::RestoreGeoData(), illegal geo data!" );
2361 maLogicRect
= static_cast<const TableObjectGeoData
&>(rGeo
).maLogicRect
;
2363 SdrTextObj::RestoreGeoData (rGeo
);
2367 auto aRectangle
= getRectangle();
2368 mpImpl
->LayoutTable(aRectangle
, false, false);
2369 setRectangle(aRectangle
);
2374 void SdrTableObj::CropTableModelToSelection(const CellPos
& rStart
, const CellPos
& rEnd
)
2381 mpImpl
->CropTableModelToSelection(rStart
, rEnd
);
2384 void SdrTableObj::LayoutTableHeight(tools::Rectangle
& rArea
)
2386 if( mpImpl
.is() && mpImpl
->mpLayouter
)
2388 mpImpl
->mpLayouter
->LayoutTableHeight(rArea
, /*bFit*/false);
2392 void SdrTableObj::DistributeColumns( sal_Int32 nFirstColumn
, sal_Int32 nLastColumn
, const bool bOptimize
, const bool bMinimize
)
2394 if( mpImpl
.is() && mpImpl
->mpLayouter
)
2396 TableModelNotifyGuard
aGuard( mpImpl
->mxTable
.get() );
2397 auto aRectangle
= getRectangle();
2398 mpImpl
->mpLayouter
->DistributeColumns(aRectangle
, nFirstColumn
, nLastColumn
, bOptimize
, bMinimize
);
2399 setRectangle(aRectangle
);
2404 void SdrTableObj::DistributeRows( sal_Int32 nFirstRow
, sal_Int32 nLastRow
, const bool bOptimize
, const bool bMinimize
)
2406 if( mpImpl
.is() && mpImpl
->mpLayouter
)
2408 TableModelNotifyGuard
aGuard( mpImpl
->mxTable
.get() );
2409 auto aRectangle
= getRectangle();
2410 mpImpl
->mpLayouter
->DistributeRows(aRectangle
, nFirstRow
, nLastRow
, bOptimize
, bMinimize
);
2411 setRectangle(aRectangle
);
2416 void SdrTableObj::SetChanged()
2420 auto aRectangle
= getRectangle();
2421 mpImpl
->LayoutTable(aRectangle
, false, false);
2422 setRectangle(aRectangle
);
2425 ::SdrTextObj::SetChanged();
2429 void SdrTableObj::uno_lock()
2431 if( mpImpl
.is() && mpImpl
->mxTable
.is() )
2432 mpImpl
->mxTable
->lockBroadcasts();
2436 void SdrTableObj::uno_unlock()
2438 if( mpImpl
.is() && mpImpl
->mxTable
.is() )
2439 mpImpl
->mxTable
->unlockBroadcasts();
2442 void SdrTableObj::dumpAsXml(xmlTextWriterPtr pWriter
) const
2444 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SdrTableObj"));
2445 (void)xmlTextWriterWriteFormatAttribute(pWriter
, BAD_CAST("ptr"), "%p", this);
2447 SdrObject::dumpAsXml(pWriter
);
2449 mpImpl
->dumpAsXml(pWriter
);
2451 (void)xmlTextWriterEndElement(pWriter
);
2454 bool SdrTableObj::createTableEdgesJson(boost::property_tree::ptree
& rJsonRoot
)
2456 if (!mpImpl
.is() || !mpImpl
->mxTable
.is())
2459 tools::Rectangle aRect
= GetCurrentBoundRect();
2460 boost::property_tree::ptree aTableColumns
;
2462 aTableColumns
.put("tableOffset", o3tl::toTwips(aRect
.Left(), o3tl::Length::mm100
));
2464 boost::property_tree::ptree aEntries
;
2465 auto const aEdges
= mpImpl
->mpLayouter
->getVerticalEdges();
2466 for (auto & rEdge
: aEdges
)
2468 if (rEdge
.nIndex
== 0)
2470 aTableColumns
.put("left", o3tl::toTwips(rEdge
.nPosition
, o3tl::Length::mm100
));
2472 else if (rEdge
.nIndex
== sal_Int32(aEdges
.size() - 1))
2474 aTableColumns
.put("right", o3tl::toTwips(rEdge
.nPosition
, o3tl::Length::mm100
));
2478 boost::property_tree::ptree aEntry
;
2479 aEntry
.put("position", o3tl::toTwips(rEdge
.nPosition
, o3tl::Length::mm100
));
2480 aEntry
.put("min", o3tl::toTwips(rEdge
.nPosition
+ rEdge
.nMin
, o3tl::Length::mm100
));
2481 aEntry
.put("max", o3tl::toTwips(rEdge
.nPosition
+ rEdge
.nMax
, o3tl::Length::mm100
));
2482 aEntry
.put("hidden", false);
2483 aEntries
.push_back(std::make_pair("", aEntry
));
2486 aTableColumns
.push_back(std::make_pair("entries", aEntries
));
2488 rJsonRoot
.add_child("columns", aTableColumns
);
2490 boost::property_tree::ptree aTableRows
;
2492 aTableRows
.put("tableOffset", o3tl::toTwips(aRect
.Top(), o3tl::Length::mm100
));
2494 boost::property_tree::ptree aEntries
;
2495 auto const aEdges
= mpImpl
->mpLayouter
->getHorizontalEdges();
2496 for (auto & rEdge
: aEdges
)
2498 if (rEdge
.nIndex
== 0)
2500 aTableRows
.put("left", o3tl::toTwips(rEdge
.nPosition
, o3tl::Length::mm100
));
2502 else if (rEdge
.nIndex
== sal_Int32(aEdges
.size() - 1))
2504 aTableRows
.put("right", o3tl::toTwips(rEdge
.nPosition
, o3tl::Length::mm100
));
2508 boost::property_tree::ptree aEntry
;
2509 aEntry
.put("position", o3tl::toTwips(rEdge
.nPosition
, o3tl::Length::mm100
));
2510 aEntry
.put("min", o3tl::toTwips(rEdge
.nPosition
+ rEdge
.nMin
, o3tl::Length::mm100
));
2511 aEntry
.put("max", o3tl::toTwips(rEdge
.nPosition
+ rEdge
.nMax
, o3tl::Length::mm100
));
2512 aEntry
.put("hidden", false);
2513 aEntries
.push_back(std::make_pair("", aEntry
));
2516 aTableRows
.push_back(std::make_pair("entries", aEntries
));
2518 rJsonRoot
.add_child("rows", aTableRows
);
2524 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */