document some style classes, start implementing builtin styles more correctly

This commit is contained in:
Thomas Fussell 2017-03-26 10:30:26 -04:00
parent 1121bcbe15
commit c3d9b85530
11 changed files with 252 additions and 190 deletions

View File

@ -426,7 +426,12 @@ public:
/// <summary> /// <summary>
/// Returns a wrapper pointing to the named style applied to this cell. /// Returns a wrapper pointing to the named style applied to this cell.
/// </summary> /// </summary>
const class style style() const; class style style();
/// <summary>
/// Returns a wrapper pointing to the named style applied to this cell.
/// </summary>
const class style style() const;
/// <summary> /// <summary>
/// Sets the named style applied to this cell to a style named style_name. /// Sets the named style applied to this cell to a style named style_name.

View File

@ -43,6 +43,7 @@ namespace detail {
struct format_impl; struct format_impl;
struct stylesheet; struct stylesheet;
class xlsx_producer;
} // namespace detail } // namespace detail
@ -52,11 +53,6 @@ struct stylesheet;
class XLNT_API format class XLNT_API format
{ {
public: public:
/// <summary>
///
/// </summary>
std::size_t id() const;
// Alignment // Alignment
/// <summary> /// <summary>
@ -234,10 +230,16 @@ public:
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
const class style style() const; class style style();
/// <summary>
///
/// </summary>
const class style style() const;
private: private:
friend struct detail::stylesheet; friend struct detail::stylesheet;
friend class detail::xlsx_producer;
friend class cell; friend class cell;
/// <summary> /// <summary>
@ -245,6 +247,11 @@ private:
/// </summary> /// </summary>
format(detail::format_impl *d); format(detail::format_impl *d);
/// <summary>
///
/// </summary>
std::size_t id() const;
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>

View File

@ -61,81 +61,79 @@ public:
style() = delete; style() = delete;
/// <summary> /// <summary>
/// Default copy constructor /// Default copy constructor. Constructs a style using the same PIMPL as other.
/// </summary> /// </summary>
style(const style &other) = default; style(const style &other) = default;
/// <summary> /// <summary>
/// Return the name of this style. /// Returns the name of this style.
/// </summary> /// </summary>
std::string name() const; std::string name() const;
/// <summary> /// <summary>
/// /// Sets the name of this style to name.
/// </summary> /// </summary>
style name(const std::string &name); style name(const std::string &name);
/// <summary> /// <summary>
/// /// Returns true if this style is hidden.
/// </summary> /// </summary>
bool hidden() const; bool hidden() const;
/// <summary> /// <summary>
/// /// Sets the hidden state of this style to value. A hidden style will not
/// be shown in the list of selectable styles in the UI, but will still
/// apply its formatting to cells using it.
/// </summary> /// </summary>
style hidden(bool value); style hidden(bool value);
/// <summary> /// <summary>
/// /// Returns true if this is a builtin style that has been customized and
/// should therefore be persisted in the workbook.
/// </summary> /// </summary>
optional<bool> custom() const; bool custom_builtin() const;
/// <summary> /// <summary>
/// /// Returns the index of the builtin style that this style is an instance
/// of or is a customized version thereof. If style::builtin() is false,
/// this will throw an invalid_attribute exception.
/// </summary> /// </summary>
style custom(bool value); std::size_t builtin_id() const;
/// <summary>
/// Returns true if this is a builtin style.
/// </summary>
bool builtin() const;
// Formatting (xf) components
/// <summary> /// <summary>
/// /// Returns the alignment of this style.
/// </summary> /// </summary>
optional<std::size_t> builtin_id() const; class alignment alignment() const;
/// <summary>
/// Returns true if the alignment of this style should be applied to cells
/// using it.
/// </summary>
bool alignment_applied() const;
/// <summary> /// <summary>
/// /// Sets the alignment of this style to new_alignment. Applied, which defaults
/// </summary> /// to true, determines whether the alignment should be enabled for cells using
style builtin_id(std::size_t builtin_id); /// this style.
// Formatting components
/// <summary>
///
/// </summary>
class alignment &alignment();
/// <summary>
///
/// </summary>
const class alignment &alignment() const;
/// <summary>
///
/// </summary> /// </summary>
style alignment(const xlnt::alignment &new_alignment, bool applied = true); style alignment(const xlnt::alignment &new_alignment, bool applied = true);
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
bool alignment_applied() const; class border border() const;
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
class border &border(); bool border_applied() const;
/// <summary>
///
/// </summary>
const class border &border() const;
/// <summary> /// <summary>
/// ///
@ -145,17 +143,12 @@ public:
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
bool border_applied() const; class fill fill() const;
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
class fill &fill(); bool fill_applied() const;
/// <summary>
///
/// </summary>
const class fill &fill() const;
/// <summary> /// <summary>
/// ///
@ -165,17 +158,12 @@ public:
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
bool fill_applied() const; class font font() const;
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
class font &font(); bool font_applied() const;
/// <summary>
///
/// </summary>
const class font &font() const;
/// <summary> /// <summary>
/// ///
@ -185,17 +173,12 @@ public:
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
bool font_applied() const; class number_format number_format() const;
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
class number_format &number_format(); bool number_format_applied() const;
/// <summary>
///
/// </summary>
const class number_format &number_format() const;
/// <summary> /// <summary>
/// ///
@ -205,53 +188,51 @@ public:
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
bool number_format_applied() const; class protection protection() const;
/// <summary>
///
/// </summary>
bool protection_applied() const;
/// <summary> /// <summary>
/// ///
/// </summary>
class protection &protection();
/// <summary>
///
/// </summary>
const class protection &protection() const;
/// <summary>
///
/// </summary> /// </summary>
style protection(const xlnt::protection &new_protection, bool applied = true); style protection(const xlnt::protection &new_protection, bool applied = true);
/// <summary> /// <summary>
/// /// Returns true if the pivot table interface is enabled for this style.
/// </summary>
bool protection_applied() const;
/// <summary>
///
/// </summary> /// </summary>
bool pivot_button() const; bool pivot_button() const;
/// <summary> /// <summary>
/// /// If show is true, a pivot table interface will be displayed for cells using
/// this style.
/// </summary> /// </summary>
void pivot_button(bool show); void pivot_button(bool show);
/// <summary> /// <summary>
/// /// Returns true if this style should add a single-quote prefix for all text values.
/// </summary> /// </summary>
bool quote_prefix() const; bool quote_prefix() const;
/// <summary> /// <summary>
/// /// If quote is true, enables a single-quote prefix for all text values in cells
/// using this style (e.g. "abc" will appear as "'abc"). The text will also not
/// be stored in sharedStrings when this is enabled.
/// </summary> /// </summary>
void quote_prefix(bool quote); void quote_prefix(bool quote);
/// <summary> /// <summary>
/// /// Returns true if this style is equivalent to other.
/// </summary> /// </summary>
bool operator==(const style &other) const; bool operator==(const style &other) const;
/// <summary>
/// Returns true if this style is not equivalent to other.
/// </summary>
bool operator!=(const style &other) const;
private: private:
friend struct detail::stylesheet; friend struct detail::stylesheet;
friend class detail::xlsx_consumer; friend class detail::xlsx_consumer;

View File

@ -669,6 +669,11 @@ public:
/// </summary> /// </summary>
class style create_style(const std::string &name); class style create_style(const std::string &name);
/// <summary>
/// Creates a new style and returns it.
/// </summary>
class style create_builtin_style(std::size_t builtin_id);
/// <summary> /// <summary>
/// Clear all named styles from cells and remove the styles from /// Clear all named styles from cells and remove the styles from
/// from the styelsheet. This leaves all other styling in place /// from the styelsheet. This leaves all other styling in place

View File

@ -792,14 +792,26 @@ void cell::style(const std::string &style_name)
style(workbook().style(style_name)); style(workbook().style(style_name));
} }
const style cell::style() const style cell::style()
{ {
if (!has_format() || !format().has_style()) if (!has_format() || !format().has_style())
{ {
throw invalid_attribute(); throw invalid_attribute();
} }
return format().style(); auto f = format();
return f.style();
}
const style cell::style() const
{
if (!has_format() || !format().has_style())
{
throw invalid_attribute();
}
return format().style();
} }
bool cell::has_style() const bool cell::has_style() const

View File

@ -25,7 +25,7 @@ struct style_impl
std::string name; std::string name;
std::size_t formatting_record_id; std::size_t formatting_record_id;
optional<bool> custom_builtin; bool custom_builtin;
bool hidden_style; bool hidden_style;
optional<std::size_t> builtin_id; optional<std::size_t> builtin_id;

View File

@ -83,6 +83,71 @@ struct stylesheet
return xlnt::style(&impl); return xlnt::style(&impl);
} }
class style create_builtin_style(const std::size_t builtin_id)
{
// From Annex G.2
static const auto *names = new std::unordered_map<std::size_t , std::string>
{
{ 0, "Normal" },
{ 1, "RowLevel_1" },
{ 2, "ColLevel_1" },
{ 3, "Comma" },
{ 4, "Currency" },
{ 5, "Percent" },
{ 6, "Comma [0]" },
{ 7, "Currency [0]" },
{ 8, "Hyperlink" },
{ 9, "Followed Hyperlink" },
{ 10, "Note" },
{ 11, "Warning Text" },
{ 15, "Title" },
{ 16, "Heading 1" },
{ 17, "Heading 2" },
{ 18, "Heading 3" },
{ 19, "Heading 4" },
{ 20, "Input" },
{ 21, "Output"},
{ 22, "Calculation"},
{ 22, "Calculation" },
{ 23, "Check Cell" },
{ 24, "Linked Cell" },
{ 25, "Total" },
{ 26, "Good" },
{ 27, "Bad" },
{ 28, "Neutral" },
{ 29, "Accent1" },
{ 30, "20% - Accent1" },
{ 31, "40% - Accent1" },
{ 32, "60% - Accent1" },
{ 33, "Accent2" },
{ 34, "20% - Accent2" },
{ 35, "40% - Accent2" },
{ 36, "60% - Accent2" },
{ 37, "Accent3" },
{ 38, "20% - Accent3" },
{ 39, "40% - Accent3" },
{ 40, "60% - Accent3" },
{ 41, "Accent4" },
{ 42, "20% - Accent4" },
{ 43, "40% - Accent4" },
{ 44, "60% - Accent4" },
{ 45, "Accent5" },
{ 46, "20% - Accent5" },
{ 47, "40% - Accent5" },
{ 48, "60% - Accent5" },
{ 49, "Accent6" },
{ 50, "20% - Accent6" },
{ 51, "40% - Accent6" },
{ 52, "60% - Accent6" },
{ 53, "Explanatory Text" }
};
auto new_style = create_style(names->at(builtin_id));
new_style.d_->builtin_id = builtin_id;
return new_style;
}
class style style(const std::string &name) class style style(const std::string &name)
{ {
if (!has_style(name)) throw key_not_found(); if (!has_style(name)) throw key_not_found();

View File

@ -1422,10 +1422,10 @@ void xlsx_producer::write_styles(const relationship & /*rel*/)
write_attribute("hidden", write_bool(true)); write_attribute("hidden", write_bool(true));
} }
if (current_style.custom_builtin.is_set()) if (current_style.builtin_id.is_set() && current_style.custom_builtin)
{ {
write_attribute("customBuiltin", write_bool(current_style.custom_builtin.get())); write_attribute("customBuiltin", write_bool(current_style.custom_builtin));
} }
write_end_element(xmlns, "cellStyle"); write_end_element(xmlns, "cellStyle");
} }

View File

@ -61,7 +61,7 @@ bool format::has_style() const
return d_->style.is_set(); return d_->style.is_set();
} }
const style format::style() const style format::style()
{ {
if (!has_style()) if (!has_style())
{ {
@ -71,6 +71,16 @@ const style format::style() const
return d_->parent->style(d_->style.get()); return d_->parent->style(d_->style.get());
} }
const style format::style() const
{
if (!has_style())
{
throw invalid_attribute();
}
return d_->parent->style(d_->style.get());
}
xlnt::alignment &format::alignment() xlnt::alignment &format::alignment()
{ {
return d_->parent->alignments.at(d_->alignment_id.get()); return d_->parent->alignments.at(d_->alignment_id.get());

View File

@ -31,6 +31,17 @@
#include <xlnt/styles/style.hpp> #include <xlnt/styles/style.hpp>
#include <detail/stylesheet.hpp> #include <detail/stylesheet.hpp>
namespace {
std::vector<xlnt::number_format>::iterator find_number_format(
std::vector<xlnt::number_format> &number_formats, std::size_t id)
{
return std::find_if(number_formats.begin(), number_formats.end(),
[=](const xlnt::number_format &nf) { return nf.id() == id; });
}
}
namespace xlnt { namespace xlnt {
style::style(detail::style_impl *d) style::style(detail::style_impl *d)
@ -49,15 +60,9 @@ style style::hidden(bool value)
return style(d_); return style(d_);
} }
optional<std::size_t> style::builtin_id() const std::size_t style::builtin_id() const
{ {
return d_->builtin_id; return d_->builtin_id.get();
}
style style::builtin_id(std::size_t builtin_id)
{
d_->builtin_id = builtin_id;
return *this;
} }
std::string style::name() const std::string style::name() const
@ -71,15 +76,9 @@ style style::name(const std::string &name)
return *this; return *this;
} }
optional<bool> style::custom() const bool style::custom_builtin() const
{ {
return d_->custom_builtin; return d_->builtin_id.is_set() && d_->custom_builtin;
}
style style::custom(bool value)
{
d_->custom_builtin = value;
return *this;
} }
bool style::operator==(const style &other) const bool style::operator==(const style &other) const
@ -87,86 +86,94 @@ bool style::operator==(const style &other) const
return name() == other.name(); return name() == other.name();
} }
xlnt::alignment &style::alignment() xlnt::alignment style::alignment() const
{ {
return d_->parent->alignments.at(d_->alignment_id.get()); return d_->parent->alignments.at(d_->alignment_id.get());
} }
const xlnt::alignment &style::alignment() const bool style::alignment_applied() const
{ {
return d_->parent->alignments.at(d_->alignment_id.get()); return d_->alignment_applied;
} }
style style::alignment(const xlnt::alignment &new_alignment, bool applied) style style::alignment(const xlnt::alignment &new_alignment, bool applied)
{ {
d_->alignment_id = d_->parent->find_or_add(d_->parent->alignments, new_alignment); d_->alignment_id = d_->parent->find_or_add(d_->parent->alignments, new_alignment);
d_->alignment_applied = applied; d_->alignment_applied = applied;
return style(d_);
return *this;
} }
xlnt::border &style::border() xlnt::border style::border() const
{ {
return d_->parent->borders.at(d_->border_id.get()); return d_->parent->borders.at(d_->border_id.get());
} }
const xlnt::border &style::border() const bool style::border_applied() const
{ {
return d_->parent->borders.at(d_->border_id.get()); return d_->border_applied;
} }
style style::border(const xlnt::border &new_border, bool applied) style style::border(const xlnt::border &new_border, bool applied)
{ {
d_->border_id = d_->parent->find_or_add(d_->parent->borders, new_border); d_->border_id = d_->parent->find_or_add(d_->parent->borders, new_border);
d_->border_applied = applied; d_->border_applied = applied;
return style(d_);
return *this;
} }
xlnt::fill &style::fill() xlnt::fill style::fill() const
{ {
return d_->parent->fills.at(d_->fill_id.get()); return d_->parent->fills.at(d_->fill_id.get());
} }
const xlnt::fill &style::fill() const bool style::fill_applied() const
{ {
return d_->parent->fills.at(d_->fill_id.get()); return d_->fill_applied;
} }
style style::fill(const xlnt::fill &new_fill, bool applied) style style::fill(const xlnt::fill &new_fill, bool applied)
{ {
d_->fill_id = d_->parent->find_or_add(d_->parent->fills, new_fill); d_->fill_id = d_->parent->find_or_add(d_->parent->fills, new_fill);
d_->fill_applied = applied; d_->fill_applied = applied;
return style(d_);
return *this;
} }
xlnt::font &style::font() xlnt::font style::font() const
{ {
return d_->parent->fonts.at(d_->font_id.get()); return d_->parent->fonts.at(d_->font_id.get());
} }
const xlnt::font &style::font() const bool style::font_applied() const
{ {
return d_->parent->fonts.at(d_->font_id.get()); return d_->font_applied;
} }
style style::font(const xlnt::font &new_font, bool applied) style style::font(const xlnt::font &new_font, bool applied)
{ {
d_->font_id = d_->parent->find_or_add(d_->parent->fonts, new_font); d_->font_id = d_->parent->find_or_add(d_->parent->fonts, new_font);
d_->font_applied = applied; d_->font_applied = applied;
return style(d_);
return *this;
} }
xlnt::number_format &style::number_format() xlnt::number_format style::number_format() const
{ {
auto tarid = d_->number_format_id.get(); auto match = find_number_format(d_->parent->number_formats,
return *std::find_if(d_->parent->number_formats.begin(), d_->parent->number_formats.end(), d_->number_format_id.get());
[=](const class number_format &nf) { return nf.id() == tarid; });
if (match == d_->parent->number_formats.end())
{
throw invalid_attribute();
}
return *match;
} }
const xlnt::number_format &style::number_format() const bool style::number_format_applied() const
{ {
auto tarid = d_->number_format_id.get(); return d_->number_format_applied;
return *std::find_if(d_->parent->number_formats.begin(), d_->parent->number_formats.end(),
[=](const class number_format &nf) { return nf.id() == tarid; });
} }
style style::number_format(const xlnt::number_format &new_number_format, bool applied) style style::number_format(const xlnt::number_format &new_number_format, bool applied)
@ -178,64 +185,34 @@ style style::number_format(const xlnt::number_format &new_number_format, bool ap
copy.id(d_->parent->next_custom_number_format_id()); copy.id(d_->parent->next_custom_number_format_id());
d_->parent->number_formats.push_back(copy); d_->parent->number_formats.push_back(copy);
} }
else if (std::find_if(d_->parent->number_formats.begin(), d_->parent->number_formats.end(), else if (find_number_format(d_->parent->number_formats, copy.id())
[&copy](const class number_format &nf) { return nf.id() == copy.id(); }) == d_->parent->number_formats.end())
== d_->parent->number_formats.end()) {
{
d_->parent->number_formats.push_back(copy); d_->parent->number_formats.push_back(copy);
} }
d_->number_format_id = copy.id(); d_->number_format_id = copy.id();
d_->number_format_applied = applied; d_->number_format_applied = applied;
return style(d_); return *this;
} }
xlnt::protection &style::protection() xlnt::protection style::protection() const
{ {
return d_->parent->protections.at(d_->protection_id.get()); return d_->parent->protections.at(d_->protection_id.get());
} }
const xlnt::protection &style::protection() const bool style::protection_applied() const
{ {
return d_->parent->protections.at(d_->protection_id.get()); return d_->protection_applied;
} }
style style::protection(const xlnt::protection &new_protection, bool applied) style style::protection(const xlnt::protection &new_protection, bool applied)
{ {
d_->protection_id = d_->parent->find_or_add(d_->parent->protections, new_protection); d_->protection_id = d_->parent->find_or_add(d_->parent->protections, new_protection);
d_->protection_applied = applied; d_->protection_applied = applied;
return style(d_);
}
bool style::alignment_applied() const return *this;
{
return d_->alignment_applied;
}
bool style::border_applied() const
{
return d_->border_applied;
}
bool style::fill_applied() const
{
return d_->fill_applied;
}
bool style::font_applied() const
{
return d_->font_applied;
}
bool style::number_format_applied() const
{
return d_->number_format_applied;
}
bool style::protection_applied() const
{
return d_->protection_applied;
} }
bool style::pivot_button() const bool style::pivot_button() const

View File

@ -497,12 +497,7 @@ workbook workbook::empty()
.color(theme_color(1)); .color(theme_color(1));
stylesheet.fonts.push_back(default_font); stylesheet.fonts.push_back(default_font);
wb.create_style("Normal") wb.create_builtin_style(0);
.builtin_id(0)
.border(default_border, false)
.fill(default_fill, false)
.font(default_font, false)
.number_format(xlnt::number_format::general(), false);
wb.create_format(true) wb.create_format(true)
.border(default_border, false) .border(default_border, false)
@ -1351,6 +1346,11 @@ style workbook::create_style(const std::string &name)
return d_->stylesheet_.get().create_style(name); return d_->stylesheet_.get().create_style(name);
} }
style workbook::create_builtin_style(const std::size_t builtin_id)
{
return d_->stylesheet_.get().create_builtin_style(builtin_id);
}
style workbook::style(const std::string &name) style workbook::style(const std::string &name)
{ {
return d_->stylesheet_.get().style(name); return d_->stylesheet_.get().style(name);