1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * The Contents of this file are made available subject to the terms of
5 * either of the following licenses
7 * - GNU Lesser General Public License Version 2.1
8 * - Sun Industry Standards Source License Version 1.1
10 * Sun Microsystems Inc., October, 2000
12 * GNU Lesser General Public License Version 2.1
13 * =============================================
14 * Copyright 2000 by Sun Microsystems, Inc.
15 * 901 San Antonio Road, Palo Alto, CA 94303, USA
17 * This library is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU Lesser General Public
19 * License version 2.1, as published by the Free Software Foundation.
21 * This library is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * Lesser General Public License for more details.
26 * You should have received a copy of the GNU Lesser General Public
27 * License along with this library; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
32 * Sun Industry Standards Source License Version 1.1
33 * =================================================
34 * The contents of this file are subject to the Sun Industry Standards
35 * Source License Version 1.1 (the "License"); You may not use this file
36 * except in compliance with the License. You may obtain a copy of the
37 * License at http://www.openoffice.org/license.html.
39 * Software provided under this License is provided on an "AS IS" basis,
40 * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
41 * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
42 * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
43 * See the License for the specific provisions governing your rights and
44 * obligations concerning the Software.
46 * The Initial Developer of the Original Code is: IBM Corporation
48 * Copyright: 2008 by IBM Corporation
50 * All Rights Reserved.
52 * Contributor(s): _______________________________________
55 ************************************************************************/
58 * For LWP filter architecture prototype - row layouts
61 #include "lwprowlayout.hxx"
62 #include "lwptable.hxx"
63 #include <lwpglobalmgr.hxx>
64 #include <xfilter/xfstylemanager.hxx>
65 #include <xfilter/xfrow.hxx>
66 #include <xfilter/xfrowstyle.hxx>
67 #include <xfilter/xftable.hxx>
68 #include <xfilter/xfcell.hxx>
69 #include <o3tl/sorted_vector.hxx>
71 LwpRowLayout::LwpRowLayout(LwpObjectHeader
const &objHdr
, LwpSvStream
* pStrm
)
72 : LwpVirtualLayout(objHdr
, pStrm
)
79 m_ConnCellList
.clear();
82 LwpRowLayout::~LwpRowLayout()
86 * @short register row style
92 void LwpRowLayout::SetRowMap()
94 LwpObjectID
*pCellID
= &GetChildHead();
95 LwpCellLayout
* pCellLayout
= dynamic_cast<LwpCellLayout
*>(pCellID
->obj().get());
97 o3tl::sorted_vector
<LwpCellLayout
*> aSeen
;
100 bool bAlreadySeen
= !aSeen
.insert(pCellLayout
).second
;
102 throw std::runtime_error("loop in conversion");
104 pCellLayout
->SetCellMap();
106 pCellID
= &pCellLayout
->GetNext();
107 pCellLayout
= dynamic_cast<LwpCellLayout
*>(pCellID
->obj().get());
111 * @short register row style
117 void LwpRowLayout::RegisterStyle()
119 // register row style
120 std::unique_ptr
<XFRowStyle
> pRowStyle(new XFRowStyle());
122 if (m_nDirection
& 0x0030)
124 pRowStyle
->SetMinRowHeight(LwpTools::ConvertFromUnits(cheight
));
128 pRowStyle
->SetRowHeight(LwpTools::ConvertFromUnits(cheight
));
130 XFStyleManager
* pXFStyleManager
= LwpGlobalMgr::GetInstance()->GetXFStyleManager();
131 m_StyleName
= pXFStyleManager
->AddStyle(std::move(pRowStyle
)).m_pStyle
->GetStyleName();
133 LwpTableLayout
* pTableLayout
= GetParentTableLayout();
136 pTableLayout
->GetTable();
138 // register cells' style
139 LwpObjectID
*pCellID
= &GetChildHead();
140 LwpCellLayout
* pCellLayout
= dynamic_cast<LwpCellLayout
*>(pCellID
->obj().get());
142 o3tl::sorted_vector
<LwpCellLayout
*> aSeen
;
145 bool bAlreadySeen
= !aSeen
.insert(pCellLayout
).second
;
147 throw std::runtime_error("loop in conversion");
149 pCellLayout
->SetFoundry(m_pFoundry
);
150 pCellLayout
->RegisterStyle();
151 pCellID
= &pCellLayout
->GetNext();
152 pCellLayout
= dynamic_cast<LwpCellLayout
*>(pCellID
->obj().get());
157 * @short register row style
163 void LwpRowLayout::Read()
165 #define MAXUNIT (0x7fffffffL) // Highest positive UNIT value
166 LwpObjectStream
* pStrm
= m_pObjStrm
.get();
168 LwpVirtualLayout::Read();
170 //skip CLiteLayout data;
171 LwpAtomHolder ContentClass
;
172 ContentClass
.Read(pStrm
);
175 // Row layout content
176 crowid
= pStrm
->QuickReaduInt16();
177 cheight
= pStrm
->QuickReadInt32();
178 cLeaderDotCount
= static_cast<sal_uInt8
>(pStrm
->QuickReaduInt16()); // was written as lushort.
179 cLeaderDotY
= MAXUNIT
; // Sentinel meaning "not calculated yet"
180 cRowFlags
= static_cast<sal_uInt8
>(pStrm
->QuickReaduInt16()); // was written as lushort.
186 * @short Parse rows with connect cell
187 * @param pXFTable - pointer to created XFTable
189 void LwpRowLayout::ConvertRow(rtl::Reference
<XFTable
> const & pXFTable
,sal_uInt8 nStartCol
,sal_uInt8 nEndCol
)
191 LwpTableLayout
* pTableLayout
= GetParentTableLayout();
193 throw std::runtime_error("missing TableLayout");
194 LwpTable
* pTable
= pTableLayout
->GetTable();
196 throw std::runtime_error("missing Table");
198 //calculate the connected cell position
199 sal_Int32 nMarkConnCell
= FindMarkConnCell(nStartCol
,nEndCol
);
201 //if there is no connected cell
202 if (nMarkConnCell
== -1)
204 ConvertCommonRow(pXFTable
,nStartCol
,nEndCol
);
208 //register connect row style
209 sal_uInt16 nRowMark
= crowid
+ GetCurMaxSpannedRows(nStartCol
,nEndCol
);
210 rtl::Reference
<XFRow
> xXFRow(new XFRow
);
211 RegisterCurRowStyle(xXFRow
.get(), nRowMark
);
213 //if there is connected cell
214 for (sal_uInt8 i
=nStartCol
; i
<nEndCol
; )
216 rtl::Reference
<XFCell
> xXFCell
;
219 if (nMarkConnCell
== -1)
222 nColMark
= m_ConnCellList
[nMarkConnCell
]->GetColID();
224 if (nColMark
> i
)//create subtable
226 xXFCell
.set(new XFCell
);
227 xXFCell
->SetColumnSpaned(nColMark
-i
);
228 rtl::Reference
<XFTable
> xSubTable(new XFTable
);
229 pTableLayout
->ConvertTable(xSubTable
,crowid
,nRowMark
,i
,nColMark
);
230 xXFCell
->Add(xSubTable
.get());
235 sal_uInt8 nColID
= m_ConnCellList
[nMarkConnCell
]->GetColID()
236 +m_ConnCellList
[nMarkConnCell
]->GetNumcols()-1;
237 xXFCell
= m_ConnCellList
[nMarkConnCell
]->DoConvertCell(
238 pTable
->GetObjectID(),
239 crowid
+m_ConnCellList
[nMarkConnCell
]->GetNumrows()-1,
240 m_ConnCellList
[nMarkConnCell
]->GetColID());
242 //set all cell in this merge cell to cellsmap
243 pTableLayout
->SetCellsMap(crowid
, i
, nRowMark
- 1, nColID
, xXFCell
.get());
245 i
+= m_ConnCellList
[nMarkConnCell
]->GetNumcols();
246 nMarkConnCell
= FindNextMarkConnCell(static_cast<sal_uInt16
>(nMarkConnCell
),nEndCol
);
250 xXFRow
->AddCell(xXFCell
);
252 pXFTable
->AddRow(xXFRow
);
256 * @short register row style in SODC table
257 * @param pXFRow - pointer of row
258 * @param nRowMark - spanned row number
260 void LwpRowLayout::RegisterCurRowStyle(XFRow
* pXFRow
,sal_uInt16 nRowMark
)
262 XFStyleManager
* pXFStyleManager
= LwpGlobalMgr::GetInstance()->GetXFStyleManager();
263 XFRowStyle
* pRowStyle
= static_cast<XFRowStyle
*>(pXFStyleManager
->FindStyle(m_StyleName
));
266 double fHeight
= pRowStyle
->GetRowHeight();
268 std::unique_ptr
<XFRowStyle
> pNewStyle(new XFRowStyle
);
269 *pNewStyle
= *pRowStyle
;
270 LwpTableLayout
* pTableLayout
= GetParentTableLayout();
275 std::map
<sal_uInt16
,LwpRowLayout
*> RowsMap
= pTableLayout
->GetRowsMap();
277 for (sal_uInt16 i
=crowid
+1; i
<nRowMark
;i
++)
279 std::map
<sal_uInt16
,LwpRowLayout
*>::iterator iter
= RowsMap
.find(i
);
280 if (iter
== RowsMap
.end())
282 pRowStyle
= static_cast<XFRowStyle
*>(
283 pXFStyleManager
->FindStyle(pTableLayout
->GetDefaultRowStyleName()));
287 pRowStyle
= static_cast<XFRowStyle
*>(
288 pXFStyleManager
->FindStyle(iter
->second
->GetStyleName()));
291 throw std::runtime_error("missing RowStyle");
292 fHeight
+= pRowStyle
->GetRowHeight();
295 if (m_nDirection
& 0x0030)
297 pNewStyle
->SetMinRowHeight(static_cast<float>(fHeight
));
301 pNewStyle
->SetRowHeight(static_cast<float>(fHeight
));
304 pXFRow
->SetStyleName(pXFStyleManager
->AddStyle(std::move(pNewStyle
)).m_pStyle
->GetStyleName());
308 * @short find max merge cell in a given column range
309 * @param nStartCol - start column ID
310 * @param nEndCol - end column ID
312 sal_Int32
LwpRowLayout::FindMarkConnCell(sal_uInt8 nStartCol
,sal_uInt8 nEndCol
)
314 if (m_ConnCellList
.empty())
317 sal_uInt16 nSpannRows
= 1;
318 sal_Int32 nMarkConnCell
= -1;
320 for (size_t i
=0;i
<m_ConnCellList
.size();i
++)
322 if (m_ConnCellList
[i
]->GetColID()>=nEndCol
)
324 if (m_ConnCellList
[i
]->GetColID()>=nStartCol
)
326 if (m_ConnCellList
[i
]->GetNumrows()>nSpannRows
)
328 nSpannRows
= m_ConnCellList
[i
]->GetNumrows();
333 return nMarkConnCell
;
337 * @short find next merge cell with the same spanned row number with current merge cell
338 * @param nStartCol - start column ID
339 * @param nEndCol - end column ID
341 sal_Int32
LwpRowLayout::FindNextMarkConnCell(sal_uInt16 nMarkConnCell
,sal_uInt8 nEndCol
)
343 sal_uInt16 nMaxRows
= m_ConnCellList
[nMarkConnCell
]->GetNumrows();
345 for (size_t i
=nMarkConnCell
+1;i
<m_ConnCellList
.size();i
++)
347 if (m_ConnCellList
[i
]->GetColID()>=nEndCol
)
349 if (m_ConnCellList
[i
]->GetNumrows() == nMaxRows
)
357 * @short get max spanned row numbers in a given column range
358 * @param nStartCol - start column ID
359 * @param nEndCol - end column ID
361 sal_uInt16
LwpRowLayout::GetCurMaxSpannedRows(sal_uInt8 nStartCol
,sal_uInt8 nEndCol
)
363 sal_Int32 nMarkConnCell
= FindMarkConnCell(nStartCol
,nEndCol
);
364 if (nMarkConnCell
== -1)
367 return m_ConnCellList
[nMarkConnCell
]->GetNumrows();
370 * @short convert row with rowlayout,but no merge cells
371 * @param pXFTable - pointer of table
372 * @param nStartCol - start column ID
373 * @param nEndCol - end column ID
375 void LwpRowLayout::ConvertCommonRow(rtl::Reference
<XFTable
> const & pXFTable
, sal_uInt8 nStartCol
, sal_uInt8 nEndCol
)
377 LwpTableLayout
* pTableLayout
= GetParentTableLayout();
380 LwpTable
* pTable
= pTableLayout
->GetTable();
384 rtl::Reference
<XFRow
> xRow(new XFRow
);
385 xRow
->SetStyleName(m_StyleName
);
387 sal_uInt8 nCellStartCol
,nCellEndCol
;
389 for (sal_uInt16 i
= nStartCol
; i
< nEndCol
; i
++)
392 LwpObjectID
*pCellID
= &GetChildHead();
393 LwpCellLayout
* pCellLayout
= dynamic_cast<LwpCellLayout
*>(pCellID
->obj().get());
394 nCellStartCol
= i
;//mark the begin position of cell
395 nCellEndCol
= i
;//mark the end position of cell
396 rtl::Reference
<XFCell
> xCell
;
399 if (pCellLayout
->GetColID() == i
)
401 if (pCellLayout
->GetLayoutType() == LWP_CONNECTED_CELL_LAYOUT
)
403 LwpConnectedCellLayout
* pConnCell
= static_cast<LwpConnectedCellLayout
*>(pCellLayout
);
404 auto nNumCols
= pConnCell
->GetNumcols();
406 throw std::runtime_error("loop in conversion");
407 auto nNewEndCol
= i
+ nNumCols
- 1;
408 if (nNewEndCol
> std::numeric_limits
<sal_uInt8
>::max())
409 throw std::range_error("column index too large");
410 nCellEndCol
= nNewEndCol
;
413 xCell
= pCellLayout
->DoConvertCell(pTable
->GetObjectID(),crowid
,i
);
416 pCellID
= &pCellLayout
->GetNext();
417 pCellLayout
= dynamic_cast<LwpCellLayout
*>(pCellID
->obj().get());
421 // if table has default cell layout, use it to ConvertCell
422 // otherwise use blank cell
423 LwpCellLayout
* pDefaultCell
= pTableLayout
->GetDefaultCellLayout();
426 xCell
= pDefaultCell
->DoConvertCell(
427 pTable
->GetObjectID(),crowid
, i
);
431 xCell
.set(new XFCell
);
434 xRow
->AddCell(xCell
);
436 pTableLayout
->SetCellsMap(crowid
, nCellStartCol
, crowid
, nCellEndCol
, xCell
.get()); //set to cellsmap
439 pXFTable
->AddRow(xRow
);
442 * @short collect merge cell info when register row styles
444 void LwpRowLayout::CollectMergeInfo()
446 LwpObjectID
*pCellID
= &GetChildHead();
447 LwpCellLayout
* pCellLayout
= dynamic_cast<LwpCellLayout
*>(pCellID
->obj().get());
451 if (pCellLayout
->GetLayoutType() == LWP_CONNECTED_CELL_LAYOUT
)
453 LwpConnectedCellLayout
* pConnCell
= static_cast<LwpConnectedCellLayout
*>(pCellLayout
);
454 m_ConnCellList
.push_back(pConnCell
);
456 pCellID
= &pCellLayout
->GetNext();
457 pCellLayout
= dynamic_cast<LwpCellLayout
*>(pCellID
->obj().get());
461 * @short split merge cells in this row
462 * @param nEffectRows - max spanned number of previous row
464 void LwpRowLayout::SetCellSplit(sal_uInt16 nEffectRows
)
466 for (LwpConnectedCellLayout
* pConnCell
: m_ConnCellList
)
469 if (o3tl::checked_add(pConnCell
->GetRowID(), pConnCell
->GetNumrows(), nRowSpan
))
470 throw std::range_error("bad span");
471 if (nRowSpan
> nEffectRows
)
473 if (o3tl::checked_sub(nEffectRows
, pConnCell
->GetRowID(), nRowSpan
))
474 throw std::range_error("bad span");
475 pConnCell
->SetNumrows(nRowSpan
);
480 * @short check if the row has merge cell
482 bool LwpRowLayout::GetMergeCellFlag() const
484 return !m_ConnCellList
.empty();
487 LwpRowHeadingLayout::LwpRowHeadingLayout(LwpObjectHeader
const &objHdr
, LwpSvStream
* pStrm
)
488 : LwpRowLayout(objHdr
, pStrm
)
491 LwpRowHeadingLayout::~LwpRowHeadingLayout()
493 void LwpRowHeadingLayout::Read()
495 LwpRowLayout::Read();
497 cRowLayout
.ReadIndexed(m_pObjStrm
.get());
498 m_pObjStrm
->SkipExtra();
501 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */