/src/libwps/src/lib/WKSChart.h
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ |
2 | | /* libwps |
3 | | * Version: MPL 2.0 / LGPLv2.1+ |
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 | | * Major Contributor(s): |
10 | | * Copyright (C) 2006, 2007 Andrew Ziem |
11 | | * Copyright (C) 2004 Marc Maurer (uwog@uwog.net) |
12 | | * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch) |
13 | | * |
14 | | * For minor contributions see the git repository. |
15 | | * |
16 | | * Alternatively, the contents of this file may be used under the terms |
17 | | * of the GNU Lesser General Public License Version 2.1 or later |
18 | | * (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are |
19 | | * applicable instead of those above. |
20 | | */ |
21 | | |
22 | | /* |
23 | | * Structure to store and construct a chart |
24 | | * |
25 | | */ |
26 | | |
27 | | #ifndef WKS_CHART |
28 | | # define WKS_CHART |
29 | | |
30 | | #include <iostream> |
31 | | #include <vector> |
32 | | #include <map> |
33 | | |
34 | | #include "libwps_internal.h" |
35 | | |
36 | | #include "WPSEntry.h" |
37 | | #include "WPSFont.h" |
38 | | #include "WPSGraphicStyle.h" |
39 | | |
40 | | namespace WKSChartInternal |
41 | | { |
42 | | class SubDocument; |
43 | | } |
44 | | /** a class used to store a chart associated to a spreadsheet .... */ |
45 | | class WKSChart |
46 | | { |
47 | | friend class WKSChartInternal::SubDocument; |
48 | | public: |
49 | | //! a cell position |
50 | | struct Position |
51 | | { |
52 | | //! constructor |
53 | | explicit Position(Vec2i pos=Vec2i(-1,-1), librevenge::RVNGString const &sheetName="") |
54 | 10.4M | : m_pos(pos) |
55 | 10.4M | , m_sheetName(sheetName) |
56 | 10.4M | , m_sheetId(-1) |
57 | 10.4M | { |
58 | 10.4M | } |
59 | | //! return true if the position is valid |
60 | | bool valid() const |
61 | 3.10M | { |
62 | 3.10M | return m_pos[0]>=0 && m_pos[1]>=0 && (!m_sheetName.empty() || m_sheetId>=0); |
63 | 3.10M | } |
64 | | //! return true if the position is valid |
65 | | bool valid(Position const &maxPos) const |
66 | 1.56M | { |
67 | 1.56M | return valid() && maxPos.valid() && maxPos.m_pos[0]>=m_pos[0] && maxPos.m_pos[1]>=m_pos[1]; |
68 | 1.56M | } |
69 | | //! return the cell name |
70 | | librevenge::RVNGString getCellName() const; |
71 | | //! operator<< |
72 | | friend std::ostream &operator<<(std::ostream &o, Position const &pos); |
73 | | //! operator== |
74 | | bool operator==(Position const &pos) const |
75 | 176k | { |
76 | 176k | return m_pos==pos.m_pos && m_sheetName==pos.m_sheetName && m_sheetId==pos.m_sheetId; |
77 | 176k | } |
78 | | //! operator!= |
79 | | bool operator!=(Position const &pos) const |
80 | 176k | { |
81 | 176k | return !(operator==(pos)); |
82 | 176k | } |
83 | | //! the cell column and row |
84 | | Vec2i m_pos; |
85 | | //! the cell sheet name |
86 | | librevenge::RVNGString m_sheetName; |
87 | | /** the cell sheet id |
88 | | \note can be used temporary if the sheet name is not known when reading a position, |
89 | | but you must before sending a chart, go through such positions to set the final |
90 | | spreadsheet name |
91 | | */ |
92 | | int m_sheetId; |
93 | | }; |
94 | | //! a axis in a chart |
95 | | struct Axis |
96 | | { |
97 | | //! the axis content |
98 | | enum Type { A_None, A_Numeric, A_Logarithmic, A_Sequence, A_Sequence_Skip_Empty }; |
99 | | //! constructor |
100 | | Axis(); |
101 | | //! destructor |
102 | | ~Axis(); |
103 | | //! add content to the propList |
104 | | void addContentTo(int coord, librevenge::RVNGPropertyList &propList) const; |
105 | | //! add style to the propList |
106 | | void addStyleTo(librevenge::RVNGPropertyList &propList) const; |
107 | | //! operator<< |
108 | | friend std::ostream &operator<<(std::ostream &o, Axis const &axis); |
109 | | //! the sequence type |
110 | | Type m_type; |
111 | | //! automatic scaling (or manual) |
112 | | bool m_automaticScaling; |
113 | | //! the minimum, maximum scaling(if manual) |
114 | | Vec2f m_scaling; |
115 | | //! show or not the grid |
116 | | bool m_showGrid; |
117 | | //! show or not the label |
118 | | bool m_showLabel; |
119 | | //! the label range if defined |
120 | | Position m_labelRanges[2]; |
121 | | |
122 | | //! show or not the title/subtitle |
123 | | bool m_showTitle; |
124 | | //! the title cell range |
125 | | Position m_titleRange; |
126 | | //! the title label |
127 | | librevenge::RVNGString m_title; |
128 | | //! the subtitle label |
129 | | librevenge::RVNGString m_subTitle; |
130 | | //! the graphic style |
131 | | WPSGraphicStyle m_style; |
132 | | }; |
133 | | //! a legend in a chart |
134 | | struct Legend |
135 | | { |
136 | | //! constructor |
137 | | Legend() |
138 | 114k | : m_show(false) |
139 | 114k | , m_autoPosition(true) |
140 | 114k | , m_relativePosition(WPSBorder::RightBit) |
141 | 114k | , m_position(0,0) |
142 | 114k | , m_font() |
143 | 114k | , m_style() |
144 | 114k | { |
145 | 114k | } |
146 | | //! add content to the propList |
147 | | void addContentTo(librevenge::RVNGPropertyList &propList) const; |
148 | | //! add style to the propList |
149 | | void addStyleTo(librevenge::RVNGPropertyList &propList) const; |
150 | | //! operator<< |
151 | | friend std::ostream &operator<<(std::ostream &o, Legend const &legend); |
152 | | //! show or not the legend |
153 | | bool m_show; |
154 | | //! automatic position |
155 | | bool m_autoPosition; |
156 | | //! the automatic position libwps::LeftBit|... |
157 | | int m_relativePosition; |
158 | | //! the position in points |
159 | | Vec2f m_position; |
160 | | //! the font |
161 | | WPSFont m_font; |
162 | | //! the graphic style |
163 | | WPSGraphicStyle m_style; |
164 | | }; |
165 | | //! a serie in a chart |
166 | | struct Serie |
167 | | { |
168 | | //! the series type |
169 | | enum Type { S_Area, S_Bar, S_Bubble, S_Circle, S_Column, S_Gantt, S_Line, S_Radar, S_Ring, S_Scatter, S_Stock, S_Surface }; |
170 | | //! the point type |
171 | | enum PointType |
172 | | { |
173 | | P_None=0, P_Automatic, P_Square, P_Diamond, P_Arrow_Down, |
174 | | P_Arrow_Up, P_Arrow_Right, P_Arrow_Left, P_Bow_Tie, P_Hourglass, |
175 | | P_Circle, P_Star, P_X, P_Plus, P_Asterisk, |
176 | | P_Horizontal_Bar, P_Vertical_Bar |
177 | | }; |
178 | | //! constructor |
179 | | Serie(); |
180 | 15.5k | Serie(Serie const &)=default; |
181 | | Serie(Serie &&)=default; |
182 | | Serie &operator=(Serie const &)=default; |
183 | 1.89M | Serie &operator=(Serie &&)=default; |
184 | | //! destructor |
185 | | virtual ~Serie(); |
186 | | //! return true if the serie style is 1D |
187 | | bool is1DStyle() const |
188 | 757k | { |
189 | 757k | return m_type==S_Line || m_type==S_Radar || (m_type==S_Scatter && m_pointType==P_None); |
190 | 757k | } |
191 | | //! set the primary color |
192 | | void setPrimaryColor(WPSColor const &color, float opacity = 1, bool force1D=false) |
193 | 194k | { |
194 | 194k | if (force1D || is1DStyle()) |
195 | 2.44k | m_style.m_lineColor=color; |
196 | 191k | else |
197 | 191k | m_style.setSurfaceColor(color, opacity); |
198 | 194k | } |
199 | | //! set the primary pattern |
200 | | void setPrimaryPattern(WPSGraphicStyle::Pattern const &pattern, bool force1D=false); |
201 | | //! set the secondary color |
202 | | void setSecondaryColor(WPSColor const &color) |
203 | 196k | { |
204 | 196k | if (!is1DStyle()) |
205 | 194k | m_style.m_lineColor=color; |
206 | 196k | } |
207 | | //! return true if the serie is valid |
208 | | bool valid() const |
209 | 154k | { |
210 | 154k | return m_ranges[0].valid(m_ranges[0]); |
211 | 154k | } |
212 | | //! add content to the propList |
213 | | void addContentTo(librevenge::RVNGPropertyList &propList) const; |
214 | | //! add style to the propList |
215 | | void addStyleTo(librevenge::RVNGPropertyList &propList) const; |
216 | | //! returns a string corresponding to a series type |
217 | | static std::string getSerieTypeName(Type type); |
218 | | //! operator<< |
219 | | friend std::ostream &operator<<(std::ostream &o, Serie const &series); |
220 | | //! the type |
221 | | Type m_type; |
222 | | //! the data range |
223 | | Position m_ranges[2]; |
224 | | //! use or not the secondary y axis |
225 | | bool m_useSecondaryY; |
226 | | //! the label font |
227 | | WPSFont m_font; |
228 | | //! the label ranges if defined(unused) |
229 | | Position m_labelRanges[2]; |
230 | | //! the legend range if defined |
231 | | Position m_legendRange; |
232 | | //! the legend name if defined |
233 | | librevenge::RVNGString m_legendText; |
234 | | //! the graphic style |
235 | | WPSGraphicStyle m_style; |
236 | | //! the point type |
237 | | PointType m_pointType; |
238 | | }; |
239 | | //! a text zone a chart |
240 | | struct TextZone |
241 | | { |
242 | | //! the text type |
243 | | enum Type { T_Title, T_SubTitle, T_Footer }; |
244 | | //! the text content type |
245 | | enum ContentType { C_Cell, C_Text }; |
246 | | |
247 | | //! constructor |
248 | | explicit TextZone(Type type); |
249 | 103k | TextZone(TextZone const &)=default; |
250 | | //! destructor |
251 | | ~TextZone(); |
252 | | //! returns true if the textbox is valid |
253 | | bool valid() const |
254 | 23.1k | { |
255 | 23.1k | if (!m_show) return false; |
256 | 22.7k | if (m_contentType==C_Cell) |
257 | 194 | return m_cell.valid(); |
258 | 22.5k | if (m_contentType!=C_Text) |
259 | 0 | return false; |
260 | 22.5k | for (auto const &e : m_textEntryList) |
261 | 22.5k | { |
262 | 22.5k | if (e.valid()) return true; |
263 | 22.5k | } |
264 | 23 | return false; |
265 | 22.5k | } |
266 | | //! add content to the propList |
267 | | void addContentTo(librevenge::RVNGPropertyList &propList) const; |
268 | | //! add to the propList |
269 | | void addStyleTo(librevenge::RVNGPropertyList &propList) const; |
270 | | //! operator<< |
271 | | friend std::ostream &operator<<(std::ostream &o, TextZone const &zone); |
272 | | //! the zone type |
273 | | Type m_type; |
274 | | //! the content type |
275 | | ContentType m_contentType; |
276 | | //! true if the zone is visible |
277 | | bool m_show; |
278 | | //! the position in the zone |
279 | | Vec2f m_position; |
280 | | //! the cell position ( or title and subtitle) |
281 | | Position m_cell; |
282 | | //! the text entry (or the list of text entry) |
283 | | std::vector<WPSEntry> m_textEntryList; |
284 | | //! the zone format |
285 | | WPSFont m_font; |
286 | | //! the graphic style |
287 | | WPSGraphicStyle m_style; |
288 | | }; |
289 | | |
290 | | //! the constructor |
291 | | explicit WKSChart(Vec2f const &dim=Vec2f()); |
292 | | //! the destructor |
293 | | virtual ~WKSChart(); |
294 | | //! send the chart to the listener |
295 | | void sendChart(WKSContentListenerPtr &listener, librevenge::RVNGSpreadsheetInterface *interface) const; |
296 | | //! send the zone content (called when the zone is of text type) |
297 | | virtual void sendContent(TextZone const &zone, WPSListenerPtr &listener) const=0; |
298 | | |
299 | | //! set the grid color |
300 | | void setGridColor(WPSColor const &color) |
301 | 39.0k | { |
302 | 39.0k | m_gridColor=color; |
303 | 39.0k | } |
304 | | //! return an axis (corresponding to a coord) |
305 | | Axis &getAxis(int coord); |
306 | | //! return an axis (corresponding to a coord) |
307 | | Axis const &getAxis(int coord) const; |
308 | | |
309 | | //! returns the legend |
310 | | Legend const &getLegend() const |
311 | 0 | { |
312 | 0 | return m_legend; |
313 | 0 | } |
314 | | //! returns the legend |
315 | | Legend &getLegend() |
316 | 89.6k | { |
317 | 89.6k | return m_legend; |
318 | 89.6k | } |
319 | | |
320 | | //! return a serie |
321 | | Serie *getSerie(int id, bool create); |
322 | | //! returns the list of defined series |
323 | | std::map<int, Serie> const &getIdSerieMap() const |
324 | 30.0k | { |
325 | 30.0k | return m_serieMap; |
326 | 30.0k | } |
327 | | //! returns a textzone content |
328 | | TextZone *getTextZone(TextZone::Type type, bool create=false); |
329 | | |
330 | | protected: |
331 | | //! sends a textzone content |
332 | | void sendTextZoneContent(TextZone::Type type, WPSListenerPtr listener) const; |
333 | | |
334 | | public: |
335 | | //! the chart dimension in point |
336 | | Vec2f m_dimension; |
337 | | //! the chart type (if no series) |
338 | | Serie::Type m_type; |
339 | | //! a flag to know if the data are stacked or not |
340 | | bool m_dataStacked; |
341 | | //! a flag to know if the data are percent stacked or not |
342 | | bool m_dataPercentStacked; |
343 | | //! a flag to know if the data are vertical (for bar) |
344 | | bool m_dataVertical; |
345 | | //! a flag to know if the graphic is 3D |
346 | | bool m_is3D; |
347 | | //! a flag to know if real 3D or 2D-extended |
348 | | bool m_is3DDeep; |
349 | | |
350 | | // main |
351 | | |
352 | | //! the chart style |
353 | | WPSGraphicStyle m_style; |
354 | | //! the chart name |
355 | | librevenge::RVNGString m_name; |
356 | | |
357 | | // plot area |
358 | | |
359 | | //! the plot area dimension in percent |
360 | | WPSBox2f m_plotAreaPosition; |
361 | | //! the ploat area style |
362 | | WPSGraphicStyle m_plotAreaStyle; |
363 | | |
364 | | // legend |
365 | | |
366 | | //! the legend dimension in percent |
367 | | WPSBox2f m_legendPosition; |
368 | | |
369 | | //! floor |
370 | | WPSGraphicStyle m_floorStyle; |
371 | | //! wall |
372 | | WPSGraphicStyle m_wallStyle; |
373 | | |
374 | | protected: |
375 | | //! the grid color |
376 | | WPSColor m_gridColor; |
377 | | //! the x,y,y-second,z and a bad axis |
378 | | Axis m_axis[5]; |
379 | | //! the legend |
380 | | Legend m_legend; |
381 | | //! the list of series |
382 | | std::map<int, Serie> m_serieMap; |
383 | | //! a map text zone type to text zone |
384 | | std::map<TextZone::Type, TextZone> m_textZoneMap; |
385 | | private: |
386 | | explicit WKSChart(WKSChart const &orig) = delete; |
387 | | WKSChart &operator=(WKSChart const &orig) = delete; |
388 | | }; |
389 | | |
390 | | #endif |
391 | | /* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */ |