diff --git a/include/xlnt/styles/fill.hpp b/include/xlnt/styles/fill.hpp index a95a1665..dae5f586 100644 --- a/include/xlnt/styles/fill.hpp +++ b/include/xlnt/styles/fill.hpp @@ -23,69 +23,47 @@ // @author: see AUTHORS file #pragma once +#include + #include #include #include namespace xlnt { -/// -/// Describes the fill style of a particular cell. -/// -class XLNT_CLASS fill : public hashable +class pattern_fill : public hashable { public: enum class type { none, solid, - gradient, - pattern - }; - - enum class gradient_type - { - none, - linear, - path - }; - - enum class pattern_type - { - none, - solid, - darkdown, - darkgray, - darkgrid, - darkhorizontal, - darktrellis, - darkup, - darkvertical, - gray0625, - gray125, - lightdown, - lightgray, - lightgrid, - lighthorizontal, - lighttrellis, - lightup, - lightvertical, mediumgray, + darkgray, + lightgray, + darkhorizontal, + darkvertical, + darkdown, + darkup, + darkgrid, + darktrellis, + lighthorizontal, + lightvertical, + lightdown, + lightup, + lightgrid, + lighttrellis, + gray125, + gray0625 }; - - fill(); + + pattern_fill(); + + pattern_fill(type pattern_type); type get_type() const; - void set_type(type t); - - pattern_type get_pattern_type() const; - - void set_pattern_type(pattern_type t); - - gradient_type get_gradient_type() const; - - void set_gradient_type(gradient_type t); + void set_type(type pattern_type); void set_foreground_color(const color &c); @@ -99,49 +77,110 @@ public: const std::experimental::optional &get_background_color() const; - void set_start_color(const color &c); +protected: + std::string to_hash_string() const override; - std::experimental::optional &get_start_color(); +private: + type type_ = type::none; - const std::experimental::optional &get_start_color() const; + std::experimental::optional foreground_color_; + std::experimental::optional background_color_; +}; - void set_end_color(const color &c); +class gradient_fill : public hashable +{ +public: + enum class type + { + linear, + path + }; - std::experimental::optional &get_end_color(); + gradient_fill(); - const std::experimental::optional &get_end_color() const; + gradient_fill(type gradient_type); - void set_rotation(double rotation); + type get_type() const; - double get_rotation() const; + void set_type(type gradient_type); + + void set_degree(double degree); + + double get_degree() const; double get_gradient_left() const; + void set_gradient_left(double value); + double get_gradient_right() const; + void set_gradient_right(double value); + double get_gradient_top() const; + void set_gradient_top(double value); + double get_gradient_bottom() const; + void set_gradient_bottom(double value); + + void add_stop(double position, color stop_color); + + void delete_stop(double position); + + void clear_stops(); + + const std::unordered_map &get_stops() const; + protected: std::string to_hash_string() const override; private: - type type_; - pattern_type pattern_type_; - gradient_type gradient_type_; - - double rotation_; - - std::experimental::optional foreground_color_; - std::experimental::optional background_color_; - std::experimental::optional start_color_; - std::experimental::optional end_color_; - - double gradient_path_left_; - double gradient_path_right_; - double gradient_path_top_; - double gradient_path_bottom_; + type type_ = type::linear; + + std::unordered_map stops_; + + double degree_ = 0; + + double left_ = 0; + double right_ = 0; + double top_ = 0; + double bottom_ = 0; +}; + +/// +/// Describes the fill style of a particular cell. +/// +class XLNT_CLASS fill : public hashable +{ +public: + enum class type + { + pattern, + gradient + }; + + static fill gradient(gradient_fill::type gradient_type); + + static fill pattern(pattern_fill::type pattern_type); + + type get_type() const; + + gradient_fill &get_gradient_fill(); + + const gradient_fill &get_gradient_fill() const; + + pattern_fill &get_pattern_fill(); + + const pattern_fill &get_pattern_fill() const; + +protected: + std::string to_hash_string() const override; + +private: + type type_ = type::pattern; + gradient_fill gradient_; + pattern_fill pattern_; }; } // namespace xlnt diff --git a/source/cell/tests/test_cell.hpp b/source/cell/tests/test_cell.hpp index 9f8e5af1..4cd65ce7 100644 --- a/source/cell/tests/test_cell.hpp +++ b/source/cell/tests/test_cell.hpp @@ -360,9 +360,8 @@ public: auto ws = wb.create_sheet(); auto cell = ws.get_cell("A1"); - xlnt::fill f; - f.set_pattern_type(xlnt::fill::pattern_type::solid); - f.set_foreground_color(xlnt::color(xlnt::color::type::rgb, "FF0000")); + xlnt::fill f = xlnt::fill::pattern(xlnt::pattern_fill::type::solid); + f.get_pattern_fill().set_foreground_color(xlnt::color::red()); cell.set_fill(f); diff --git a/source/detail/style_serializer.cpp b/source/detail/style_serializer.cpp index fcb94625..314f95fe 100644 --- a/source/detail/style_serializer.cpp +++ b/source/detail/style_serializer.cpp @@ -144,46 +144,46 @@ std::string underline_style_to_string(xlnt::font::underline_style underline_styl // fill::pattern_type serialization -const std::unordered_map &get_string_pattern_fill_type_map() +const std::unordered_map &get_string_pattern_fill_type_map() { - static std::unordered_map *map = nullptr; + static std::unordered_map *map = nullptr; if (map == nullptr) { - map = new std::unordered_map + map = new std::unordered_map { - { "darkdown", xlnt::fill::pattern_type::darkdown }, - { "darkgray", xlnt::fill::pattern_type::darkgray }, - { "darkgrid", xlnt::fill::pattern_type::darkgrid }, - { "darkhorizontal", xlnt::fill::pattern_type::darkhorizontal }, - { "darktrellis", xlnt::fill::pattern_type::darktrellis }, - { "darkup", xlnt::fill::pattern_type::darkup }, - { "darkvertical", xlnt::fill::pattern_type::darkvertical }, - { "gray0625", xlnt::fill::pattern_type::gray0625 }, - { "gray125", xlnt::fill::pattern_type::gray125 }, - { "lightdown", xlnt::fill::pattern_type::lightdown }, - { "lightgray", xlnt::fill::pattern_type::lightgray }, - { "lightgrid", xlnt::fill::pattern_type::lightgrid }, - { "lighthorizontal", xlnt::fill::pattern_type::lighthorizontal }, - { "lighttrellis", xlnt::fill::pattern_type::lighttrellis }, - { "lightup", xlnt::fill::pattern_type::lightup }, - { "lightvertical", xlnt::fill::pattern_type::lightvertical }, - { "mediumgray", xlnt::fill::pattern_type::mediumgray }, - { "none", xlnt::fill::pattern_type::none }, - { "solid", xlnt::fill::pattern_type::solid } + { "darkdown", xlnt::pattern_fill::type::darkdown }, + { "darkgray", xlnt::pattern_fill::type::darkgray }, + { "darkgrid", xlnt::pattern_fill::type::darkgrid }, + { "darkhorizontal", xlnt::pattern_fill::type::darkhorizontal }, + { "darktrellis", xlnt::pattern_fill::type::darktrellis }, + { "darkup", xlnt::pattern_fill::type::darkup }, + { "darkvertical", xlnt::pattern_fill::type::darkvertical }, + { "gray0625", xlnt::pattern_fill::type::gray0625 }, + { "gray125", xlnt::pattern_fill::type::gray125 }, + { "lightdown", xlnt::pattern_fill::type::lightdown }, + { "lightgray", xlnt::pattern_fill::type::lightgray }, + { "lightgrid", xlnt::pattern_fill::type::lightgrid }, + { "lighthorizontal", xlnt::pattern_fill::type::lighthorizontal }, + { "lighttrellis", xlnt::pattern_fill::type::lighttrellis }, + { "lightup", xlnt::pattern_fill::type::lightup }, + { "lightvertical", xlnt::pattern_fill::type::lightvertical }, + { "mediumgray", xlnt::pattern_fill::type::mediumgray }, + { "none", xlnt::pattern_fill::type::none }, + { "solid", xlnt::pattern_fill::type::solid } }; } return *map; } -const std::unordered_map &get_pattern_fill_type_string_map() +const std::unordered_map &get_pattern_fill_type_string_map() { - static std::unordered_map *map = nullptr; + static std::unordered_map *map = nullptr; if (map == nullptr) { - map = new std::unordered_map; + map = new std::unordered_map; for (auto pair : get_string_pattern_fill_type_map()) { @@ -194,16 +194,61 @@ const std::unordered_map & return *map; } -xlnt::fill::pattern_type pattern_fill_type_from_string(const std::string &fill_type) +xlnt::pattern_fill::type pattern_fill_type_from_string(const std::string &fill_type) { return get_string_pattern_fill_type_map().at(string_lower(fill_type)); }; -std::string pattern_fill_type_to_string(xlnt::fill::pattern_type fill_type) +std::string pattern_fill_type_to_string(xlnt::pattern_fill::type fill_type) { return get_pattern_fill_type_string_map().at(fill_type); } +// fill::gradient_type serialization + +const std::unordered_map &get_string_gradient_fill_type_map() +{ + static std::unordered_map *map = nullptr; + + if (map == nullptr) + { + map = new std::unordered_map + { + { "linear", xlnt::gradient_fill::type::linear }, + { "path", xlnt::gradient_fill::type::path } + }; + } + + return *map; +} + +const std::unordered_map &get_gradient_fill_type_string_map() +{ + static std::unordered_map *map = nullptr; + + if (map == nullptr) + { + map = new std::unordered_map; + + for (auto pair : get_string_gradient_fill_type_map()) + { + map->emplace(pair.second, pair.first); + } + } + + return *map; +} + +xlnt::gradient_fill::type gradient_fill_type_from_string(const std::string &fill_type) +{ + return get_string_gradient_fill_type_map().at(string_lower(fill_type)); +}; + +std::string gradient_fill_type_to_string(xlnt::gradient_fill::type fill_type) +{ + return get_gradient_fill_type_string_map().at(fill_type); +} + // border_style serialization @@ -563,25 +608,41 @@ xlnt::fill read_fill(const pugi::xml_node &fill_node) if (fill_node.child("patternFill")) { - new_fill.set_type(xlnt::fill::type::pattern); - auto pattern_fill_node = fill_node.child("patternFill"); std::string pattern_fill_type_string = pattern_fill_node.attribute("patternType").value(); if (!pattern_fill_type_string.empty()) { - new_fill.set_pattern_type(pattern_fill_type_from_string(pattern_fill_type_string)); + new_fill = xlnt::fill::pattern(pattern_fill_type_from_string(pattern_fill_type_string)); if (pattern_fill_node.child("bgColor")) { - new_fill.get_background_color() = read_color(pattern_fill_node.child("bgColor")); + new_fill.get_pattern_fill().get_background_color() = read_color(pattern_fill_node.child("bgColor")); } if (pattern_fill_node.child("fgColor")) { - new_fill.get_foreground_color() = read_color(pattern_fill_node.child("fgColor")); + new_fill.get_pattern_fill().get_foreground_color() = read_color(pattern_fill_node.child("fgColor")); } } + else + { + new_fill = xlnt::fill::pattern(xlnt::pattern_fill::type::none); + } + } + else if (fill_node.child("gradientFill")) + { + auto gradient_fill_node = fill_node.child("gradientFill"); + std::string gradient_fill_type_string = gradient_fill_node.attribute("gradientType").value(); + + if (!gradient_fill_type_string.empty()) + { + new_fill = xlnt::fill::gradient(gradient_fill_type_from_string(gradient_fill_type_string)); + } + else + { + new_fill = xlnt::fill::gradient(xlnt::gradient_fill::type::linear); + } } return new_fill; @@ -895,46 +956,59 @@ bool write_fills(const std::vector &fills, pugi::xml_node &fills_nod if (fill_.get_type() == xlnt::fill::type::pattern) { + const auto &pattern = fill_.get_pattern_fill(); + auto pattern_fill_node = fill_node.append_child("patternFill"); - pattern_fill_node.append_attribute("patternType").set_value(pattern_fill_type_to_string(fill_.get_pattern_type()).c_str()); - - if (fill_.get_pattern_type() != xlnt::fill::pattern_type::solid) continue; + pattern_fill_node.append_attribute("patternType").set_value(pattern_fill_type_to_string(pattern.get_type()).c_str()); - if (fill_.get_foreground_color()) + if (pattern.get_foreground_color()) { - write_color(*fill_.get_foreground_color(), pattern_fill_node.append_child("fgColor")); + write_color(*pattern.get_foreground_color(), pattern_fill_node.append_child("fgColor")); } - if (fill_.get_background_color()) + if (pattern.get_background_color()) { - write_color(*fill_.get_background_color(), pattern_fill_node.append_child("bgColor")); + write_color(*pattern.get_background_color(), pattern_fill_node.append_child("bgColor")); } } - else if (fill_.get_type() == xlnt::fill::type::solid) - { - auto solid_fill_node = fill_node.append_child("solidFill"); - solid_fill_node.append_child("color"); - } else if (fill_.get_type() == xlnt::fill::type::gradient) { + const auto &gradient = fill_.get_gradient_fill(); + auto gradient_fill_node = fill_node.append_child("gradientFill"); + auto gradient_fill_type_string = gradient_fill_type_to_string(gradient.get_type()); + gradient_fill_node.append_attribute("gradientType").set_value(gradient_fill_type_string.c_str()); - if (fill_.get_gradient_type() == xlnt::fill::gradient_type::linear) + if (gradient.get_degree() != 0) { - gradient_fill_node.append_attribute("degree").set_value(std::to_string(fill_.get_rotation()).c_str()); + gradient_fill_node.append_attribute("degree").set_value(gradient.get_degree()); } - else if (fill_.get_gradient_type() == xlnt::fill::gradient_type::path) + + if (gradient.get_gradient_left() != 0) { - gradient_fill_node.append_attribute("left").set_value(std::to_string(fill_.get_gradient_left()).c_str()); - gradient_fill_node.append_attribute("right").set_value(std::to_string(fill_.get_gradient_right()).c_str()); - gradient_fill_node.append_attribute("top").set_value(std::to_string(fill_.get_gradient_top()).c_str()); - gradient_fill_node.append_attribute("bottom").set_value(std::to_string(fill_.get_gradient_bottom()).c_str()); + gradient_fill_node.append_attribute("left").set_value(gradient.get_gradient_left()); + } - auto start_node = gradient_fill_node.append_child("stop"); - start_node.append_attribute("position").set_value("0"); + if (gradient.get_gradient_right() != 0) + { + gradient_fill_node.append_attribute("right").set_value(gradient.get_gradient_right()); + } - auto end_node = gradient_fill_node.append_child("stop"); - end_node.append_attribute("position").set_value("1"); + if (gradient.get_gradient_top() != 0) + { + gradient_fill_node.append_attribute("top").set_value(gradient.get_gradient_top()); + } + + if (gradient.get_gradient_bottom() != 0) + { + gradient_fill_node.append_attribute("bottom").set_value(gradient.get_gradient_bottom()); + } + + for (const auto &stop : gradient.get_stops()) + { + auto stop_node = gradient_fill_node.append_child("stop"); + stop_node.append_attribute("position").set_value(stop.first); + write_color(stop.second, stop_node.append_child("color")); } } } @@ -989,6 +1063,41 @@ bool write_borders(const std::vector &borders, pugi::xml_node &bor return true; } +bool write_alignment(const xlnt::alignment &a, pugi::xml_node alignment_node) +{ + if (a.has_vertical()) + { + auto vertical = vertical_alignment_to_string(a.get_vertical()); + alignment_node.append_attribute("vertical").set_value(vertical.c_str()); + } + + if (a.has_horizontal()) + { + auto horizontal = horizontal_alignment_to_string(a.get_horizontal()); + alignment_node.append_attribute("horizontal").set_value(horizontal.c_str()); + } + + if (a.get_wrap_text()) + { + alignment_node.append_attribute("wrapText").set_value("1"); + } + + if (a.get_shrink_to_fit()) + { + alignment_node.append_attribute("shrinkToFit").set_value("1"); + } + + return true; +} + +bool write_protection(const xlnt::protection &p, pugi::xml_node protection_node) +{ + protection_node.append_attribute("locked").set_value(p.get_locked() ? "1" : "0"); + protection_node.append_attribute("hidden").set_value(p.get_hidden() ? "1" : "0"); + + return true; +} + bool write_base_format(const xlnt::base_format &xf, const xlnt::detail::stylesheet &stylesheet, pugi::xml_node xf_node) { xf_node.append_attribute("numFmtId").set_value(std::to_string(xf.get_number_format().get_id()).c_str()); @@ -1006,41 +1115,17 @@ bool write_base_format(const xlnt::base_format &xf, const xlnt::detail::styleshe if(xf.fill_applied()) xf_node.append_attribute("applyFill").set_value("1"); if(xf.font_applied()) xf_node.append_attribute("applyFont").set_value("1"); if(xf.border_applied()) xf_node.append_attribute("applyBorder").set_value("1"); - if(xf.alignment_applied()) xf_node.append_attribute("applyAlignment").set_value("1"); - if(xf.protection_applied()) xf_node.append_attribute("applyProtection").set_value("1"); - if (xf.alignment_applied()) + if(xf.alignment_applied()) { - auto alignment_node = xf_node.append_child("alignment"); - - if (xf.get_alignment().has_vertical()) - { - auto vertical = vertical_alignment_to_string(xf.get_alignment().get_vertical()); - alignment_node.append_attribute("vertical").set_value(vertical.c_str()); - } - - if (xf.get_alignment().has_horizontal()) - { - auto horizontal = horizontal_alignment_to_string(xf.get_alignment().get_horizontal()); - alignment_node.append_attribute("horizontal").set_value(horizontal.c_str()); - } - - if (xf.get_alignment().get_wrap_text()) - { - alignment_node.append_attribute("wrapText").set_value("1"); - } - - if (xf.get_alignment().get_shrink_to_fit()) - { - alignment_node.append_attribute("shrinkToFit").set_value("1"); - } + xf_node.append_attribute("applyAlignment").set_value("1"); + write_alignment(xf.get_alignment(), xf_node.append_child("alignment")); } if (xf.protection_applied()) { - auto protection_node = xf_node.append_child("protection"); - protection_node.append_attribute("locked").set_value(xf.get_protection().get_locked() ? "1" : "0"); - protection_node.append_attribute("hidden").set_value(xf.get_protection().get_hidden() ? "1" : "0"); + xf_node.append_attribute("applyProtection").set_value("1"); + write_protection(xf.get_protection(), xf_node.append_child("protection")); } return true; diff --git a/source/styles/fill.cpp b/source/styles/fill.cpp index 30cd185b..888ac433 100644 --- a/source/styles/fill.cpp +++ b/source/styles/fill.cpp @@ -26,103 +26,105 @@ namespace xlnt { -fill::fill() - : type_(type::pattern), - pattern_type_(pattern_type::none), - gradient_type_(gradient_type::none), - rotation_(0), - gradient_path_left_(0), - gradient_path_right_(0), - gradient_path_top_(0), - gradient_path_bottom_(0) -{ -} - fill::type fill::get_type() const { return type_; } -void fill::set_type(type t) +pattern_fill::type pattern_fill::get_type() const +{ + return type_; +} + +void pattern_fill::set_type(pattern_fill::type t) { type_ = t; } -fill::pattern_type fill::get_pattern_type() const +gradient_fill::type gradient_fill::get_type() const { - return pattern_type_; + return type_; } -void fill::set_pattern_type(pattern_type t) +void gradient_fill::set_type(gradient_fill::type t) { - type_ = type::pattern; - pattern_type_ = t; + type_ = t; } -fill::gradient_type fill::get_gradient_type() const -{ - return gradient_type_; -} - -void fill::set_gradient_type(gradient_type t) -{ - type_ = type::gradient; - gradient_type_ = t; -} - -void fill::set_foreground_color(const color &c) +void pattern_fill::set_foreground_color(const color &c) { foreground_color_ = c; } -std::experimental::optional &fill::get_foreground_color() +std::experimental::optional &pattern_fill::get_foreground_color() { return foreground_color_; } -const std::experimental::optional &fill::get_foreground_color() const +const std::experimental::optional &pattern_fill::get_foreground_color() const { return foreground_color_; } -std::experimental::optional &fill::get_background_color() +void pattern_fill::set_background_color(const color &c) +{ + background_color_ = c; +} + +std::experimental::optional &pattern_fill::get_background_color() { return background_color_; } -const std::experimental::optional &fill::get_background_color() const +const std::experimental::optional &pattern_fill::get_background_color() const { return background_color_; } -std::experimental::optional &fill::get_start_color() +void gradient_fill::set_degree(double degree) { - return start_color_; + degree_ = degree; } -const std::experimental::optional &fill::get_start_color() const +double gradient_fill::get_degree() const { - return start_color_; + return degree_; } -std::experimental::optional &fill::get_end_color() +std::string pattern_fill::to_hash_string() const { - return end_color_; + std::string hash_string = "pattern_fill"; + + hash_string.append(background_color_ ? "1" : "0"); + + if (background_color_) + { + hash_string.append(std::to_string(background_color_->hash())); + } + + hash_string.append(background_color_ ? "1" : "0"); + + if (background_color_) + { + hash_string.append(std::to_string(background_color_->hash())); + } + + return hash_string; } -const std::experimental::optional &fill::get_end_color() const +std::string gradient_fill::to_hash_string() const { - return end_color_; -} + std::string hash_string = "gradient_fill"; -void fill::set_rotation(double rotation) -{ - rotation_ = rotation; -} - -double fill::get_rotation() const -{ - return rotation_; + hash_string.append(std::to_string(static_cast(type_))); + hash_string.append(std::to_string(stops_.size())); + hash_string.append(std::to_string(degree_)); + hash_string.append(std::to_string(left_)); + hash_string.append(std::to_string(right_)); + hash_string.append(std::to_string(top_)); + hash_string.append(std::to_string(bottom_)); + + return hash_string; } std::string fill::to_hash_string() const @@ -134,99 +136,154 @@ std::string fill::to_hash_string() const switch (type_) { case type::pattern: - { - hash_string.append(std::to_string(static_cast(pattern_type_))); - - hash_string.append(background_color_ ? "1" : "0"); - - if (background_color_) - { - hash_string.append(std::to_string(background_color_->hash())); - } - - hash_string.append(background_color_ ? "1" : "0"); - - if (background_color_) - { - hash_string.append(std::to_string(background_color_->hash())); - } - + hash_string.append(std::to_string(pattern_.hash())); break; - } + case type::gradient: - { - hash_string.append(std::to_string(static_cast(gradient_type_))); - - if (gradient_type_ == gradient_type::path) - { - hash_string.append(std::to_string(gradient_path_left_)); - hash_string.append(std::to_string(gradient_path_right_)); - hash_string.append(std::to_string(gradient_path_top_)); - hash_string.append(std::to_string(gradient_path_bottom_)); - } - else if (gradient_type_ == gradient_type::linear) - { - hash_string.append(std::to_string(rotation_)); - } - - hash_string.append(start_color_ ? "1" : "0"); - - if (start_color_) - { - hash_string.append(std::to_string(start_color_->hash())); - } - - hash_string.append(end_color_ ? "1" : "0"); - - if (end_color_) - { - hash_string.append(std::to_string(end_color_->hash())); - } - + hash_string.append(std::to_string(gradient_.hash())); break; - } + default: - { break; - } } // switch (type_) return hash_string; } -double fill::get_gradient_left() const +double gradient_fill::get_gradient_left() const { - return gradient_path_left_; + return left_; } -double fill::get_gradient_right() const +void gradient_fill::set_gradient_left(double value) { - return gradient_path_right_; + left_ = value; } -double fill::get_gradient_top() const +double gradient_fill::get_gradient_right() const { - return gradient_path_top_; + return right_; } -double fill::get_gradient_bottom() const +void gradient_fill::set_gradient_right(double value) { - return gradient_path_bottom_; + right_ = value; } -void fill::set_background_color(const color &c) +double gradient_fill::get_gradient_top() const { - background_color_ = c; + return top_; } -void fill::set_start_color(const color &c) +void gradient_fill::set_gradient_top(double value) { - start_color_ = c; + top_ = value; } -void fill::set_end_color(const color &c) +double gradient_fill::get_gradient_bottom() const { - end_color_ = c; + return bottom_; +} + +void gradient_fill::set_gradient_bottom(double value) +{ + bottom_ = value; +} + +fill fill::pattern(pattern_fill::type pattern_type) +{ + fill f; + f.type_ = type::pattern; + f.pattern_ = pattern_fill(pattern_type); + return f; +} + +fill fill::gradient(gradient_fill::type gradient_type) +{ + fill f; + f.type_ = type::gradient; + f.gradient_ = gradient_fill(gradient_type); + return f; +} + +pattern_fill::pattern_fill(type pattern_type) : type_(pattern_type) +{ + +} + +pattern_fill::pattern_fill() : pattern_fill(type::none) +{ + +} + +gradient_fill::gradient_fill(type gradient_type) : type_(gradient_type) +{ + +} + +gradient_fill::gradient_fill() : gradient_fill(type::linear) +{ + +} + +gradient_fill &fill::get_gradient_fill() +{ + if (type_ != fill::type::gradient) + { + throw std::runtime_error("not gradient"); + } + + return gradient_; +} + +const gradient_fill &fill::get_gradient_fill() const +{ + if (type_ != fill::type::gradient) + { + throw std::runtime_error("not gradient"); + } + + return gradient_; +} + +pattern_fill &fill::get_pattern_fill() +{ + if (type_ != fill::type::pattern) + { + throw std::runtime_error("not pattern"); + } + + return pattern_; +} + +const pattern_fill &fill::get_pattern_fill() const +{ + if (type_ != fill::type::pattern) + { + throw std::runtime_error("not pattern"); + } + + return pattern_; +} + +void gradient_fill::add_stop(double position, color stop_color) +{ + stops_[position] = stop_color; +} + +void gradient_fill::delete_stop(double position) +{ + stops_.erase(stops_.find(position)); +} + +void gradient_fill::clear_stops() +{ + stops_.clear(); +} + +const std::unordered_map &gradient_fill::get_stops() const +{ + return stops_; } } // namespace xlnt diff --git a/source/styles/tests/test_fill.hpp b/source/styles/tests/test_fill.hpp index decd56d0..34b3a70c 100644 --- a/source/styles/tests/test_fill.hpp +++ b/source/styles/tests/test_fill.hpp @@ -12,66 +12,45 @@ public: { xlnt::fill fill; - TS_ASSERT_EQUALS(fill.get_gradient_type(), xlnt::fill::gradient_type::none); - fill.set_gradient_type(xlnt::fill::gradient_type::linear); - TS_ASSERT_EQUALS(fill.get_gradient_type(), xlnt::fill::gradient_type::linear); + TS_ASSERT_EQUALS(fill.get_type(), xlnt::fill::type::pattern); + fill = xlnt::fill::gradient(xlnt::gradient_fill::type::linear); + TS_ASSERT_EQUALS(fill.get_type(), xlnt::fill::type::gradient); + TS_ASSERT_EQUALS(fill.get_gradient_fill().get_type(), xlnt::gradient_fill::type::linear); + + TS_ASSERT_EQUALS(fill.get_gradient_fill().get_gradient_left(), 0); + TS_ASSERT_EQUALS(fill.get_gradient_fill().get_gradient_right(), 0); + TS_ASSERT_EQUALS(fill.get_gradient_fill().get_gradient_top(), 0); + TS_ASSERT_EQUALS(fill.get_gradient_fill().get_gradient_bottom(), 0); + + TS_ASSERT_THROWS(fill.get_pattern_fill(), std::runtime_error); + + TS_ASSERT_EQUALS(fill.get_gradient_fill().get_degree(), 0); + fill.get_gradient_fill().set_degree(1); + TS_ASSERT_EQUALS(fill.get_gradient_fill().get_degree(), 1); + + fill = xlnt::fill::pattern(xlnt::pattern_fill::type::solid); + + fill.get_pattern_fill().set_foreground_color(xlnt::color::black()); + TS_ASSERT(fill.get_pattern_fill().get_foreground_color()); + TS_ASSERT_EQUALS(*fill.get_pattern_fill().get_foreground_color(), xlnt::color::black()); - TS_ASSERT(!fill.get_foreground_color()); - fill.set_foreground_color(xlnt::color::black()); - TS_ASSERT(fill.get_foreground_color()); - - TS_ASSERT(!fill.get_background_color()); - fill.set_background_color(xlnt::color::black()); - TS_ASSERT(fill.get_background_color()); - - TS_ASSERT(!fill.get_start_color()); - fill.set_start_color(xlnt::color::black()); - TS_ASSERT(fill.get_start_color()); - - TS_ASSERT(!fill.get_end_color()); - fill.set_end_color(xlnt::color::black()); - TS_ASSERT(fill.get_end_color()); - - TS_ASSERT_EQUALS(fill.get_rotation(), 0); - fill.set_rotation(1); - TS_ASSERT_EQUALS(fill.get_rotation(), 1); - - TS_ASSERT_EQUALS(fill.get_gradient_bottom(), 0); - TS_ASSERT_EQUALS(fill.get_gradient_left(), 0); - TS_ASSERT_EQUALS(fill.get_gradient_top(), 0); - TS_ASSERT_EQUALS(fill.get_gradient_right(), 0); + fill.get_pattern_fill().set_background_color(xlnt::color::green()); + TS_ASSERT(fill.get_pattern_fill().get_background_color()); + TS_ASSERT_EQUALS(*fill.get_pattern_fill().get_background_color(), xlnt::color::green()); const auto &const_fill = fill; - TS_ASSERT(const_fill.get_foreground_color()); - TS_ASSERT(const_fill.get_background_color()); - TS_ASSERT(const_fill.get_start_color()); - TS_ASSERT(const_fill.get_end_color()); + TS_ASSERT(const_fill.get_pattern_fill().get_foreground_color()); + TS_ASSERT(const_fill.get_pattern_fill().get_background_color()); } void test_hash() { - xlnt::fill none_fill; + xlnt::fill pattern_fill = xlnt::fill::pattern(xlnt::pattern_fill::type::solid); + xlnt::fill gradient_fill_linear = xlnt::fill::gradient(xlnt::gradient_fill::type::linear); + xlnt::fill gradient_fill_path = xlnt::fill::gradient(xlnt::gradient_fill::type::path); - xlnt::fill solid_fill; - solid_fill.set_type(xlnt::fill::type::solid); - - xlnt::fill pattern_fill; - pattern_fill.set_type(xlnt::fill::type::pattern); - - xlnt::fill gradient_fill_linear; - gradient_fill_linear.set_type(xlnt::fill::type::gradient); - gradient_fill_linear.set_gradient_type(xlnt::fill::gradient_type::linear); - - xlnt::fill gradient_fill_path; - gradient_fill_path.set_type(xlnt::fill::type::gradient); - gradient_fill_path.set_gradient_type(xlnt::fill::gradient_type::path); - gradient_fill_path.set_start_color(xlnt::color::red()); - gradient_fill_path.set_end_color(xlnt::color::green()); - - TS_ASSERT_DIFFERS(none_fill.hash(), solid_fill.hash()); - TS_ASSERT_DIFFERS(solid_fill.hash(), pattern_fill.hash()); TS_ASSERT_DIFFERS(pattern_fill.hash(), gradient_fill_linear.hash()); TS_ASSERT_DIFFERS(gradient_fill_linear.hash(), gradient_fill_path.hash()); - TS_ASSERT_DIFFERS(gradient_fill_path.hash(), none_fill.hash()); + TS_ASSERT_DIFFERS(gradient_fill_path.hash(), pattern_fill.hash()); } }; diff --git a/source/workbook/tests/test_style_writer.hpp b/source/workbook/tests/test_style_writer.hpp index 0e5f3e12..06f19efa 100644 --- a/source/workbook/tests/test_style_writer.hpp +++ b/source/workbook/tests/test_style_writer.hpp @@ -214,4 +214,147 @@ public: TS_ASSERT(style_xml_matches(expected, wb)); } + + void test_alignment() + { + xlnt::workbook wb; + xlnt::alignment a; + a.set_horizontal(xlnt::horizontal_alignment::center_continuous); + a.set_vertical(xlnt::vertical_alignment::justify); + a.set_wrap_text(true); + a.set_shrink_to_fit(true); + wb.get_active_sheet().get_cell("A1").set_alignment(a); + + std::string expected = + "" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + ""; + TS_ASSERT(style_xml_matches(expected, wb)); + } + + void test_fill() + { + xlnt::workbook wb; + + xlnt::fill pattern_fill = xlnt::fill::pattern(xlnt::pattern_fill::type::solid); + pattern_fill.get_pattern_fill().set_foreground_color(xlnt::color::red()); + pattern_fill.get_pattern_fill().set_background_color(xlnt::color::blue()); + wb.get_active_sheet().get_cell("A1").set_fill(pattern_fill); + + xlnt::fill gradient_fill_linear = xlnt::fill::gradient(xlnt::gradient_fill::type::linear); + gradient_fill_linear.get_gradient_fill().set_degree(90); + wb.get_active_sheet().get_cell("A1").set_fill(gradient_fill_linear); + + xlnt::fill gradient_fill_path = xlnt::fill::gradient(xlnt::gradient_fill::type::path); + gradient_fill_path.get_gradient_fill().set_gradient_left(1); + gradient_fill_path.get_gradient_fill().set_gradient_right(2); + gradient_fill_path.get_gradient_fill().set_gradient_top(3); + gradient_fill_path.get_gradient_fill().set_gradient_bottom(4); + gradient_fill_path.get_gradient_fill().add_stop(0, xlnt::color::red()); + gradient_fill_path.get_gradient_fill().add_stop(1, xlnt::color::blue()); + wb.get_active_sheet().get_cell("A1").set_fill(gradient_fill_path); + + std::string expected = + "" + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + ""; + TS_ASSERT(style_xml_matches(expected, wb)); + } }; diff --git a/source/workbook/workbook.cpp b/source/workbook/workbook.cpp index 14ee51a1..e1e2dbf7 100644 --- a/source/workbook/workbook.cpp +++ b/source/workbook/workbook.cpp @@ -92,9 +92,7 @@ workbook::workbook() : d_(new detail::workbook_impl()) create_style("Normal"); d_->stylesheet_.format_styles.front() = "Normal"; - xlnt::fill gray125; - gray125.set_type(xlnt::fill::type::pattern); - gray125.set_pattern_type(xlnt::fill::pattern_type::gray125); + xlnt::fill gray125 = xlnt::fill::pattern(xlnt::pattern_fill::type::gray125); d_->stylesheet_.fills.push_back(gray125); }