From 62d8c80158a0aed989ea21c5e08b6c9e81f54dea Mon Sep 17 00:00:00 2001 From: Filip Sykala Date: Thu, 21 Oct 2021 19:42:13 +0200 Subject: [PATCH] Change appConfig store / load --- src/libslic3r/AppConfig.cpp | 2 +- src/libslic3r/AppConfig.hpp | 2 +- src/libslic3r/CMakeLists.txt | 2 - .../TextConfigurationSerialization.cpp | 168 ------------------ .../TextConfigurationSerialization.hpp | 130 -------------- src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp | 150 ++++++++++------ src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp | 14 +- 7 files changed, 107 insertions(+), 361 deletions(-) delete mode 100644 src/libslic3r/TextConfigurationSerialization.cpp delete mode 100644 src/libslic3r/TextConfigurationSerialization.hpp diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index fb12fee345..e8e2753728 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -39,7 +39,7 @@ static const std::string VERSION_CHECK_URL = "https://files.prusa3d.com/wp-conte const std::string AppConfig::SECTION_FILAMENTS = "filaments"; const std::string AppConfig::SECTION_MATERIALS = "sla_materials"; -const std::string AppConfig::SECTION_EMBOSS = "emboss"; +const std::string AppConfig::SECTION_FONT = "font"; void AppConfig::reset() { diff --git a/src/libslic3r/AppConfig.hpp b/src/libslic3r/AppConfig.hpp index 28014c4c17..1fc208482b 100644 --- a/src/libslic3r/AppConfig.hpp +++ b/src/libslic3r/AppConfig.hpp @@ -168,7 +168,7 @@ public: static const std::string SECTION_FILAMENTS; static const std::string SECTION_MATERIALS; - static const std::string SECTION_EMBOSS; + static const std::string SECTION_FONT; private: template diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index e4db506240..8cde4ae30d 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -206,8 +206,6 @@ add_library(libslic3r STATIC Tesselate.cpp Tesselate.hpp TextConfiguration.hpp - TextConfigurationSerialization.cpp - TextConfigurationSerialization.hpp TriangleMesh.cpp TriangleMesh.hpp TriangleMeshSlicer.cpp diff --git a/src/libslic3r/TextConfigurationSerialization.cpp b/src/libslic3r/TextConfigurationSerialization.cpp deleted file mode 100644 index c11cc3753a..0000000000 --- a/src/libslic3r/TextConfigurationSerialization.cpp +++ /dev/null @@ -1,168 +0,0 @@ -#include "TextConfigurationSerialization.hpp" -#include "Utils.hpp" - -using namespace Slic3r; -// Convert map -const std::map TextConfigurationSerialization::to_string = { - {FontItem::Type::file_path, "file_path"}, - {FontItem::Type::wx_font_descr, "wx_font_descriptor"}, - {FontItem::Type::undefined, "unknown"} -}; - -const std::map TextConfigurationSerialization::to_type = - TextConfigurationSerialization::create_oposit_map(TextConfigurationSerialization::to_string); - -const char TextConfigurationSerialization::separator = '|'; - -std::string TextConfigurationSerialization::serialize(const TextConfiguration &text_configuration) -{ - size_t size = 1 + 3 + 5; - std::vector columns; - columns.reserve(size); - columns.emplace_back(text_configuration.text); - to_columns(text_configuration.font_item, columns); - to_columns(text_configuration.font_prop, columns); - assert(columns.size() == size); - return serialize(columns, separator); -} - -std::optional TextConfigurationSerialization::deserialize(const std::string &data) -{ - size_t size = 1 + 3 + 5; - std::vector columns; - columns.reserve(size); - deserialize(data, separator, columns); - assert(columns.size() == size); - - const std::string& text = columns[0]; - std::optional font_item = get_font_item(columns, 1); - if (!font_item.has_value()) return {}; - std::optional font_prop = get_font_prop(columns, 4); - if (!font_prop.has_value()) return {}; - - return TextConfiguration(*font_item, *font_prop, text); -} - -std::string TextConfigurationSerialization::serialize(const FontList &font_list) -{ - std::vector columns; - columns.reserve(3 * font_list.size()); - for (const FontItem &fi : font_list) to_columns(fi, columns); - return serialize(columns, separator); -} - -FontList TextConfigurationSerialization::deserialize_font_list(const std::string &data) -{ - std::vector columns; - deserialize(data, separator, columns); - if ((columns.size() % 3) != 0) return {}; - size_t count = columns.size() / 3; - FontList fl; - fl.reserve(count); - for (size_t i = 0; i < count; i++) - { - std::optional fi = get_font_item(columns, i * 3); - if (!fi.has_value()) return {}; - fl.emplace_back(*fi); - } - return fl; -} - -std::string TextConfigurationSerialization::serialize(const std::vector &columns, char separator) -{ - std::string result; - const std::string separator_str = std::string(" ") + separator + ' '; - bool is_first = true; - for (const std::string& column : columns) { - if (is_first) is_first = false; - else result += separator_str; - result += twice(column, separator); - } - return result; -} - -void TextConfigurationSerialization::deserialize(const std::string &data, char separator, std::vector &columns) -{ - if (data.empty()) return; - - size_t position = 0; - while (position < data.size()) { - size_t start = position; - position = find_odd(data, position+1, separator); - size_t size = position - start; - - // is not last column - if (position != data.size()) { - assert(size != 0); - --size; - } - // is not first column - if (start != 0) { - // previous separator + space = 2 - start+=2; - assert(size >=2); - size-=2; - } - - std::string column = data.substr(start, size); - - // heal column - columns.emplace_back(reduce(column, separator)); - } -} - -std::string TextConfigurationSerialization::serialize(const FontItem::Type &type) -{ - auto it = to_string.find(type); - assert(it != to_string.end()); - if (it == to_string.end()) - return serialize(FontItem::Type::undefined); - return it->second; -} - -FontItem::Type TextConfigurationSerialization::deserialize_type(const std::string &type) -{ - auto it = to_type.find(type); - assert(it != to_type.end()); - if (it == to_type.end()) return FontItem::Type::undefined; - return it->second; -} - -void TextConfigurationSerialization::to_columns( - const FontItem &font_item, std::vector &columns) -{ - columns.emplace_back(font_item.name); - columns.emplace_back(font_item.path); - columns.emplace_back(serialize(font_item.type)); -} - -std::optional TextConfigurationSerialization::get_font_item( - const std::vector &columns, size_t offset) -{ - if (columns.size() <= (offset + 2)) return {}; // no enough columns - FontItem::Type type = deserialize_type(columns[offset + 2]); - return FontItem(columns[offset], columns[offset + 1], type); -} - -void TextConfigurationSerialization::to_columns( - const FontProp& font_prop, std::vector &columns) -{ - columns.emplace_back(std::to_string(font_prop.emboss)); - columns.emplace_back(std::to_string(font_prop.flatness)); - columns.emplace_back(std::to_string(font_prop.size_in_mm)); - columns.emplace_back(std::to_string(font_prop.char_gap)); - columns.emplace_back(std::to_string(font_prop.line_gap)); -} - -std::optional TextConfigurationSerialization::get_font_prop( - const std::vector &columns, size_t offset) -{ - if (columns.size() <= (offset + 4)) return {}; // no enough columns - FontProp font_prop; - font_prop.emboss = static_cast(std::atof(columns[offset].c_str())); - font_prop.flatness = static_cast(std::atof(columns[offset+1].c_str())); - font_prop.size_in_mm = static_cast(std::atof(columns[offset+2].c_str())); - font_prop.char_gap = static_cast(std::atof(columns[offset+3].c_str())); - font_prop.line_gap = std::atoi(columns[offset+4].c_str()); - return font_prop; -} \ No newline at end of file diff --git a/src/libslic3r/TextConfigurationSerialization.hpp b/src/libslic3r/TextConfigurationSerialization.hpp deleted file mode 100644 index b1ed25ba19..0000000000 --- a/src/libslic3r/TextConfigurationSerialization.hpp +++ /dev/null @@ -1,130 +0,0 @@ -#ifndef slic3r_TextConfigurationSerialization_hpp_ -#define slic3r_TextConfigurationSerialization_hpp_ - -#include "TextConfiguration.hpp" -#include -#include -#include -#include - -namespace Slic3r { - -// utility for convert TextConfiguration into string and vice versa -class TextConfigurationSerialization -{ -public: - TextConfigurationSerialization() = delete; // only static functions - - // store / load TextConfiguration - .3mf files - static std::string serialize(const TextConfiguration &text_configuration); - static std::optional deserialize(const std::string &data); - - // store / load FontList - AppConfig - static std::string serialize(const FontList &font_list); - static FontList deserialize_font_list(const std::string &data); - - static std::string serialize(const FontItem::Type &type); - static FontItem::Type deserialize_type(const std::string& type); - -private: - // convert type to string and vice versa - static const std::map to_type; - static const std::map to_string; - static const char separator; - - // store / load general connection of string into one string - static std::string serialize(const std::vector &columns, char separator); - static void deserialize(const std::string& data, char separator, std::vector &columns);// columns vector should be reserved on valid count - - static void to_columns(const FontItem& font_item, std::vector &columns); - static std::optional get_font_item(const std::vector &columns, size_t offset); - - static void to_columns(const FontProp& font_prop, std::vector &columns); - static std::optional get_font_prop(const std::vector &columns, size_t offset); - - /// - /// Twice all appearance of character in data. - /// Twiced character could be used as separator for this data. - /// IMPROVE: move to string utils - /// - /// input data to twice character - /// Specify character to be twiced in data - /// String conatin only pair continous count of specified character - static std::string twice(const std::string &data, char letter) - { - // no value is one space - if (data.empty()) return std::string(" "); - std::string::size_type pos = data.find(letter); - if (pos == data.npos) return data; - // twice all separator inside data - std::string copy = data; // copy - do { - copy.insert(pos, 1, letter); - pos += 2; - } while (copy.npos != (pos = copy.find(letter, pos))); - return copy; - }; - - /// - /// Reduce all twice appearance of character in data. - /// Main purpose heal after twice function. - /// IMPROVE: move to string utils - /// - /// input data to reduce character - /// Specify character to be reduced - /// String conatining only half letter in row - static std::string reduce(const std::string &data, char letter) - { - std::string::size_type pos = data.find(letter); - if (pos == data.npos) return data; - std::string copy = data; // copy - do { - std::string::size_type pos_plus_one = pos + 1; - // is data endig with odd number of letters - if (pos_plus_one == copy.npos) return copy; - // is pair count of letter - should not appear after twice - if (copy[pos_plus_one] != letter) continue; - - // reduce by removing first - copy.erase(pos, size_t(1)); - pos = copy.find(letter, pos_plus_one); - } while (pos != copy.npos); - return copy; - }; - - /// - /// Find odd position of letter in text data - /// Used with combination of twice and reduce - /// IMPROVE: move to string utils - /// - /// Input text - /// Start index into data for searching odd letter - /// Character to find - /// Index to data with next odd appearance of letter - /// OR size of data when NO next one exists - static size_t find_odd(const std::string &data, size_t pos, char letter) - { - pos = data.find(letter, pos); - while ((pos+1) <= data.size() && data[pos + 1] == letter) - pos = data.find(letter, pos + 2); - return pos; - } - - /// - /// Create map with swaped key-value - /// IMPROVE: Move to map utils - /// - /// Input map - /// Map with swapped key-value - template - static std::map create_oposit_map( - const std::map &map) - { - std::map result; - for (const auto &it : map) result[it.second] = it.first; - return result; - } -}; -} // namespace Slic3r - -#endif // slic3r_TextConfigurationSerialization_hpp_ diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp index 4367555342..a1e14a52d5 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp @@ -15,7 +15,6 @@ #include "libslic3r/Model.hpp" #include "libslic3r/ClipperUtils.hpp" // union_ex #include "libslic3r/AppConfig.hpp" // store/load font list -#include "libslic3r/TextConfigurationSerialization.hpp" // store/load font list #include "imgui/imgui_stdlib.h" // using std::string for inputs #include "nanosvg/nanosvg.h" // load SVG file @@ -215,7 +214,8 @@ void GLGizmoEmboss::on_render_for_picking() {} void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit) { check_selection(); - int flag = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | + int flag = //ImGuiWindowFlags_AlwaysAutoResize | + // ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse; m_imgui->begin(on_get_name(), flag); draw_window(); @@ -304,33 +304,11 @@ void GLGizmoEmboss::initialize() set_default_configuration(); } -void GLGizmoEmboss::load_font_list() -{ - const AppConfig *cfg = wxGetApp().app_config; - std::string font_list_str = cfg->get(AppConfig::SECTION_FONT, M_APP_CFG_FONT_LIST); - if (!font_list_str.empty()) { - std::optional fl = TextConfigurationSerialization::deserialize_font_list(font_list_str); - if (fl.has_value()) m_font_list = *fl; - } - if (m_font_list.empty()) m_font_list = create_default_font_list(); -} - -void GLGizmoEmboss::store_font_list() -{ - AppConfig *cfg = wxGetApp().app_config; - std::string font_list_str = TextConfigurationSerialization::serialize(m_font_list); - cfg->set(AppConfig::SECTION_FONT, M_APP_CFG_FONT_LIST, font_list_str); -} - FontList GLGizmoEmboss::create_default_font_list() { return { - {"NotoSans Regular", Slic3r::resources_dir() + "/fonts/NotoSans-Regular.ttf"} - , {"NotoSans CJK", Slic3r::resources_dir() + "/fonts/NotoSansCJK-Regular.ttc"} -#ifdef USE_FONT_DIALOG - , WxFontUtils::get_font_item(wxFont(5, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)) + WxFontUtils::get_font_item(wxFont(5, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)) , WxFontUtils::get_font_item(wxFont(10, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD)) , WxFontUtils::get_os_font() -#endif // USE_FONT_DIALOG }; } @@ -409,21 +387,9 @@ bool GLGizmoEmboss::process() void GLGizmoEmboss::set_volume_type(ModelVolumeType volume_type) { - const Selection& selection = m_parent.get_selection(); - if (selection.is_empty() || - selection.get_object_idx() < 0 || - m_volume == nullptr) - return; - + if (m_volume == nullptr) return; m_volume->set_type(volume_type); - - ObjectList* obj_list = wxGetApp().obj_list(); - ModelVolume* volume = m_volume; // copy pointer for lambda - wxDataViewItemArray sel = obj_list->reorder_volumes_and_get_selection(selection.get_object_idx(), [volume](const ModelVolume* vol) { return vol == volume; }); - if (!sel.IsEmpty()) - obj_list->select_item(sel.front()); - - obj_list->selection_changed(); + refresh_object_list(); m_parent.reload_scene(true); } @@ -471,6 +437,10 @@ bool GLGizmoEmboss::add_volume(const std::string &name, indexed_triangle_set &it m_volume->config.set_key_value("extruder", new ConfigOptionInt(0)); m_volume->text_configuration = create_configuration(); + // update volume name in object list + refresh_object_list(); + + m_parent.reload_scene(true); return true; } @@ -520,19 +490,18 @@ void GLGizmoEmboss::draw_font_list() ImGui::SetNextItemWidth(m_gui_cfg->combo_font_width); if (ImGui::BeginCombo("##font_selector", current_name.c_str())) { // first line -#ifdef USE_FONT_DIALOG if (ImGui::Button(_u8L("Choose font").c_str())) { choose_font_by_wxdialog(); store_font_list(); ImGui::CloseCurrentPopup(); - } else if (ImGui::IsItemHovered()) ImGui::SetTooltip(_u8L("Choose from installed font in dialog.").c_str()); - ImGui::SameLine(); -#endif // USE_FONT_DIALOG - if (ImGui::Button(_u8L("Add File").c_str())) { - choose_true_type_file(); - store_font_list(); - ImGui::CloseCurrentPopup(); - } else if (ImGui::IsItemHovered()) ImGui::SetTooltip(_u8L("add file with font(.ttf, .ttc)").c_str()); + } else if (ImGui::IsItemHovered()) ImGui::SetTooltip(_u8L("Choose from installed font inside dialog.").c_str()); + + // select font file by file browser + //if (ImGui::Button(_u8L("Add File").c_str())) { + // choose_true_type_file(); + // store_font_list(); + // ImGui::CloseCurrentPopup(); + //} else if (ImGui::IsItemHovered()) ImGui::SetTooltip(_u8L("add file with font(.ttf, .ttc)").c_str()); ImGui::Separator(); @@ -692,6 +661,23 @@ bool GLGizmoEmboss::create_default_model_object() return false; } +void GLGizmoEmboss::refresh_object_list() +{ + const Selection &selection = m_parent.get_selection(); + if (selection.is_empty() || + selection.get_object_idx() < 0 || + m_volume == nullptr) + return; + + ObjectList *obj_list = wxGetApp().obj_list(); + ModelVolume *volume = m_volume; // copy for lambda + auto add_to_selection = [volume](const ModelVolume *vol) { return vol == volume; }; + wxDataViewItemArray sel = obj_list->reorder_volumes_and_get_selection( + selection.get_object_idx(), add_to_selection); + if (!sel.IsEmpty()) obj_list->select_item(sel.front()); + obj_list->selection_changed(); +} + bool GLGizmoEmboss::load_font(size_t font_index) { std::swap(font_index, m_font_selected); @@ -978,15 +964,11 @@ void GLGizmoEmboss::notify_cant_load_font(const FontItem &font_item) { // TODO: Add closing of notification, when switch volume or edit auto type = NotificationType::CustomNotification; auto level = NotificationManager::NotificationLevel::WarningNotificationLevel; - std::string font_type_name = TextConfigurationSerialization::serialize(font_item.type); - std::string value = font_item.path; - // discard file path - if (font_item.type == FontItem::Type::file_path) value = get_file_name(value); std::string text = - GUI::format(_L("WARNING: Can't load font (name=\"%1%\", type=\"%2%\", value=\"%3%\"), " + GUI::format(_L("WARNING: Can't load font (name=\"%1%\", value=\"%3%\"), " "Selected font is different. " "When you edit, actual font will be used."), - font_item.name, font_type_name, value); + font_item.name, font_item.path); auto notification_manager = wxGetApp().plater()->get_notification_manager(); notification_manager->push_notification(type, level, text); } @@ -1115,6 +1097,64 @@ bool GLGizmoEmboss::draw_button(IconType icon, bool disable) return false; } +void GLGizmoEmboss::load_font_list() +{ + const AppConfig *cfg = wxGetApp().app_config; + unsigned index = 1; + std::string section_name = get_app_config_font_section(index++); + while (cfg->has_section(section_name)) { + std::optional fi = get_font_item( + cfg->get_section(section_name)); + if (fi.has_value()) m_font_list.emplace_back(*fi); + section_name = get_app_config_font_section(index++); + } + if (m_font_list.empty()) m_font_list = create_default_font_list(); +} + +void GLGizmoEmboss::store_font_list() +{ + AppConfig *cfg = wxGetApp().app_config; + unsigned index = 1; + for (const FontItem &fi : m_font_list) + set_font_item(*cfg, fi, index++); + + // remove rest of font sections + std::string section_name = get_app_config_font_section(index); + while (cfg->has_section(section_name)) { + cfg->clear_section(section_name); + section_name = get_app_config_font_section(++index); + } +} + +const std::string GLGizmoEmboss::APP_CONFIG_FONT_NAME = "name"; +const std::string GLGizmoEmboss::APP_CONFIG_FONT_DESCRIPTOR = "descriptor"; + +std::string GLGizmoEmboss::get_app_config_font_section(unsigned index) +{ + return AppConfig::SECTION_FONT + ':' + std::to_string(index); +} + +std::optional GLGizmoEmboss::get_font_item( + const std::map &app_cfg_section) +{ + auto path_it = app_cfg_section.find(APP_CONFIG_FONT_DESCRIPTOR); + if (path_it == app_cfg_section.end()) return {}; + const std::string& path = path_it->second; + + auto name_it = app_cfg_section.find(APP_CONFIG_FONT_NAME); + static const std::string default_name = "font_name"; + const std::string& name = (name_it == app_cfg_section.end()) ? + default_name : name_it->second; + return FontItem(name, path, FontItem::Type::wx_font_descr); +} + +void GLGizmoEmboss::set_font_item(AppConfig &cfg, const FontItem &fi, unsigned index) { + std::string section_name = get_app_config_font_section(index); + cfg.clear_section(section_name); + cfg.set(section_name, APP_CONFIG_FONT_NAME, fi.name); + cfg.set(section_name, APP_CONFIG_FONT_DESCRIPTOR, fi.path); +} + std::optional WxFontUtils::load_font(FontItem &fi) { switch (fi.type) { @@ -1284,7 +1324,5 @@ ExPolygons NSVGUtils::to_ExPolygons(NSVGimage *image, return Slic3r::union_ex(polygons); } -const std::string GLGizmoEmboss::M_APP_CFG_FONT_LIST = "font_list"; - // any existing icon filename to not influence GUI const std::string GLGizmoEmboss::M_ICON_FILENAME = "cut.svg"; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp index 4d5d230b5f..ff3d91173c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp @@ -16,6 +16,7 @@ #include +namespace Slic3r{class AppConfig;} namespace Slic3r::GUI { class GLGizmoEmboss : public GLGizmoBase { @@ -37,8 +38,6 @@ protected: private: void initialize(); - void load_font_list(); - void store_font_list(); static FontList create_default_font_list(); void set_default_configuration(); void check_selection(); @@ -55,6 +54,7 @@ private: void draw_advanced(); bool create_default_model_object(); + void refresh_object_list(); bool load_font(); // try to set font_index @@ -140,7 +140,15 @@ private: void draw_icon(IconType icon, IconState state); bool draw_button(IconType icon, bool disable = false); - static const std::string M_APP_CFG_FONT_LIST; + // load / store appConfig + void load_font_list(); + void store_font_list(); + static const std::string APP_CONFIG_FONT_NAME; + static const std::string APP_CONFIG_FONT_DESCRIPTOR; + std::string get_app_config_font_section(unsigned index); + std::optional get_font_item(const std::map &app_cfg_section); + void set_font_item(AppConfig &cfg, const FontItem &fi, unsigned index); + // only temporary solution static const std::string M_ICON_FILENAME; };