/src/libetonyek/src/lib/contexts/IWORKTableInfoElement.cpp
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* |
3 | | * This file is part of the libetonyek project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | */ |
9 | | |
10 | | #include "IWORKTableInfoElement.h" |
11 | | |
12 | | #include <memory> |
13 | | |
14 | | #include "libetonyek_xml.h" |
15 | | #include "IWORKCollector.h" |
16 | | #include "IWORKDictionary.h" |
17 | | #include "IWORKFormulaElement.h" |
18 | | #include "IWORKGeometryElement.h" |
19 | | #include "IWORKMutableArrayElement.h" |
20 | | #include "IWORKNumberElement.h" |
21 | | #include "IWORKPushCollector.h" |
22 | | #include "IWORKRefContext.h" |
23 | | #include "IWORKStringElement.h" |
24 | | #include "IWORKStyleContainer.h" |
25 | | #include "IWORKTable.h" |
26 | | #include "IWORKText.h" |
27 | | #include "IWORKTextStorageElement.h" |
28 | | #include "IWORKToken.h" |
29 | | #include "IWORKWrapElement.h" |
30 | | #include "IWORKXMLParserState.h" |
31 | | #include "IWORKXMLContextBase.h" |
32 | | |
33 | | |
34 | | namespace libetonyek |
35 | | { |
36 | | |
37 | | namespace |
38 | | { |
39 | | typedef IWORKStyleContainer<+IWORKToken::NS_URI_SF | IWORKToken::table_style, +IWORKToken::NS_URI_SF | IWORKToken::table_style_ref> TableStyleContext; |
40 | | } |
41 | | |
42 | | namespace |
43 | | { |
44 | | |
45 | | class TableCellContentElement : public IWORKXMLElementContextBase |
46 | | { |
47 | | public: |
48 | | explicit TableCellContentElement(IWORKXMLParserState &state); |
49 | | |
50 | | private: |
51 | | void attribute(int name, const char *value) override; |
52 | | IWORKXMLContextPtr_t element(int name) override; |
53 | | }; |
54 | | |
55 | | TableCellContentElement::TableCellContentElement(IWORKXMLParserState &state) |
56 | 0 | : IWORKXMLElementContextBase(state) |
57 | 0 | { |
58 | 0 | if (isCollector()) |
59 | 0 | { |
60 | 0 | assert(!getState().m_currentText); |
61 | 0 | getState().m_currentText = getCollector().createText(getState().m_langManager, false); |
62 | 0 | } |
63 | 0 | } |
64 | | |
65 | | void TableCellContentElement::attribute(const int name, const char *const value) |
66 | 0 | { |
67 | 0 | switch (name) |
68 | 0 | { |
69 | 0 | case +IWORKToken::ID | IWORKToken::NS_URI_SFA : |
70 | 0 | IWORKXMLElementContextBase::attribute(name, value); |
71 | 0 | break; |
72 | 0 | default : |
73 | 0 | ETONYEK_DEBUG_MSG(("TableCellContentElement::attribute[IWORKTableInfoElement.cpp]: find some unknown attribute\n")); |
74 | 0 | break; |
75 | 0 | } |
76 | 0 | } |
77 | | |
78 | | IWORKXMLContextPtr_t TableCellContentElement::element(const int name) |
79 | 0 | { |
80 | 0 | switch (name) |
81 | 0 | { |
82 | 0 | case +IWORKToken::text_storage | IWORKToken::NS_URI_SF : |
83 | 0 | getState().m_tableData->m_type = IWORK_CELL_TYPE_TEXT; |
84 | 0 | return std::make_shared<IWORKTextStorageElement>(getState()); |
85 | 0 | default : |
86 | 0 | ETONYEK_DEBUG_MSG(("TableCellContentElement::element[IWORKTableInfoElement.cpp]: find some unknown element\n")); |
87 | 0 | break; |
88 | 0 | } |
89 | | |
90 | 0 | return IWORKXMLContextPtr_t(); |
91 | 0 | } |
92 | | |
93 | | } |
94 | | |
95 | | namespace |
96 | | { |
97 | | |
98 | | class TableCellValueElement : public IWORKXMLEmptyContextBase |
99 | | { |
100 | | public: |
101 | | explicit TableCellValueElement(IWORKXMLParserState &state); |
102 | | |
103 | | private: |
104 | | void attribute(int name, const char *value) override; |
105 | | IWORKXMLContextPtr_t element(int name) override; |
106 | | void endOfElement() override; |
107 | | |
108 | | boost::optional<double> m_value; |
109 | | }; |
110 | | |
111 | | TableCellValueElement::TableCellValueElement(IWORKXMLParserState &state) |
112 | 0 | : IWORKXMLEmptyContextBase(state) |
113 | 0 | , m_value() |
114 | 0 | { |
115 | 0 | } |
116 | | |
117 | | void TableCellValueElement::attribute(const int name, const char *const value) |
118 | 0 | { |
119 | 0 | ETONYEK_DEBUG_MSG(("TableCellValueElement::attribute[IWORKTableInfoElement.cpp]: find some unknown attribute\n")); |
120 | 0 | IWORKXMLEmptyContextBase::attribute(name, value); |
121 | 0 | } |
122 | | |
123 | | IWORKXMLContextPtr_t TableCellValueElement::element(const int name) |
124 | 0 | { |
125 | 0 | switch (name) |
126 | 0 | { |
127 | 0 | case +IWORKToken::number | IWORKToken::NS_URI_SF : |
128 | 0 | getState().m_tableData->m_type = IWORK_CELL_TYPE_NUMBER; |
129 | 0 | return std::make_shared<IWORKNumberElement<double> >(getState(), m_value); |
130 | 0 | default: |
131 | 0 | ETONYEK_DEBUG_MSG(("TableCellValueElement::element[IWORKTableInfoElement.cpp]: find some unknown element\n")); |
132 | 0 | } |
133 | 0 | return IWORKXMLContextPtr_t(); |
134 | 0 | } |
135 | | |
136 | | void TableCellValueElement::endOfElement() |
137 | 0 | { |
138 | 0 | if (m_value) |
139 | 0 | { |
140 | 0 | std::stringstream s; |
141 | 0 | s << get(m_value); |
142 | 0 | getState().m_tableData->m_content = s.str(); |
143 | 0 | } |
144 | 0 | } |
145 | | } |
146 | | |
147 | | namespace |
148 | | { |
149 | | class TableCellElement : public IWORKXMLEmptyContextBase |
150 | | { |
151 | | public: |
152 | | explicit TableCellElement(IWORKXMLParserState &state, boost::optional<IWORKTableCell> &value); |
153 | | private: |
154 | | void attribute(int name, const char *value) override; |
155 | | IWORKXMLContextPtr_t element(int name) override; |
156 | | void endOfElement() override; |
157 | | void emitCell(); |
158 | | |
159 | | boost::optional<IWORKTableCell> &m_value; |
160 | | boost::optional<ID_t> m_styleRef; |
161 | | boost::optional<ID_t> m_minXBorderRef, m_maxXBorderRef, m_minYBorderRef, m_maxYBorderRef; |
162 | | }; |
163 | | |
164 | | TableCellElement::TableCellElement(IWORKXMLParserState &state, boost::optional<IWORKTableCell> &value) |
165 | 0 | : IWORKXMLEmptyContextBase(state) |
166 | 0 | , m_value(value) |
167 | 0 | , m_styleRef() |
168 | 0 | , m_minXBorderRef() |
169 | 0 | , m_maxXBorderRef() |
170 | 0 | , m_minYBorderRef() |
171 | 0 | , m_maxYBorderRef() |
172 | 0 | { |
173 | 0 | m_value=IWORKTableCell(); |
174 | 0 | } |
175 | | |
176 | | void TableCellElement::attribute(const int name, const char *const value) |
177 | 0 | { |
178 | 0 | switch (name) |
179 | 0 | { |
180 | 0 | case +IWORKToken::tableCellPreferredHeight | IWORKToken::NS_URI_SF : |
181 | 0 | get(m_value).m_preferredHeight=try_double_cast(value); |
182 | 0 | break; |
183 | 0 | case +IWORKToken::ID | IWORKToken::NS_URI_SFA : // must we store this element ? |
184 | 0 | IWORKXMLEmptyContextBase::attribute(name, value); |
185 | 0 | break; |
186 | 0 | default : |
187 | 0 | ETONYEK_DEBUG_MSG(("TableCellElement::attribute[IWORKTableInfoElement.cpp]: find some unknown attribute\n")); |
188 | 0 | IWORKXMLEmptyContextBase::attribute(name, value); |
189 | 0 | } |
190 | 0 | } |
191 | | |
192 | | IWORKXMLContextPtr_t TableCellElement::element(const int name) |
193 | 0 | { |
194 | 0 | switch (name) |
195 | 0 | { |
196 | 0 | case +IWORKToken::tableCellStyle_ref | IWORKToken::NS_URI_SF : |
197 | 0 | return std::make_shared<IWORKRefContext>(getState(), m_styleRef); |
198 | 0 | case +IWORKToken::tableCellMinXSide_ref | IWORKToken::NS_URI_SF : |
199 | 0 | return std::make_shared<IWORKRefContext>(getState(), m_minXBorderRef); |
200 | 0 | case +IWORKToken::tableCellMaxXSide_ref | IWORKToken::NS_URI_SF : |
201 | 0 | return std::make_shared<IWORKRefContext>(getState(), m_maxXBorderRef); |
202 | 0 | case +IWORKToken::tableCellMinYSide_ref | IWORKToken::NS_URI_SF : |
203 | 0 | return std::make_shared<IWORKRefContext>(getState(), m_minYBorderRef); |
204 | 0 | case +IWORKToken::tableCellMaxYSide_ref | IWORKToken::NS_URI_SF : |
205 | 0 | return std::make_shared<IWORKRefContext>(getState(), m_maxYBorderRef); |
206 | 0 | case +IWORKToken::tableCellContent | IWORKToken::NS_URI_SF : |
207 | 0 | return std::make_shared<TableCellContentElement>(getState()); |
208 | 0 | case +IWORKToken::tableCellFormula | IWORKToken::NS_URI_SF : |
209 | 0 | return std::make_shared<IWORKTableCellFormulaElement>(getState()); |
210 | 0 | case +IWORKToken::tableCellValue | IWORKToken::NS_URI_SF : |
211 | 0 | return std::make_shared<TableCellValueElement>(getState()); |
212 | 0 | default: |
213 | 0 | ETONYEK_DEBUG_MSG(("TableCellElement::element[IWORKTableInfoElement.cpp]: find some unknown element\n")); |
214 | 0 | break; |
215 | 0 | } |
216 | 0 | return IWORKXMLContextPtr_t(); |
217 | 0 | } |
218 | | |
219 | | void TableCellElement::endOfElement() |
220 | 0 | { |
221 | 0 | IWORKTableCell &cell=get(m_value); |
222 | 0 | if (m_styleRef) |
223 | 0 | cell.m_style=getState().getStyleByName(get(m_styleRef).c_str(), getState().getDictionary().m_tableCellStyles); |
224 | 0 | for (int i=0; i<4; ++i) |
225 | 0 | { |
226 | 0 | boost::optional<ID_t> const &ref= |
227 | 0 | i==0 ? m_minXBorderRef : i==1 ? m_maxXBorderRef : i==2 ? m_minYBorderRef : m_maxYBorderRef; |
228 | 0 | if (!ref) continue; |
229 | 0 | const IWORKTableVectorMap_t::const_iterator it = getState().getDictionary().m_tableVectors.find(get(ref)); |
230 | 0 | if (it==getState().getDictionary().m_tableVectors.end()) |
231 | 0 | { |
232 | 0 | ETONYEK_DEBUG_MSG(("TableCellElement::endOfElement[IWORKTableInfoElement.cpp]: can not find vector %s\n", get(ref).c_str())); |
233 | 0 | } |
234 | 0 | else if (i==0) |
235 | 0 | cell.m_minXBorder=it->second; |
236 | 0 | else if (i==1) |
237 | 0 | cell.m_maxXBorder=it->second; |
238 | 0 | else if (i==2) |
239 | 0 | cell.m_minYBorder=it->second; |
240 | 0 | else |
241 | 0 | cell.m_maxYBorder=it->second; |
242 | 0 | } |
243 | 0 | if (getId()) |
244 | 0 | getState().getDictionary().m_tableCells[get(getId())]=cell; |
245 | 0 | emitCell(); |
246 | 0 | } |
247 | | |
248 | | void TableCellElement::emitCell() |
249 | 0 | { |
250 | 0 | const IWORKTableDataPtr_t tableData = getState().m_tableData; |
251 | 0 | IWORKTableCell &cell=get(m_value); |
252 | 0 | if (cell.m_minXBorder.m_along && cell.m_minYBorder.m_along |
253 | 0 | && tableData->m_positionToHorizontalLineMap.find(get(cell.m_minXBorder.m_along)) |
254 | 0 | != tableData->m_positionToHorizontalLineMap.end() |
255 | 0 | && tableData->m_positionToVerticalLineMap.find(get(cell.m_minYBorder.m_along)) |
256 | 0 | != tableData->m_positionToVerticalLineMap.end()) |
257 | 0 | { |
258 | | // column |
259 | 0 | unsigned column=tableData->m_positionToHorizontalLineMap.find(get(cell.m_minXBorder.m_along))->second; |
260 | 0 | unsigned columnSpan=0; |
261 | 0 | auto numColumns=(unsigned) tableData->m_columnSizes.size(); |
262 | 0 | if (cell.m_maxXBorder.m_along && tableData->m_positionToHorizontalLineMap.find(get(cell.m_maxXBorder.m_along)) |
263 | 0 | != tableData->m_positionToHorizontalLineMap.end()) |
264 | 0 | columnSpan=unsigned(tableData->m_positionToHorizontalLineMap.find(get(cell.m_maxXBorder.m_along))->second-column); |
265 | 0 | if (columnSpan+column>numColumns) |
266 | 0 | { |
267 | 0 | ETONYEK_DEBUG_MSG(("TableCellElement::endOfElement[IWORKTableInfoElement.cpp]: column span seems bad\n")); |
268 | 0 | columnSpan=0; |
269 | 0 | } |
270 | | // row |
271 | 0 | unsigned row=tableData->m_positionToVerticalLineMap.find(get(cell.m_minYBorder.m_along))->second; |
272 | 0 | unsigned rowSpan=0; |
273 | 0 | auto numRows=(unsigned) tableData->m_rowSizes.size(); |
274 | 0 | if (cell.m_maxYBorder.m_along && tableData->m_positionToVerticalLineMap.find(get(cell.m_maxYBorder.m_along)) |
275 | 0 | != tableData->m_positionToVerticalLineMap.end()) |
276 | 0 | rowSpan=unsigned(tableData->m_positionToVerticalLineMap.find(get(cell.m_maxYBorder.m_along))->second-row); |
277 | 0 | if (rowSpan+row>numRows) |
278 | 0 | { |
279 | 0 | ETONYEK_DEBUG_MSG(("TableCellElement::endOfElement[IWORKTableInfoElement.cpp]: row span seems bad\n")); |
280 | 0 | rowSpan=0; |
281 | 0 | } |
282 | 0 | IWORKTextPtr_t text(getState().m_currentText); |
283 | 0 | getState().m_currentText.reset(); |
284 | 0 | if (bool(tableData->m_content) && tableData->m_type == IWORK_CELL_TYPE_TEXT) |
285 | 0 | { |
286 | 0 | text = getCollector().createText(getState().m_langManager); |
287 | 0 | text->insertText(get(tableData->m_content)); |
288 | 0 | text->flushParagraph(); |
289 | 0 | } |
290 | 0 | getState().m_currentTable->insertCell( |
291 | 0 | column, row, |
292 | 0 | tableData->m_content, text, tableData->m_dateTime, |
293 | 0 | columnSpan ? columnSpan : 1, rowSpan ? rowSpan : 1, |
294 | 0 | tableData->m_formula, tableData->m_formulaHC, cell.m_style, tableData->m_type |
295 | 0 | ); |
296 | | // finally update the grid |
297 | 0 | if (rowSpan && cell.m_minXBorder.m_style) |
298 | 0 | { |
299 | 0 | if (tableData->m_verticalLines.find(column)==tableData->m_verticalLines.end()) |
300 | 0 | tableData->m_verticalLines.insert(IWORKGridLineMap_t::value_type(column,IWORKGridLine_t(0, numRows+1, IWORKStylePtr_t()))); |
301 | 0 | IWORKGridLine_t &cLine=tableData->m_verticalLines.find(column)->second; |
302 | 0 | cLine.insert_back(row, row+rowSpan, cell.m_minXBorder.m_style); |
303 | 0 | } |
304 | 0 | if (rowSpan && columnSpan && cell.m_maxXBorder.m_style) |
305 | 0 | { |
306 | 0 | if (tableData->m_verticalLines.find(column+columnSpan)==tableData->m_verticalLines.end()) |
307 | 0 | tableData->m_verticalLines.insert(IWORKGridLineMap_t::value_type(column+columnSpan,IWORKGridLine_t(0, numRows+1, IWORKStylePtr_t()))); |
308 | 0 | IWORKGridLine_t &cLine=tableData->m_verticalLines.find(column+columnSpan)->second; |
309 | 0 | cLine.insert_back(row, row+rowSpan, cell.m_maxXBorder.m_style); |
310 | 0 | } |
311 | 0 | if (columnSpan && cell.m_minYBorder.m_style) |
312 | 0 | { |
313 | 0 | if (tableData->m_horizontalLines.find(row)==tableData->m_horizontalLines.end()) |
314 | 0 | tableData->m_horizontalLines.insert(IWORKGridLineMap_t::value_type(row,IWORKGridLine_t(0, numColumns+1, IWORKStylePtr_t()))); |
315 | 0 | IWORKGridLine_t &cLine=tableData->m_horizontalLines.find(row)->second; |
316 | 0 | cLine.insert_back(column, column+columnSpan, cell.m_minYBorder.m_style); |
317 | 0 | } |
318 | 0 | if (rowSpan && columnSpan && cell.m_maxYBorder.m_style) |
319 | 0 | { |
320 | 0 | if (tableData->m_horizontalLines.find(row+rowSpan)==tableData->m_horizontalLines.end()) |
321 | 0 | tableData->m_horizontalLines.insert(IWORKGridLineMap_t::value_type(row+rowSpan,IWORKGridLine_t(0, numColumns+1, IWORKStylePtr_t()))); |
322 | 0 | IWORKGridLine_t &cLine=tableData->m_horizontalLines.find(row+rowSpan)->second; |
323 | 0 | cLine.insert_back(column, column+columnSpan, cell.m_maxYBorder.m_style); |
324 | 0 | } |
325 | 0 | } |
326 | 0 | else |
327 | 0 | { |
328 | 0 | ETONYEK_DEBUG_MSG(("TableCellElement::endOfElement[IWORKTableInfoElement.cpp]: can not find cell positions\n")); |
329 | 0 | } |
330 | | |
331 | | // reset cell attributes |
332 | 0 | tableData->m_columnSpan.reset(); |
333 | 0 | tableData->m_rowSpan.reset(); |
334 | 0 | tableData->m_content.reset(); |
335 | 0 | tableData->m_dateTime.reset(); |
336 | 0 | tableData->m_formula.reset(); |
337 | 0 | tableData->m_style.reset(); |
338 | 0 | tableData->m_type = IWORK_CELL_TYPE_TEXT; |
339 | 0 | } |
340 | | } |
341 | | |
342 | | namespace |
343 | | { |
344 | | typedef IWORKMutableArrayElement<IWORKTableCell, TableCellElement, IWORKPushCollector, +IWORKToken::NS_URI_SF | IWORKToken::table_cell, +IWORKToken::NS_URI_SF | IWORKToken::table_cell_ref> TableCellArrayElement; |
345 | | } |
346 | | |
347 | | namespace |
348 | | { |
349 | | class TableModelCellsElement : public IWORKXMLEmptyContextBase |
350 | | { |
351 | | public: |
352 | | explicit TableModelCellsElement(IWORKXMLParserState &state, std::deque<IWORKTableCell> &colCell, std::deque<IWORKTableCell> &rowCell); |
353 | | private: |
354 | | IWORKXMLContextPtr_t element(int name) override; |
355 | | void endOfElement() override; |
356 | | |
357 | | std::unordered_map<ID_t, std::deque<IWORKTableCell> > m_dict; |
358 | | std::deque<IWORKTableCell> &m_columnsCell; |
359 | | std::deque<IWORKTableCell> &m_rowsCell; |
360 | | }; |
361 | | |
362 | | TableModelCellsElement::TableModelCellsElement(IWORKXMLParserState &state, std::deque<IWORKTableCell> &colCell, std::deque<IWORKTableCell> &rowCell) |
363 | 0 | : IWORKXMLEmptyContextBase(state) |
364 | 0 | , m_dict() |
365 | 0 | , m_columnsCell(colCell) |
366 | 0 | , m_rowsCell(rowCell) |
367 | 0 | { |
368 | 0 | } |
369 | | |
370 | | IWORKXMLContextPtr_t TableModelCellsElement::element(const int name) |
371 | 0 | { |
372 | 0 | switch (name) |
373 | 0 | { |
374 | 0 | case +IWORKToken::tableCellArrayCellsByColumn | IWORKToken::NS_URI_SF : |
375 | 0 | return std::make_shared<TableCellArrayElement>(getState(), m_dict, getState().getDictionary().m_tableCells, m_columnsCell); |
376 | 0 | case +IWORKToken::tableCellArrayCellsByRow | IWORKToken::NS_URI_SF : |
377 | 0 | return std::make_shared<TableCellArrayElement>(getState(), m_dict, getState().getDictionary().m_tableCells, m_rowsCell); |
378 | 0 | default: |
379 | 0 | ETONYEK_DEBUG_MSG(("TableModelCellsElement::element[IWORKTableInfoElement.cpp]: find some unknown element\n")); |
380 | 0 | break; |
381 | 0 | } |
382 | 0 | return IWORKXMLContextPtr_t(); |
383 | 0 | } |
384 | | |
385 | | void TableModelCellsElement::endOfElement() |
386 | 0 | { |
387 | 0 | } |
388 | | } |
389 | | |
390 | | namespace |
391 | | { |
392 | | class TableVectorElement : public IWORKXMLEmptyContextBase |
393 | | { |
394 | | public: |
395 | | explicit TableVectorElement(IWORKXMLParserState &state, boost::optional<IWORKTableVector> &value); |
396 | | private: |
397 | | void attribute(int name, const char *value) override; |
398 | | IWORKXMLContextPtr_t element(int name) override; |
399 | | void endOfElement() override; |
400 | | |
401 | | boost::optional<IWORKTableVector> &m_value; |
402 | | boost::optional<ID_t> m_styleRef; |
403 | | }; |
404 | | |
405 | | TableVectorElement::TableVectorElement(IWORKXMLParserState &state, boost::optional<IWORKTableVector> &value) |
406 | 0 | : IWORKXMLEmptyContextBase(state) |
407 | 0 | , m_value(value) |
408 | 0 | , m_styleRef() |
409 | 0 | { |
410 | 0 | m_value=IWORKTableVector(); |
411 | 0 | } |
412 | | |
413 | | void TableVectorElement::attribute(const int name, const char *const value) |
414 | 0 | { |
415 | 0 | switch (name) |
416 | 0 | { |
417 | 0 | case +IWORKToken::tableVectorAlong | IWORKToken::NS_URI_SF : |
418 | 0 | get(m_value).m_along=try_double_cast(value); |
419 | 0 | break; |
420 | 0 | case +IWORKToken::tableVectorAxis | IWORKToken::NS_URI_SF : |
421 | 0 | get(m_value).m_axis=try_int_cast(value); |
422 | 0 | break; |
423 | 0 | case +IWORKToken::tableVectorBegin | IWORKToken::NS_URI_SF : |
424 | 0 | get(m_value).m_beginCell=try_int_cast(value); |
425 | 0 | break; |
426 | 0 | case +IWORKToken::tableVectorEnd | IWORKToken::NS_URI_SF : |
427 | 0 | get(m_value).m_endCell=try_int_cast(value); |
428 | 0 | break; |
429 | 0 | case +IWORKToken::ID | IWORKToken::NS_URI_SFA : |
430 | 0 | IWORKXMLEmptyContextBase::attribute(name, value); |
431 | 0 | break; |
432 | 0 | default : |
433 | 0 | ETONYEK_DEBUG_MSG(("TableVectorElement::attribute[IWORKTableInfoElement.cpp]: find some unknown attribute\n")); |
434 | 0 | IWORKXMLEmptyContextBase::attribute(name, value); |
435 | 0 | } |
436 | 0 | } |
437 | | |
438 | | IWORKXMLContextPtr_t TableVectorElement::element(const int name) |
439 | 0 | { |
440 | 0 | switch (name) |
441 | 0 | { |
442 | 0 | case +IWORKToken::tableVectorStyle_ref | IWORKToken::NS_URI_SF : |
443 | 0 | return std::make_shared<IWORKRefContext>(getState(), m_styleRef); |
444 | 0 | default: |
445 | 0 | ETONYEK_DEBUG_MSG(("TableVectorElement::element[IWORKTableInfoElement.cpp]: find some unknown element\n")); |
446 | 0 | break; |
447 | 0 | } |
448 | 0 | return IWORKXMLContextPtr_t(); |
449 | 0 | } |
450 | | |
451 | | void TableVectorElement::endOfElement() |
452 | 0 | { |
453 | 0 | if (m_styleRef) |
454 | 0 | get(m_value).m_style=getState().getStyleByName(get(m_styleRef).c_str(), getState().getDictionary().m_tableVectorStyles); |
455 | 0 | if (getId()) |
456 | 0 | getState().getDictionary().m_tableVectors[get(getId())]=get(m_value); |
457 | 0 | } |
458 | | } |
459 | | |
460 | | namespace |
461 | | { |
462 | | typedef IWORKMutableArrayElement<IWORKTableVector, TableVectorElement, IWORKPushCollector, +IWORKToken::NS_URI_SF | IWORKToken::table_vector> TableVectorArrayElement; |
463 | | } |
464 | | |
465 | | namespace |
466 | | { |
467 | | class TableModelVectorsElement : public IWORKXMLEmptyContextBase |
468 | | { |
469 | | public: |
470 | | explicit TableModelVectorsElement(IWORKXMLParserState &state, std::deque<IWORKTableVector> &colVector, std::deque<IWORKTableVector> &rowVector); |
471 | | private: |
472 | | IWORKXMLContextPtr_t element(int name) override; |
473 | | void endOfElement() override; |
474 | | |
475 | | std::unordered_map<ID_t, std::deque<IWORKTableVector> > m_dict; |
476 | | std::deque<IWORKTableVector> &m_columnsVector; |
477 | | std::deque<IWORKTableVector> &m_rowsVector; |
478 | | }; |
479 | | |
480 | | TableModelVectorsElement::TableModelVectorsElement(IWORKXMLParserState &state, std::deque<IWORKTableVector> &colVector, std::deque<IWORKTableVector> &rowVector) |
481 | 0 | : IWORKXMLEmptyContextBase(state) |
482 | 0 | , m_dict() |
483 | 0 | , m_columnsVector(colVector) |
484 | 0 | , m_rowsVector(rowVector) |
485 | 0 | { |
486 | 0 | } |
487 | | |
488 | | IWORKXMLContextPtr_t TableModelVectorsElement::element(const int name) |
489 | 0 | { |
490 | 0 | switch (name) |
491 | 0 | { |
492 | 0 | case +IWORKToken::tableVectorArrayColumnVectors | IWORKToken::NS_URI_SF : |
493 | 0 | return std::make_shared<TableVectorArrayElement>(getState(), m_dict, getState().getDictionary().m_tableVectors, m_columnsVector); |
494 | 0 | case +IWORKToken::tableVectorArrayRowVectors | IWORKToken::NS_URI_SF : |
495 | 0 | return std::make_shared<TableVectorArrayElement>(getState(), m_dict, getState().getDictionary().m_tableVectors, m_rowsVector); |
496 | 0 | default: |
497 | 0 | ETONYEK_DEBUG_MSG(("TableModelVectorsElement::element[IWORKTableInfoElement.cpp]: find some unknown element\n")); |
498 | 0 | break; |
499 | 0 | } |
500 | 0 | return IWORKXMLContextPtr_t(); |
501 | 0 | } |
502 | | |
503 | | void TableModelVectorsElement::endOfElement() |
504 | 0 | { |
505 | 0 | const IWORKTableDataPtr_t tableData = getState().m_tableData; |
506 | | |
507 | | // normally the columns and rows are sorted |
508 | 0 | double pos=0; |
509 | 0 | bool posSet=false; |
510 | 0 | unsigned line=0; |
511 | 0 | for (auto &col : m_columnsVector) |
512 | 0 | { |
513 | 0 | if (!col.m_along) |
514 | 0 | continue; |
515 | 0 | if (!posSet) |
516 | 0 | { |
517 | 0 | pos=get(col.m_along); |
518 | 0 | posSet=true; |
519 | 0 | tableData->m_positionToHorizontalLineMap[pos]=line; |
520 | 0 | } |
521 | 0 | else if (get(col.m_along)>pos) |
522 | 0 | { |
523 | 0 | tableData->m_columnSizes.push_back(IWORKColumnRowSize(get(col.m_along)-pos)); |
524 | 0 | pos=get(col.m_along); |
525 | 0 | tableData->m_positionToHorizontalLineMap[pos]=++line; |
526 | 0 | } |
527 | 0 | } |
528 | 0 | posSet=false; |
529 | 0 | line=0; |
530 | 0 | for (auto &row : m_rowsVector) |
531 | 0 | { |
532 | 0 | if (!row.m_along) |
533 | 0 | continue; |
534 | 0 | if (!posSet) |
535 | 0 | { |
536 | 0 | pos=get(row.m_along); |
537 | 0 | posSet=true; |
538 | 0 | tableData->m_positionToVerticalLineMap[pos]=line; |
539 | 0 | } |
540 | 0 | else if (get(row.m_along)>pos) |
541 | 0 | { |
542 | 0 | tableData->m_rowSizes.push_back(IWORKColumnRowSize(get(row.m_along)-pos)); |
543 | 0 | pos=get(row.m_along); |
544 | 0 | tableData->m_positionToVerticalLineMap[pos]=++line; |
545 | 0 | } |
546 | 0 | } |
547 | 0 | if (getState().m_currentTable) |
548 | 0 | getState().m_currentTable->setSizes(getState().m_tableData->m_columnSizes, getState().m_tableData->m_rowSizes); |
549 | 0 | } |
550 | | } |
551 | | |
552 | | namespace |
553 | | { |
554 | | class TableInfoTableElement : public IWORKXMLElementContextBase |
555 | | { |
556 | | public: |
557 | | explicit TableInfoTableElement(IWORKXMLParserState &state); |
558 | | |
559 | | private: |
560 | | void attribute(int name, const char *value) override; |
561 | | void startOfElement() override; |
562 | | IWORKXMLContextPtr_t element(int name) override; |
563 | | void endOfElement() override; |
564 | | |
565 | | private: |
566 | | boost::optional<ID_t> m_id; |
567 | | boost::optional<std::string> m_tableId; |
568 | | boost::optional<ID_t> m_styleRef; |
569 | | bool m_hasHeaderColumn; |
570 | | bool m_hasHeaderRow; |
571 | | std::deque<IWORKTableCell> m_columnsCell; |
572 | | std::deque<IWORKTableCell> m_rowsCell; |
573 | | std::deque<IWORKTableVector> m_columnsVector; |
574 | | std::deque<IWORKTableVector> m_rowsVector; |
575 | | }; |
576 | | |
577 | | TableInfoTableElement::TableInfoTableElement(IWORKXMLParserState &state) |
578 | 0 | : IWORKXMLElementContextBase(state) |
579 | 0 | , m_id() |
580 | 0 | , m_tableId() |
581 | 0 | , m_styleRef() |
582 | 0 | , m_hasHeaderColumn(false) |
583 | 0 | , m_hasHeaderRow(false) |
584 | 0 | , m_columnsCell() |
585 | 0 | , m_rowsCell() |
586 | 0 | , m_columnsVector() |
587 | 0 | , m_rowsVector() |
588 | 0 | { |
589 | 0 | } |
590 | | |
591 | | void TableInfoTableElement::attribute(const int name, const char *value) |
592 | 0 | { |
593 | 0 | switch (name) |
594 | 0 | { |
595 | 0 | case +IWORKToken::ID | IWORKToken::NS_URI_SFA : |
596 | 0 | m_id=value; |
597 | 0 | break; |
598 | 0 | case +IWORKToken::tableModelIsHeaderColumn | IWORKToken::NS_URI_SF : |
599 | 0 | m_hasHeaderColumn =bool_cast(value); |
600 | 0 | break; |
601 | 0 | case +IWORKToken::tableModelIsHeaderRow | IWORKToken::NS_URI_SF : |
602 | 0 | m_hasHeaderRow =bool_cast(value); |
603 | 0 | break; |
604 | 0 | default: |
605 | | // also tableModelResize, tableIsForPasteboardOnly |
606 | 0 | break; |
607 | 0 | } |
608 | 0 | } |
609 | | |
610 | | void TableInfoTableElement::startOfElement() |
611 | 0 | { |
612 | 0 | getState().m_tableData = std::make_shared<IWORKTableData>(); |
613 | 0 | } |
614 | | |
615 | | IWORKXMLContextPtr_t TableInfoTableElement::element(const int name) |
616 | 0 | { |
617 | 0 | switch (name) |
618 | 0 | { |
619 | 0 | case +IWORKToken::tableModelStyle_ref | IWORKToken::NS_URI_SF : |
620 | 0 | return std::make_shared<IWORKRefContext>(getState(), m_styleRef); |
621 | 0 | case +IWORKToken::tableModelPartitionSource | IWORKToken::NS_URI_SF : // contains id + frame data |
622 | 0 | break; |
623 | 0 | case +IWORKToken::tableModelVectors | IWORKToken::NS_URI_SF : |
624 | 0 | return std::make_shared<TableModelVectorsElement>(getState(), m_columnsVector, m_rowsVector); |
625 | 0 | case +IWORKToken::tableModelCells | IWORKToken::NS_URI_SF : |
626 | 0 | return std::make_shared<TableModelCellsElement>(getState(), m_columnsCell, m_rowsCell); |
627 | 0 | case +IWORKToken::tableModelTableID | IWORKToken::NS_URI_SF : |
628 | 0 | return std::make_shared<IWORKStringElement>(getState(), m_tableId); |
629 | 0 | default: |
630 | 0 | ETONYEK_DEBUG_MSG(("TableInfoTableElement::element[IWORKTableInfoElement.cpp]: find some unknown element\n")); |
631 | 0 | break; |
632 | 0 | } |
633 | 0 | return IWORKXMLContextPtr_t(); |
634 | 0 | } |
635 | | |
636 | | void TableInfoTableElement::endOfElement() |
637 | 0 | { |
638 | 0 | if (bool(getState().m_currentTable)) |
639 | 0 | { |
640 | 0 | auto const &table=getState().m_currentTable; |
641 | 0 | if (m_styleRef) |
642 | 0 | { |
643 | 0 | IWORKStylePtr_t style; |
644 | 0 | style=getState().getStyleByName(get(m_styleRef).c_str(), getState().getDictionary().m_tableStyles); |
645 | 0 | table->setStyle(style); |
646 | 0 | } |
647 | 0 | table->setRepeated(m_hasHeaderColumn, m_hasHeaderRow); |
648 | 0 | table->setHeaders(0, 0, 0); |
649 | 0 | } |
650 | 0 | } |
651 | | } |
652 | | |
653 | | IWORKTableInfoElement::IWORKTableInfoElement(IWORKXMLParserState &state) |
654 | 0 | : IWORKXMLElementContextBase(state) |
655 | 0 | , m_style() |
656 | 0 | , m_wrap() |
657 | 0 | { |
658 | 0 | } |
659 | | |
660 | | void IWORKTableInfoElement::startOfElement() |
661 | 0 | { |
662 | 0 | assert(!getState().m_currentTable); |
663 | 0 | getState().m_currentTable = getCollector().createTable(getState().m_tableNameMap, getState().m_formatNameMap, getState().m_langManager); |
664 | 0 | if (isCollector()) |
665 | 0 | getCollector().startLevel(); |
666 | 0 | } |
667 | | |
668 | | IWORKXMLContextPtr_t IWORKTableInfoElement::element(const int name) |
669 | 0 | { |
670 | 0 | switch (name) |
671 | 0 | { |
672 | 0 | case +IWORKToken::geometry | IWORKToken::NS_URI_SF : |
673 | 0 | return std::make_shared<IWORKGeometryElement>(getState()); |
674 | 0 | case +IWORKToken::style | IWORKToken::NS_URI_SF : |
675 | 0 | return std::make_shared<TableStyleContext>(getState(), m_style, getState().getDictionary().m_tableStyles); |
676 | 0 | case +IWORKToken::tableInfoTable | IWORKToken::NS_URI_SF : |
677 | 0 | return std::make_shared<TableInfoTableElement>(getState()); |
678 | 0 | case +IWORKToken::NS_URI_SF | IWORKToken::wrap : // USEME |
679 | 0 | return std::make_shared<IWORKWrapElement>(getState(), m_wrap); |
680 | 0 | default: |
681 | 0 | ETONYEK_DEBUG_MSG(("IWORKTableInfoElement::element: find some unknown element\n")); |
682 | 0 | } |
683 | | |
684 | 0 | return IWORKXMLContextPtr_t(); |
685 | 0 | } |
686 | | |
687 | | void IWORKTableInfoElement::endOfElement() |
688 | 0 | { |
689 | 0 | if (!isCollector()) |
690 | 0 | return; |
691 | | |
692 | 0 | if (m_style && getState().m_currentTable) |
693 | 0 | getState().m_currentTable->setStyle(m_style); |
694 | 0 | getCollector().collectTable(getState().m_currentTable); |
695 | 0 | getState().m_currentTable.reset(); |
696 | |
|
697 | 0 | getCollector().endLevel(); |
698 | 0 | } |
699 | | |
700 | | } |
701 | | |
702 | | /* vim:set shiftwidth=2 softtabstop=2 expandtab: */ |