summaryrefslogtreecommitdiff
path: root/src/lib/SW602Cell.h
blob: 26c81b5c129770140d269adc4837770c64632448 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libsw602 project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

/** \file SW602Cell.h
 * Defines SW602Cell (cell content and format)
 */

#ifndef INCLUDED_SW602_CELL_H
#define INCLUDED_SW602_CELL_H

#include <string>
#include <vector>

#include "SW602Entry.h"
#include "SW602Font.h"
#include "SW602Types.h"

namespace libsw602
{

class SW602Table;

/** a structure used to define a cell and its format */
class SW602Cell
{
public:
  /** the different format of a cell's content */
  enum FormatType { F_TEXT, F_BOOLEAN, F_NUMBER, F_DATE, F_TIME, F_UNKNOWN };
  /** the different number format of a cell's content */
  enum NumberType { F_NUMBER_CURRENCY, F_NUMBER_DECIMAL, F_NUMBER_FRACTION, F_NUMBER_GENERIC, F_NUMBER_SCIENTIFIC, F_NUMBER_PERCENT, F_NUMBER_UNKNOWN };
  /** a structure uses to define the format of a cell content */
  struct Format
  {
    //! constructor
    Format() : m_format(F_UNKNOWN), m_numberFormat(F_NUMBER_UNKNOWN), m_digits(-1), m_integerDigits(-1), m_numeratorDigits(-1), m_denominatorDigits(-1),
      m_thousandHasSeparator(false), m_parenthesesForNegative(false), m_currencySymbol("$"), m_DTFormat("")
    {
    }
    //! destructor
    virtual ~Format() {}
    //! returns true if this is a basic format style
    bool hasBasicFormat() const
    {
      return m_format==F_TEXT || m_format==F_UNKNOWN;
    }
    //! returns a value type
    std::string getValueType() const;
    //! get the numbering style
    bool getNumberingProperties(librevenge::RVNGPropertyList &propList) const;
    //! convert a DTFormat in a propertyList
    static bool convertDTFormat(std::string const &dtFormat, librevenge::RVNGPropertyListVector &propListVector);
    //! operator<<
    friend std::ostream &operator<<(std::ostream &o, Format const &format);
    //! a comparison  function
    int compare(Format const &format) const;

    //! the cell format : by default unknown
    FormatType m_format;
    //! the numeric format
    NumberType m_numberFormat;
    //! the number of digits
    int m_digits;
    //! the number of main digits
    int m_integerDigits;
    //! the number of numerator digits
    int m_numeratorDigits;
    //! the number of denominator digits
    int m_denominatorDigits;
    //! true if we must separate the thousand
    bool m_thousandHasSeparator;
    //! true if we use parenthese to print negative number
    bool m_parenthesesForNegative;
    //! the currency symbol ( default '$')
    std::string m_currencySymbol;
    //! a date/time format ( using a subset of strftime format )
    std::string m_DTFormat;
  };
  //! a comparaison structure used to store data
  struct CompareFormat
  {
    //! constructor
    CompareFormat() {}
    //! comparaison function
    bool operator()(Format const &c1, Format const &c2) const
    {
      return c1.compare(c2) < 0;
    }
  };
  /** the default horizontal alignment.

  \note actually mainly used for table/spreadsheet cell, FULL is not yet implemented */
  enum HorizontalAlignment { HALIGN_LEFT, HALIGN_RIGHT, HALIGN_CENTER,
                             HALIGN_FULL, HALIGN_DEFAULT
                           };

  /** the default vertical alignment.
  \note actually mainly used for table/spreadsheet cell,  not yet implemented */
  enum VerticalAlignment { VALIGN_TOP, VALIGN_CENTER, VALIGN_BOTTOM, VALIGN_DEFAULT };

  //! an enum to defined potential internal line: E_Line1=TL to RB, E_Line2=BL to RT
  enum ExtraLine { E_None, E_Line1, E_Line2, E_Cross };

  //! constructor
  SW602Cell() : m_position(0,0), m_numberCellSpanned(1,1), m_bdBox(),  m_bdSize(),
    m_format(), m_font(3,12), m_fontSet(false), m_hAlign(HALIGN_DEFAULT), m_vAlign(VALIGN_DEFAULT),
    m_backgroundColor(SW602Color::white()), m_protected(false),
    m_bordersList(), m_extraLine(E_None), m_extraLineType() { }

  //! destructor
  virtual ~SW602Cell() {}

  /** adds to the propList*/
  void addTo(librevenge::RVNGPropertyList &propList) const;

  //! operator<<
  friend std::ostream &operator<<(std::ostream &o, SW602Cell const &cell);

  // interface with SW602Table:

  /** function called when a cell is send by SW602Table to send a cell to a
      listener.

      By default: calls openTableCell(*this), sendContent and then closeTableCell() */
  virtual bool send(SW602ListenerPtr listener, SW602Table &table);
  /** function called when the content of a cell must be send to the listener,
      ie. when SW602Table::sendTable or SW602Table::sendAsText is called.

      \note default behavior: does nothing and prints an error in debug mode.*/
  virtual bool sendContent(SW602ListenerPtr listener, SW602Table &table);

  // position

  //! position  accessor
  SW602Vec2i const &position() const
  {
    return m_position;
  }
  //! set the cell positions :  0,0 -> A1, 0,1 -> A2
  void setPosition(SW602Vec2i posi)
  {
    m_position = posi;
  }

  //! returns the number of spanned cells
  SW602Vec2i const &numSpannedCells() const
  {
    return m_numberCellSpanned;
  }
  //! sets the number of spanned cells : SW602Vec2i(1,1) means 1 cellule
  void setNumSpannedCells(SW602Vec2i numSpanned)
  {
    m_numberCellSpanned=numSpanned;
  }

  //! bdbox  accessor
  SW602Box2f const &bdBox() const
  {
    return m_bdBox;
  }
  //! set the bdbox (unit point)
  void setBdBox(SW602Box2f box)
  {
    m_bdBox = box;
  }

  //! bdbox size accessor
  SW602Vec2f const &bdSize() const
  {
    return m_bdSize;
  }
  //! set the bdbox size(unit point)
  void setBdSize(SW602Vec2f sz)
  {
    m_bdSize = sz;
  }
  //! return the name of a cell (given row and column) : 0,0 -> A1, 0,1 -> A2...
  static std::string getBasicCellName(SW602Vec2i const &pos);
  //! return the name of a cell (given row and column) : 0,0 -> [.A1], 0,1 -> [.A2]
  static std::string getCellName(SW602Vec2i const &pos, SW602Vec2b const &absolute);

  //! return the column name
  static std::string getColumnName(int col);

  // format

  //! returns the cell format
  Format const &getFormat() const
  {
    return m_format;
  }
  //! set the cell format
  void setFormat(Format const &format)
  {
    m_format=format;
  }

  //! returns true if the font has been set
  bool isFontSet() const
  {
    return m_fontSet;
  }
  //! returns the font
  SW602Font getFont() const
  {
    return m_font;
  }
  //! sets the fonts
  void setFont(SW602Font const &font, bool isDefault=false)
  {
    m_font=font;
    m_fontSet=!isDefault;
  }

  //! returns true if the cell is protected
  bool isProtected() const
  {
    return m_protected;
  }
  //! sets the cell's protected flag
  void setProtected(bool fl)
  {
    m_protected = fl;
  }

  //! returns the horizontal alignment
  HorizontalAlignment hAlignment() const
  {
    return m_hAlign;
  }
  //! sets the horizontal alignment
  void setHAlignment(HorizontalAlignment align)
  {
    m_hAlign = align;
  }

  //! returns the vertical alignment
  VerticalAlignment vAlignment() const
  {
    return m_vAlign;
  }
  //! sets the vertical alignment
  void setVAlignment(VerticalAlignment align)
  {
    m_vAlign = align;
  }

  //! return true if the cell has some border
  bool hasBorders() const
  {
    return m_bordersList.size() != 0;
  }
  //! return the cell border: libsw602::Left | ...
  std::vector<SW602Border> const &borders() const
  {
    return m_bordersList;
  }

  //! reset the border
  void resetBorders()
  {
    m_bordersList.resize(0);
  }
  //! sets the cell border: wh=libsw602::LeftBit|...
  void setBorders(int wh, SW602Border const &border);

  //! returns the background color
  SW602Color backgroundColor() const
  {
    return m_backgroundColor;
  }
  //! sets the background color
  void setBackgroundColor(SW602Color color)
  {
    m_backgroundColor = color;
  }
  //! returns true if we have some extra lines
  bool hasExtraLine() const
  {
    return m_extraLine!=E_None && !m_extraLineType.isEmpty();
  }
  //! returns the extra lines
  ExtraLine extraLine() const
  {
    return m_extraLine;
  }
  //! returns the extra line border
  SW602Border const &extraLineType() const
  {
    return m_extraLineType;
  }
  //! sets the extraline
  void setExtraLine(ExtraLine extrLine, SW602Border const &type=SW602Border())
  {
    m_extraLine = extrLine;
    m_extraLineType=type;
  }
protected:
  //! the cell row and column : 0,0 -> A1, 0,1 -> A2
  SW602Vec2i m_position;
  //! the cell spanned : by default (1,1)
  SW602Vec2i m_numberCellSpanned;
  /** the cell bounding box (unit in point)*/
  SW602Box2f m_bdBox;
  /** the cell bounding size : unit point */
  SW602Vec2f m_bdSize;

  //! the cell format
  Format m_format;
  //! the cell font
  SW602Font m_font;
  //! a flag to know if the font has been set
  bool m_fontSet;
  //! the cell alignment : by default nothing
  HorizontalAlignment m_hAlign;
  //! the vertical cell alignment : by default nothing
  VerticalAlignment m_vAlign;
  //! the backgroung color
  SW602Color m_backgroundColor;
  //! cell protected
  bool m_protected;

  //! the cell border SW602Border::Pos
  std::vector<SW602Border> m_bordersList;
  /** extra line */
  ExtraLine m_extraLine;
  /** extra line type */
  SW602Border m_extraLineType;
};

//! small class use to define a sheet cell content
class SW602CellContent
{
public:
  //! small class use to define a formula instruction
  struct FormulaInstruction
  {
    enum Type { F_Operator, F_Function, F_Cell, F_CellList, F_Long, F_Double, F_Text };
    //! constructor
    FormulaInstruction() : m_type(F_Text), m_content(""), m_longValue(0), m_doubleValue(0), m_sheet("")
    {
      for (int i=0; i<2; ++i)
      {
        m_position[i]=SW602Vec2i(0,0);
        m_positionRelative[i]=SW602Vec2b(false,false);
      }
    }
    /** returns a proplist corresponding to a instruction using a font converter to send the t ext */
    librevenge::RVNGPropertyList getPropertyList() const;
    //! operator<<
    friend std::ostream &operator<<(std::ostream &o, FormulaInstruction const &inst);
    //! the type
    Type m_type;
    //! the content ( if type == F_Operator or type = F_Function or type==F_Text)
    std::string m_content;
    //! value ( if type==F_Long )
    double m_longValue;
    //! value ( if type==F_Double )
    double m_doubleValue;
    //! cell position ( if type==F_Cell or F_CellList )
    SW602Vec2i m_position[2];
    //! relative cell position ( if type==F_Cell or F_CellList )
    SW602Vec2b m_positionRelative[2];
    //! the sheet name (if not empty)
    std::string m_sheet;
  };

  /** the different types of cell's field */
  enum Type { C_NONE, C_TEXT, C_NUMBER, C_FORMULA, C_UNKNOWN };
  /// constructor
  SW602CellContent() : m_contentType(C_UNKNOWN), m_value(0.0), m_valueSet(false), m_textEntry(), m_formula() { }
  /// destructor
  ~SW602CellContent() {}
  //! operator<<
  friend std::ostream &operator<<(std::ostream &o, SW602CellContent const &cell);

  //! returns true if the cell has no content
  bool empty() const
  {
    if (m_contentType == C_NUMBER) return false;
    if (m_contentType == C_TEXT && m_textEntry.valid()) return false;
    if (m_contentType == C_FORMULA && (m_formula.size() || isValueSet())) return false;
    return true;
  }
  //! sets the double value
  void setValue(double value)
  {
    m_value = value;
    m_valueSet = true;
  }
  //! returns true if the value has been setted
  bool isValueSet() const
  {
    return m_valueSet;
  }
  //! returns true if the text is set
  bool hasText() const
  {
    return m_textEntry.valid();
  }
  /** conversion beetween double days since 1900 and a date, ie val=0
      corresponds to 1/1/1900, val=365 to 1/1/1901, ... */
  static bool double2Date(double val, int &Y, int &M, int &D);
  /** conversion beetween double: second since 0:00 and time */
  static bool double2Time(double val, int &H, int &M, int &S);
  /** conversion of the value in string knowing the cell format */
  static bool double2String(double val, SW602Cell::Format const &format, std::string &str);
  /** conversion beetween date and double days since 1900 date */
  static bool date2Double(int Y, int M, int D, double &val);
  //! the content type ( by default unknown )
  Type m_contentType;
  //! the cell value
  double m_value;
  //! true if the value has been set
  bool m_valueSet;
  //! the cell string
  SW602Entry m_textEntry;
  //! the formula list of instruction
  std::vector<FormulaInstruction> m_formula;
};

}

#endif

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */