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 <tools/mempool.hxx>
22 #include <tools/ref.hxx>
23 #include <tblenum.hxx>
24 #include <swtypes.hxx>
29 #include <boost/noncopyable.hpp>
32 #include <o3tl/sorted_vector.hxx>
41 class SwHTMLTableLayout
;
56 class SwTableBox_Impl
;
57 class SwUndoTblCpyTbl
;
62 #ifndef SW_DECL_SWSERVEROBJECT_DEFINED
63 #define SW_DECL_SWSERVEROBJECT_DEFINED
64 SV_DECL_REF( SwServerObject
)
67 class SwTableLines
: public std::vector
<SwTableLine
*> {
69 // free's any remaining child objects
72 // return USHRT_MAX if not found, else index of position
73 sal_uInt16
GetPos(const SwTableLine
* pBox
) const
75 const_iterator it
= std::find(begin(), end(), pBox
);
76 return it
== end() ? USHRT_MAX
: it
- begin();
80 class SwTableBoxes
: public std::vector
<SwTableBox
*> {
82 // return USHRT_MAX if not found, else index of position
83 sal_uInt16
GetPos(const SwTableBox
* pBox
) const
85 const_iterator it
= std::find(begin(), end(), pBox
);
86 return it
== end() ? USHRT_MAX
: it
- begin();
90 // Save content-bearing box-pointers additionally in a sorted array
91 // (for calculation in table).
92 class SwTableSortBoxes
: public o3tl::sorted_vector
<SwTableBox
*> {};
94 class SW_DLLPUBLIC SwTable
: public SwClient
//Client of FrmFmt.
100 SwTableSortBoxes m_TabSortContentBoxes
;
101 SwServerObjectRef refObj
; // In case DataServer -> pointer is set.
103 SwHTMLTableLayout
*pHTMLLayout
;
105 // Usually, the table node of a SwTable can be accessed by getting a box
106 // out of m_TabSortContentBoxes, which know their SwStartNode. But in some rare
107 // cases, we need to know the table node of a SwTable, before the table
108 // boxes have been build (SwTableNode::MakeCopy with tables in tables).
109 SwTableNode
* pTableNode
;
111 // Should that be adjustable for every table?
112 TblChgMode eTblChgMode
;
114 sal_uInt16 nGrfsThatResize
; // Count of Grfs that initiate a resize of table
116 sal_uInt16 nRowsToRepeat
; // Number of rows to repeat on every page.
118 bool bModifyLocked
:1;
119 sal_Bool bNewModel
:1; // sal_False: old SubTableModel; sal_True: new RowSpanModel
121 /// This is set by functions (like Merge()) to forbid a late model change.
122 bool m_bDontChangeModel
;
125 bool IsModifyLocked(){ return bModifyLocked
;}
127 virtual void Modify( const SfxPoolItem
* pOld
, const SfxPoolItem
* pNew
);
132 SEARCH_NONE
, // Default: expand to rectangle
133 SEARCH_ROW
, // row selection
134 SEARCH_COL
// column selection
139 // single argument ctors shall be explicit.
140 explicit SwTable( SwTableFmt
* );
143 // @@@ public copy ctor, but no copy assignment?
144 SwTable( const SwTable
& rTable
); // no copy of the lines !!
146 // @@@ public copy ctor, but no copy assignment?
147 SwTable
& operator= (const SwTable
&);
150 bool OldMerge( SwDoc
*, const SwSelBoxes
&, SwTableBox
*, SwUndoTblMerge
* );
151 bool OldSplitRow( SwDoc
*, const SwSelBoxes
&, sal_uInt16
, bool );
152 sal_Bool
NewMerge( SwDoc
*, const SwSelBoxes
&, const SwSelBoxes
& rMerged
,
153 SwTableBox
*, SwUndoTblMerge
* );
154 sal_Bool
NewSplitRow( SwDoc
*, const SwSelBoxes
&, sal_uInt16
, sal_Bool
);
155 SwBoxSelection
* CollectBoxSelection( const SwPaM
& rPam
) const;
156 void InsertSpannedRow( SwDoc
* pDoc
, sal_uInt16 nIdx
, sal_uInt16 nCnt
);
157 bool _InsertRow( SwDoc
*, const SwSelBoxes
&, sal_uInt16 nCnt
, bool bBehind
);
158 bool NewInsertCol( SwDoc
*, const SwSelBoxes
& rBoxes
, sal_uInt16 nCnt
, bool );
159 void _FindSuperfluousRows( SwSelBoxes
& rBoxes
, SwTableLine
*, SwTableLine
* );
160 void AdjustWidths( const long nOld
, const long nNew
);
161 void NewSetTabCols( Parm
&rP
, const SwTabCols
&rNew
, const SwTabCols
&rOld
,
162 const SwTableBox
*pStart
, sal_Bool bCurRowOnly
);
166 SwHTMLTableLayout
*GetHTMLTableLayout() { return pHTMLLayout
; }
167 const SwHTMLTableLayout
*GetHTMLTableLayout() const { return pHTMLLayout
; }
168 void SetHTMLTableLayout( SwHTMLTableLayout
*p
); //Change of property!
170 sal_uInt16
IncGrfsThatResize() { return ++nGrfsThatResize
; }
171 sal_uInt16
DecGrfsThatResize() { return nGrfsThatResize
? --nGrfsThatResize
: 0; }
173 void LockModify() { bModifyLocked
= true; } // Must be used always
174 void UnlockModify() { bModifyLocked
= false;} // in pairs!
176 void SetTableModel( sal_Bool bNew
){ bNewModel
= bNew
; }
177 sal_Bool
IsNewModel() const { return bNewModel
; }
179 sal_uInt16
GetRowsToRepeat() const { return std::min( (sal_uInt16
)GetTabLines().size(), nRowsToRepeat
); }
180 sal_uInt16
_GetRowsToRepeat() const { return nRowsToRepeat
; }
181 void SetRowsToRepeat( sal_uInt16 nNumOfRows
) { nRowsToRepeat
= nNumOfRows
; }
183 bool IsHeadline( const SwTableLine
& rLine
) const;
185 SwTableLines
&GetTabLines() { return aLines
; }
186 const SwTableLines
&GetTabLines() const { return aLines
; }
188 SwFrmFmt
* GetFrmFmt() { return (SwFrmFmt
*)GetRegisteredIn(); }
189 SwFrmFmt
* GetFrmFmt() const { return (SwFrmFmt
*)GetRegisteredIn(); }
190 SwTableFmt
* GetTableFmt() const { return (SwTableFmt
*)GetRegisteredIn(); }
192 void GetTabCols( SwTabCols
&rToFill
, const SwTableBox
*pStart
,
193 sal_Bool bHidden
= sal_False
, sal_Bool bCurRowOnly
= sal_False
) const;
194 void SetTabCols( const SwTabCols
&rNew
, const SwTabCols
&rOld
,
195 const SwTableBox
*pStart
, sal_Bool bCurRowOnly
);
197 // The following functions are for new table model only...
198 void CreateSelection( const SwPaM
& rPam
, SwSelBoxes
& rBoxes
,
199 const SearchType eSearchType
, bool bProtect
) const;
200 void CreateSelection( const SwNode
* pStart
, const SwNode
* pEnd
,
201 SwSelBoxes
& rBoxes
, const SearchType eSearchType
, bool bProtect
) const;
202 void ExpandSelection( SwSelBoxes
& rBoxes
) const;
203 // When a table is splitted into two tables, the row spans which overlaps
204 // the split have to be corrected and stored for undo
205 // SwSavRowSpan is the structure needed by Undo to undo the split operation
206 // CleanUpRowSpan corrects the (top of the) second table and delviers the structure
208 SwSaveRowSpan
* CleanUpTopRowSpan( sal_uInt16 nSplitLine
);
209 // RestoreRowSpan is called by Undo to restore the old row span values
210 void RestoreRowSpan( const SwSaveRowSpan
& );
211 // CleanUpBottomRowSpan corrects the overhanging row spans at the end of the first table
212 void CleanUpBottomRowSpan( sal_uInt16 nDelLines
);
215 // The following functions are "pseudo-virtual", i.e. they are different for old and new table model
216 // It's not allowed to change the table model after the first call of one of these functions.
218 sal_Bool
Merge( SwDoc
* pDoc
, const SwSelBoxes
& rBoxes
, const SwSelBoxes
& rMerged
,
219 SwTableBox
* pMergeBox
, SwUndoTblMerge
* pUndo
= 0 )
222 m_bDontChangeModel
= true;
224 return bNewModel
? NewMerge( pDoc
, rBoxes
, rMerged
, pMergeBox
, pUndo
) :
225 OldMerge( pDoc
, rBoxes
, pMergeBox
, pUndo
);
227 bool SplitRow( SwDoc
* pDoc
, const SwSelBoxes
& rBoxes
, sal_uInt16 nCnt
=1,
228 bool bSameHeight
= false )
231 m_bDontChangeModel
= true;
233 return bNewModel
? NewSplitRow( pDoc
, rBoxes
, nCnt
, bSameHeight
) :
234 OldSplitRow( pDoc
, rBoxes
, nCnt
, bSameHeight
);
236 bool PrepareMerge( const SwPaM
& rPam
, SwSelBoxes
& rBoxes
,
237 SwSelBoxes
& rMerged
, SwTableBox
** ppMergeBox
, SwUndoTblMerge
* pUndo
);
238 void ExpandColumnSelection( SwSelBoxes
& rBoxes
, long &rMin
, long &rMax
) const;
239 void PrepareDeleteCol( long nMin
, long nMax
);
241 bool InsertCol( SwDoc
*, const SwSelBoxes
& rBoxes
,
242 sal_uInt16 nCnt
= 1, bool bBehind
= true );
243 bool InsertRow( SwDoc
*, const SwSelBoxes
& rBoxes
,
244 sal_uInt16 nCnt
= 1, bool bBehind
= true );
245 void PrepareDelBoxes( const SwSelBoxes
& rBoxes
);
246 bool DeleteSel( SwDoc
*, const SwSelBoxes
& rBoxes
, const SwSelBoxes
* pMerged
,
247 SwUndo
* pUndo
, const bool bDelMakeFrms
, const bool bCorrBorder
);
248 bool SplitCol( SwDoc
* pDoc
, const SwSelBoxes
& rBoxes
, sal_uInt16 nCnt
=1 );
249 sal_Bool
Merge( const SwSelBoxes
& rBoxes
,
250 SwTableBox
* pMergeBox
, SwUndoTblMerge
* = 0 );
252 void FindSuperfluousRows( SwSelBoxes
& rBoxes
)
253 { _FindSuperfluousRows( rBoxes
, 0, 0 ); }
254 void CheckRowSpan( SwTableLine
* &rpLine
, bool bUp
) const;
256 SwTableSortBoxes
& GetTabSortBoxes() { return m_TabSortContentBoxes
; }
257 const SwTableSortBoxes
& GetTabSortBoxes() const { return m_TabSortContentBoxes
; }
259 // Read 1st number and delete it from string (used by GetTblBox and SwTblFld).
262 // add 3rd parameter in order to control validation check on <rStr>
263 static sal_uInt16
_GetBoxNum( String
& rStr
,
264 sal_Bool bFirst
= sal_False
,
265 const bool bPerformValidCheck
= false );
267 // Search content-bearing box with that name.
270 // add 2nd parameter in order to control validation check in called method
272 const SwTableBox
* GetTblBox( const String
& rName
,
273 const bool bPerformValidCheck
= false ) const;
274 // Copy selected boxes to another document.
275 bool MakeCopy( SwDoc
*, const SwPosition
&, const SwSelBoxes
&,
276 bool bCpyNds
= true, bool bCpyName
= false ) const;
277 // Copy table in this
278 sal_Bool
InsTable( const SwTable
& rCpyTbl
, const SwNodeIndex
&,
279 SwUndoTblCpyTbl
* pUndo
= 0 );
280 sal_Bool
InsTable( const SwTable
& rCpyTbl
, const SwSelBoxes
&,
281 SwUndoTblCpyTbl
* pUndo
= 0 );
282 sal_Bool
InsNewTable( const SwTable
& rCpyTbl
, const SwSelBoxes
&,
283 SwUndoTblCpyTbl
* pUndo
);
284 // Copy headline of table (with content!) into an other one.
285 bool CopyHeadlineIntoTable( SwTableNode
& rTblNd
);
287 // Get box, whose start index is set on nBoxStt.
288 SwTableBox
* GetTblBox( sal_uLong nSttIdx
);
289 const SwTableBox
* GetTblBox( sal_uLong nSttIdx
) const
290 { return ((SwTable
*)this)->GetTblBox( nSttIdx
); }
292 // Returns true if table contains nestings.
293 bool IsTblComplex() const;
295 // Returns true if table or selection is balanced.
296 bool IsTblComplexForChart( const String
& rSel
) const;
298 // Search all content-bearing boxes of the base line on which this box stands.
299 // rBoxes as a return value for immediate use.
300 // steht. rBoxes auch als Return-Wert, um es gleich weiter zu benutzen
301 // bToTop = true -> up to base line, sal_False-> else only line of box.
302 SwSelBoxes
& SelLineFromBox( const SwTableBox
* pBox
,
303 SwSelBoxes
& rBoxes
, bool bToTop
= true ) const;
305 // Get information from client.
306 virtual bool GetInfo( SfxPoolItem
& ) const;
308 // Search in format for registered table.
309 static SwTable
* FindTable( SwFrmFmt
const*const pFmt
);
311 // Clean up structure a bit.
314 // Returns the table node via m_TabSortContentBoxes or pTableNode.
315 SwTableNode
* GetTableNode() const;
316 void SetTableNode( SwTableNode
* pNode
) { pTableNode
= pNode
; }
318 // Data server methods.
319 void SetRefObject( SwServerObject
* );
320 const SwServerObject
* GetObject() const { return &refObj
; }
321 SwServerObject
* GetObject() { return &refObj
; }
323 // Fill data for chart.
324 void UpdateCharts() const;
326 TblChgMode
GetTblChgMode() const { return eTblChgMode
; }
327 void SetTblChgMode( TblChgMode eMode
) { eTblChgMode
= eMode
; }
329 bool SetColWidth( SwTableBox
& rAktBox
, sal_uInt16 eType
,
330 SwTwips nAbsDiff
, SwTwips nRelDiff
, SwUndo
** ppUndo
);
331 bool SetRowHeight( SwTableBox
& rAktBox
, sal_uInt16 eType
,
332 SwTwips nAbsDiff
, SwTwips nRelDiff
, SwUndo
** ppUndo
);
333 void RegisterToFormat( SwFmt
& rFmt
);
335 void CheckConsistency() const;
338 bool HasLayout() const;
341 class SW_DLLPUBLIC SwTableLine
: public SwClient
// Client of FrmFmt.
349 SwTableLine() : pUpper(0) {}
351 SwTableLine( SwTableLineFmt
*, sal_uInt16 nBoxes
, SwTableBox
*pUp
);
352 virtual ~SwTableLine();
354 SwTableBoxes
&GetTabBoxes() { return aBoxes
; }
355 const SwTableBoxes
&GetTabBoxes() const { return aBoxes
; }
357 SwTableBox
*GetUpper() { return pUpper
; }
358 const SwTableBox
*GetUpper() const { return pUpper
; }
359 void SetUpper( SwTableBox
*pNew
) { pUpper
= pNew
; }
362 SwFrmFmt
* GetFrmFmt() { return (SwFrmFmt
*)GetRegisteredIn(); }
363 SwFrmFmt
* GetFrmFmt() const { return (SwFrmFmt
*)GetRegisteredIn(); }
365 // Creates a own FrmFmt if more lines depend on it.
366 SwFrmFmt
* ClaimFrmFmt();
367 void ChgFrmFmt( SwTableLineFmt
* pNewFmt
);
369 // Search next/previous box with content.
370 SwTableBox
* FindNextBox( const SwTable
&, const SwTableBox
* =0,
371 bool bOvrTblLns
=true ) const;
372 SwTableBox
* FindPreviousBox( const SwTable
&, const SwTableBox
* =0,
373 bool bOvrTblLns
=true ) const;
375 SwTwips
GetTableLineHeight( bool& bLayoutAvailable
) const;
377 bool hasSoftPageBreak() const;
378 void RegisterToFormat( SwFmt
& rFmt
);
381 class SW_DLLPUBLIC SwTableBox
: public SwClient
//Client of FrmFmt.
383 friend class SwNodes
; // Transpose index.
384 friend void DelBoxNode(SwTableSortBoxes
&); // Delete StartNode* !
385 friend class SwXMLTableContext
;
387 // Not implemented (any more).
388 SwTableBox( const SwTableBox
& );
389 SwTableBox
&operator=( const SwTableBox
&); // Does not exist.
392 const SwStartNode
* pSttNd
;
394 SwTableBox_Impl
* pImpl
;
396 // In case Format contains formulas/values already,
397 // a new one must be created for the new box.
398 SwTableBoxFmt
* CheckBoxFmt( SwTableBoxFmt
* );
403 SwTableBox() : pSttNd(0), pUpper(0), pImpl(0) {}
405 SwTableBox( SwTableBoxFmt
*, sal_uInt16 nLines
, SwTableLine
*pUp
= 0 );
406 SwTableBox( SwTableBoxFmt
*, const SwStartNode
&, SwTableLine
*pUp
= 0 );
407 SwTableBox( SwTableBoxFmt
*, const SwNodeIndex
&, SwTableLine
*pUp
= 0 );
408 virtual ~SwTableBox();
410 SwTableLines
&GetTabLines() { return aLines
; }
411 const SwTableLines
&GetTabLines() const { return aLines
; }
413 SwTableLine
*GetUpper() { return pUpper
; }
414 const SwTableLine
*GetUpper() const { return pUpper
; }
415 void SetUpper( SwTableLine
*pNew
) { pUpper
= pNew
; }
417 SwFrmFmt
* GetFrmFmt() { return (SwFrmFmt
*)GetRegisteredIn(); }
418 SwFrmFmt
* GetFrmFmt() const { return (SwFrmFmt
*)GetRegisteredIn(); }
420 // Creates its own FrmFmt if more boxes depend on it.
421 SwFrmFmt
* ClaimFrmFmt();
422 void ChgFrmFmt( SwTableBoxFmt
*pNewFmt
);
424 void RemoveFromTable();
425 const SwStartNode
*GetSttNd() const { return pSttNd
; }
426 sal_uLong
GetSttIdx() const;
428 // Search next/previous box with content.
429 SwTableBox
* FindNextBox( const SwTable
&, const SwTableBox
* =0,
430 bool bOvrTblLns
=true ) const;
431 SwTableBox
* FindPreviousBox( const SwTable
&, const SwTableBox
* =0,
432 bool bOvrTblLns
=true ) const;
433 // Return name of this box. It is determined dynamically and
434 // is calculated from the position in the lines/boxes/table.
435 String
GetName() const;
436 // Return "value" of box (for calculating in table).
437 double GetValue( SwTblCalcPara
& rPara
) const;
439 sal_Bool
IsInHeadline( const SwTable
* pTbl
= 0 ) const;
441 // Contains box contents, that can be formated as a number?
442 sal_Bool
HasNumCntnt( double& rNum
, sal_uInt32
& rFmtIndex
,
443 sal_Bool
& rIsEmptyTxtNd
) const;
444 sal_uLong
IsValidNumTxtNd( sal_Bool bCheckAttr
= sal_True
) const;
445 // If a table formula is set, test if box contents is congruent with number.
446 // (For Redo of change of NumFormat!).
447 sal_Bool
IsNumberChanged() const;
449 // Is that a formula box or a box with numeric contents (AutoSum)?
450 // What it is is indicated by the return value - the WhichId of the attribute.
451 // Empty boxes have the return value USHRT_MAX !!
452 sal_uInt16
IsFormulaOrValueBox() const;
454 // Loading of a document requires an actualisation of cells with values
455 void ActualiseValueBox();
457 DECL_FIXEDMEMPOOL_NEWDEL(SwTableBox
)
459 // Access on internal data - currently used for the NumFormatter.
460 inline const Color
* GetSaveUserColor() const;
461 inline const Color
* GetSaveNumFmtColor() const;
462 inline void SetSaveUserColor(const Color
* p
);
463 inline void SetSaveNumFmtColor( const Color
* p
);
465 long getRowSpan() const;
466 void setRowSpan( long nNewRowSpan
);
467 bool getDummyFlag() const;
468 void setDummyFlag( bool bDummy
);
470 SwTableBox
& FindStartOfRowSpan( const SwTable
&, sal_uInt16 nMaxStep
= USHRT_MAX
);
471 const SwTableBox
& FindStartOfRowSpan( const SwTable
& rTable
,
472 sal_uInt16 nMaxStep
= USHRT_MAX
) const
473 { return const_cast<SwTableBox
*>(this)->FindStartOfRowSpan( rTable
, nMaxStep
); }
475 SwTableBox
& FindEndOfRowSpan( const SwTable
&, sal_uInt16 nMaxStep
= USHRT_MAX
);
476 const SwTableBox
& FindEndOfRowSpan( const SwTable
& rTable
,
477 sal_uInt16 nMaxStep
= USHRT_MAX
) const
478 { return const_cast<SwTableBox
*>(this)->FindEndOfRowSpan( rTable
, nMaxStep
); }
479 void RegisterToFormat( SwFmt
& rFmt
) ;
483 class SW_DLLPUBLIC SwTableCellInfo
: public ::boost::noncopyable
486 ::std::auto_ptr
<Impl
> m_pImpl
;
488 const SwCellFrm
* getCellFrm() const ;
491 SwTableCellInfo(const SwTable
* pTable
);
495 SwRect
getRect() const;
496 const SwTableBox
* getTableBox() const;
499 #endif //_SWTABLE_HXX
501 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */