spreadsheet_ods/format/
mod.rs

1//!
2//! Defines one ValueFormatXX per ValueType for textual formatting of those values.
3//!
4//! ```
5//! use spreadsheet_ods::{ValueType};
6//! use spreadsheet_ods::format::{FormatCalendarStyle, FormatNumberStyle, ValueFormatDateTime, ValueFormatNumber};
7//!
8//! let mut v = ValueFormatDateTime::new_named("dt0");
9//! v.part_day().long_style().build();
10//! v.part_text(".").build();
11//! v.part_month().long_style().build();
12//! v.part_text(".").build();
13//! v.part_year().long_style().build();
14//! v.part_text(" ").build();
15//! v.part_hours().long_style().build();
16//! v.part_text(":").build();
17//! v.part_minutes().long_style().build();
18//! v.part_text(":").build();
19//! v.part_seconds().long_style().build();
20//!
21//! let mut v = ValueFormatNumber::new_named("n3");
22//! v.part_number().decimal_places(3).build();
23//! ```
24//!
25
26// This cares about the following parts of office:styles and office:automatic-styles.
27//
28// <number:boolean-style> 16.29.24,
29// <number:currency-style> 16.29.8,
30// <number:date-style> 16.29.11,
31// <number:number-style> 16.29.2,
32// <number:percentage-style> 16.29.10,
33// <number:text-style> 16.29.26,
34// <number:time-style> 16.29.19,
35//
36
37mod builder;
38mod create;
39mod stylemap;
40
41pub use builder::*;
42pub use create::*;
43pub use stylemap::*;
44
45use crate::attrmap2::AttrMap2;
46use crate::color::Rgb;
47use crate::style::units::{
48    Angle, FontSize, FontStyle, FontVariant, FontWeight, FormatSource, Length, LetterSpacing,
49    LineMode, LineStyle, LineType, LineWidth, Percent, RotationScale, TextCombine, TextCondition,
50    TextDisplay, TextEmphasize, TextEmphasizePosition, TextPosition, TextRelief, TextTransform,
51    TransliterationStyle,
52};
53use crate::style::AnyStyleRef;
54use crate::style::ParseStyleAttr;
55use crate::style::{
56    color_string, shadow_string, text_position, StyleOrigin, StyleUse, TextStyleRef,
57};
58use crate::{OdsError, ValueType};
59use core::borrow::Borrow;
60use get_size::GetSize;
61use get_size_derive::GetSize;
62use icu_locid::subtags::{Language, Region, Script};
63use icu_locid::{LanguageIdentifier, Locale};
64use std::fmt::{Display, Formatter};
65use std::str::FromStr;
66
67style_ref2!(ValueFormatRef);
68
69/// Trait used by the builder types.
70pub trait ValueFormatTrait {
71    /// Returns a reference name for this value format.
72    fn format_ref(&self) -> ValueFormatRef;
73
74    /// The style:name attribute specifies names that reference style mechanisms.
75    fn set_name<S: Into<String>>(&mut self, name: S);
76
77    /// The style:name attribute specifies names that reference style mechanisms.
78    fn name(&self) -> &String;
79
80    /// Returns the value type.
81    fn value_type(&self) -> ValueType;
82
83    /// Sets the storage location for this ValueFormat. Either content.xml
84    /// or styles.xml.
85    fn set_origin(&mut self, origin: StyleOrigin);
86
87    /// Returns the storage location.
88    fn origin(&self) -> StyleOrigin;
89
90    /// How is the style used in the document.
91    fn set_styleuse(&mut self, styleuse: StyleUse);
92
93    /// How is the style used in the document.
94    fn styleuse(&self) -> StyleUse;
95
96    /// All direct attributes of the number:xxx-style tag.
97    fn attrmap(&self) -> &AttrMap2;
98
99    /// All direct attributes of the number:xxx-style tag.
100    fn attrmap_mut(&mut self) -> &mut AttrMap2;
101
102    /// Text style attributes.
103    fn textstyle(&self) -> &AttrMap2;
104
105    /// Text style attributes.
106    fn textstyle_mut(&mut self) -> &mut AttrMap2;
107
108    /// Adds a format part.
109    fn push_part(&mut self, part: FormatPart);
110
111    /// Adds all format parts.
112    fn push_parts(&mut self, partvec: &mut Vec<FormatPart>);
113
114    /// Returns the parts.
115    fn parts(&self) -> &Vec<FormatPart>;
116
117    /// Returns the mutable parts.
118    fn parts_mut(&mut self) -> &mut Vec<FormatPart>;
119
120    /// Adds a stylemap.
121    fn push_stylemap(&mut self, stylemap: ValueStyleMap);
122
123    /// Returns the stylemaps
124    fn stylemaps(&self) -> Option<&Vec<ValueStyleMap>>;
125
126    /// Returns the mutable stylemap.
127    fn stylemaps_mut(&mut self) -> &mut Vec<ValueStyleMap>;
128}
129
130valueformat!(ValueFormatBoolean, ValueType::Boolean);
131
132// 16.29.24 <number:boolean-style>
133impl ValueFormatBoolean {
134    part_boolean!();
135
136    push_boolean!();
137}
138
139// 16.29.2 <number:number-style>
140valueformat!(ValueFormatNumber, ValueType::Number);
141
142impl ValueFormatNumber {
143    part_fill_character!();
144    part_fraction!();
145    part_number!();
146    part_scientific!();
147    part_text!();
148
149    push_fraction!();
150    push_number!();
151    push_number_fix!();
152    push_scientific!();
153    push_text!();
154}
155
156// 16.29.10 <number:percentage-style>
157valueformat!(ValueFormatPercentage, ValueType::Percentage);
158
159impl ValueFormatPercentage {
160    part_fill_character!();
161    part_number!();
162    part_text!();
163
164    push_number!();
165    push_number_fix!();
166    push_text!();
167}
168
169// 16.29.8 <number:currency-style>
170valueformat!(ValueFormatCurrency, ValueType::Currency);
171
172impl ValueFormatCurrency {
173    number_automatic_order!(attr);
174
175    part_currency!();
176    part_fill_character!();
177    part_number!();
178    part_text!();
179
180    push_currency_symbol!();
181    push_number!();
182    push_number_fix!();
183    push_text!();
184}
185
186// 16.29.26 <number:text-style>
187valueformat!(ValueFormatText, ValueType::Text);
188
189impl ValueFormatText {
190    part_fill_character!();
191    part_text!();
192    part_text_content!();
193
194    push_text!();
195    push_text_content!();
196}
197
198// 16.29.11 <number:date-style>
199valueformat!(ValueFormatDateTime, ValueType::DateTime);
200
201impl ValueFormatDateTime {
202    number_automatic_order!(attr);
203    number_format_source!(attr);
204
205    part_am_pm!();
206    part_day!();
207    part_day_of_week!();
208    part_era!();
209    part_fill_character!();
210    part_hours!();
211    part_minutes!();
212    part_month!();
213    part_quarter!();
214    part_seconds!();
215    part_text!();
216    part_week_of_year!();
217    part_year!();
218
219    push_am_pm!();
220    push_day!();
221    push_day_of_week!();
222    push_era!();
223    push_hours!();
224    push_minutes!();
225    push_month!();
226    push_quarter!();
227    push_seconds!();
228    push_text!();
229    push_week_of_year!();
230    push_year!();
231}
232
233// 16.29.19 <number:time-style>
234valueformat!(ValueFormatTimeDuration, ValueType::TimeDuration);
235
236impl ValueFormatTimeDuration {
237    number_format_source!(attr);
238    number_truncate_on_overflow!(attr);
239
240    part_am_pm!();
241    part_fill_character!();
242    part_hours!();
243    part_minutes!();
244    part_seconds!();
245    part_text!();
246
247    push_am_pm!();
248    push_hours!();
249    push_minutes!();
250    push_seconds!();
251    push_text!();
252}
253
254/// Identifies the structural parts of a value format.
255#[derive(Debug, Clone, Copy, Eq, PartialEq, GetSize)]
256#[allow(missing_docs)]
257pub enum FormatPartType {
258    Number,
259    FillCharacter,
260    ScientificNumber,
261    Fraction,
262    CurrencySymbol,
263    Day,
264    Month,
265    Year,
266    Era,
267    DayOfWeek,
268    WeekOfYear,
269    Quarter,
270    Hours,
271    Minutes,
272    Seconds,
273    AmPm,
274    Boolean,
275    Text,
276    TextContent,
277}
278
279/// One structural part of a value format.
280#[derive(Debug, Clone, GetSize)]
281pub struct FormatPart {
282    /// What kind of format part is this?
283    part_type: FormatPartType,
284    /// Properties of this part.
285    attr: AttrMap2,
286    /// Textposition for embedded text when acting as a number format part.
287    ///
288    /// The number:position attribute specifies the position where text appears.
289    /// The index of a position starts with 1 and is counted by digits from right to left in the integer part of
290    /// a number, starting left from a decimal separator if one exists, or from the last digit of the number.
291    /// Text is inserted before the digit at the specified position. If the value of number:position
292    /// attribute is greater than the value of number:min-integer-digits and greater than
293    /// the number of integer digits in the number, text is prepended to the number.
294    position: Option<i32>,
295    /// Some content.
296    content: Option<String>,
297}
298
299/// Flag for several PartTypes.
300#[derive(Debug, Clone, Copy, Eq, PartialEq)]
301#[allow(missing_docs)]
302pub enum FormatNumberStyle {
303    Short,
304    Long,
305}
306
307impl Display for FormatNumberStyle {
308    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
309        match self {
310            FormatNumberStyle::Short => write!(f, "short"),
311            FormatNumberStyle::Long => write!(f, "long"),
312        }
313    }
314}
315
316/// Calendar types.
317#[derive(Debug, Clone, Copy, Eq, PartialEq)]
318#[allow(missing_docs)]
319pub enum FormatCalendarStyle {
320    Gregorian,
321    Gengou,
322    Roc,
323    Hanja,
324    Hijri,
325    Jewish,
326    Buddhist,
327}
328
329impl Display for FormatCalendarStyle {
330    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
331        match self {
332            FormatCalendarStyle::Gregorian => write!(f, "gregorian"),
333            FormatCalendarStyle::Gengou => write!(f, "gengou"),
334            FormatCalendarStyle::Roc => write!(f, "ROC"),
335            FormatCalendarStyle::Hanja => write!(f, "hanja"),
336            FormatCalendarStyle::Hijri => write!(f, "hijri"),
337            FormatCalendarStyle::Jewish => write!(f, "jewish"),
338            FormatCalendarStyle::Buddhist => write!(f, "buddhist"),
339        }
340    }
341}
342
343impl FormatPart {
344    /// New, empty
345    pub fn new(ftype: FormatPartType) -> Self {
346        FormatPart {
347            part_type: ftype,
348            attr: Default::default(),
349            position: None,
350            content: None,
351        }
352    }
353
354    /// Sets the kind of the part.
355    pub fn set_part_type(&mut self, p_type: FormatPartType) {
356        self.part_type = p_type;
357    }
358
359    /// What kind of part?
360    pub fn part_type(&self) -> FormatPartType {
361        self.part_type
362    }
363
364    /// General attributes.
365    pub(crate) fn attrmap(&self) -> &AttrMap2 {
366        &self.attr
367    }
368
369    /// General attributes.
370    pub(crate) fn attrmap_mut(&mut self) -> &mut AttrMap2 {
371        &mut self.attr
372    }
373
374    /// Adds an attribute.
375    pub fn set_attr(&mut self, name: &str, value: String) {
376        self.attr.set_attr(name, value);
377    }
378
379    /// Returns a property or a default.
380    pub fn attr_def<'a, 'b, S>(&'a self, name: &'b str, default: S) -> &'a str
381    where
382        S: Into<&'a str>,
383    {
384        self.attr.attr_def(name, default)
385    }
386
387    /// Sets the position for embedded text in a number format part.
388    pub fn set_position(&mut self, pos: i32) {
389        self.position = Some(pos);
390    }
391
392    /// Clear the position for embedded text in a number format part.
393    pub fn clear_position(&mut self) {
394        self.position = None;
395    }
396
397    /// The position for embedded text in a number format part.
398    pub fn position(&self) -> Option<i32> {
399        self.position
400    }
401
402    /// Sets a textual content for this part. This is only used
403    /// for text and currency-symbol.
404    pub fn set_content<S: Into<String>>(&mut self, content: S) {
405        self.content = Some(content.into());
406    }
407
408    /// Clear the textual content for this part. This is only used
409    /// for text and currency-symbol.
410    pub fn clear_content(&mut self) {
411        self.content = None;
412    }
413
414    /// Returns the text content.
415    pub fn content(&self) -> Option<&String> {
416        self.content.as_ref()
417    }
418}