Duplicate font item GUI

This commit is contained in:
Filip Sykala 2022-01-11 14:07:38 +01:00
parent 734026bf96
commit 310d53c1b9
3 changed files with 70 additions and 35 deletions

View File

@ -49,6 +49,7 @@ struct FontProp
// represent selected font // represent selected font
// Name must be human readable is visible in gui // Name must be human readable is visible in gui
// (Path + Type) must define how to open font for using on different OS // (Path + Type) must define how to open font for using on different OS
// NOTE: OnEdit fix serializations: FontListSerializable, TextConfigurationSerialization
struct FontItem struct FontItem
{ {
std::string name; std::string name;
@ -81,9 +82,12 @@ struct FontItem
// Font item name inside list is unique // Font item name inside list is unique
// FontList is not map beacuse items order matters (view of list) // FontList is not map beacuse items order matters (view of list)
// It is stored into AppConfig by FontListSerializable
using FontList = std::vector<FontItem>; using FontList = std::vector<FontItem>;
// define how to create 'Text volume' // define how to create 'Text volume'
// It is stored into .3mf by TextConfigurationSerialization
// Also it is stored into undo / redo stack by cereal
struct TextConfiguration struct TextConfiguration
{ {
// define font // define font

View File

@ -396,16 +396,18 @@ void GLGizmoEmboss::initialize()
ImGui::GetTextLineHeight(); ImGui::GetTextLineHeight();
m_gui_cfg->max_font_name_width = ImGui::CalcTextSize("Maximal font name").x; m_gui_cfg->max_font_name_width = ImGui::CalcTextSize("Maximal font name").x;
m_gui_cfg->icon_width = ImGui::GetTextLineHeight(); m_gui_cfg->icon_width = ImGui::GetTextLineHeight();
m_gui_cfg->icon_width_with_spacing = m_gui_cfg->icon_width + space; float icon_width_with_spacing = m_gui_cfg->icon_width + space;
float scroll_width = m_gui_cfg->icon_width_with_spacing; // fix float scroll_width = icon_width_with_spacing; // fix
m_gui_cfg->combo_font_width = m_gui_cfg->max_font_name_width + m_gui_cfg->combo_font_width = m_gui_cfg->max_font_name_width + space
2 * m_gui_cfg->icon_width_with_spacing + + 3 * icon_width_with_spacing
scroll_width; + scroll_width;
m_gui_cfg->rename_pos_x = m_gui_cfg->max_font_name_width + space; m_gui_cfg->duplicate_pos_x = m_gui_cfg->max_font_name_width + space;
m_gui_cfg->rename_pos_x = m_gui_cfg->duplicate_pos_x +
icon_width_with_spacing;
m_gui_cfg->delete_pos_x = m_gui_cfg->rename_pos_x + m_gui_cfg->delete_pos_x = m_gui_cfg->rename_pos_x +
m_gui_cfg->icon_width_with_spacing; icon_width_with_spacing;
m_gui_cfg->text_size = ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * m_gui_cfg->text_size = ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() *
m_gui_cfg->count_line_of_text); m_gui_cfg->count_line_of_text);
@ -616,8 +618,9 @@ void GLGizmoEmboss::draw_window()
void GLGizmoEmboss::draw_font_list() void GLGizmoEmboss::draw_font_list()
{ {
const float & max_width = m_gui_cfg->max_font_name_width; const float &max_width = m_gui_cfg->max_font_name_width;
std::optional<size_t> rename_index; std::optional<size_t> rename_index, delete_index, duplicate_index;
const std::string& current_name = m_font_list[m_font_selected].name; const std::string& current_name = m_font_list[m_font_selected].name;
std::string trunc_name = ImGuiWrapper::trunc(current_name, max_width); std::string trunc_name = ImGuiWrapper::trunc(current_name, max_width);
ImGui::SetNextItemWidth(m_gui_cfg->combo_font_width); ImGui::SetNextItemWidth(m_gui_cfg->combo_font_width);
@ -643,14 +646,13 @@ void GLGizmoEmboss::draw_font_list()
#endif // ALLOW_DEBUG_MODE #endif // ALLOW_DEBUG_MODE
ImGui::Separator(); ImGui::Separator();
for (FontItem &f : m_font_list) { for (FontItem &f : m_font_list) {
ImGui::PushID(f.name.c_str()); ImGui::PushID(f.name.c_str());
std::string name = ImGuiWrapper::trunc(f.name, max_width); std::string name = ImGuiWrapper::trunc(f.name, max_width);
size_t index = &f - &m_font_list.front(); size_t index = &f - &m_font_list.front();
bool is_selected = index == m_font_selected; bool is_selected = index == m_font_selected;
auto flags = ImGuiSelectableFlags_AllowItemOverlap; // allow click buttons ImGuiSelectableFlags_ flags = ImGuiSelectableFlags_AllowItemOverlap; // allow click buttons
if (ImGui::Selectable(name.c_str(), is_selected, flags)) { if (ImGui::Selectable(name.c_str(), is_selected, flags) ) {
if (load_font(index)) process(); if (load_font(index)) process();
} else if (ImGui::IsItemHovered()) } else if (ImGui::IsItemHovered())
ImGui::SetTooltip("%s", f.name.c_str()); ImGui::SetTooltip("%s", f.name.c_str());
@ -660,26 +662,44 @@ void GLGizmoEmboss::draw_font_list()
int other_index = index + (ImGui::GetMouseDragDelta(0).y < 0.f ? -1 : 1); int other_index = index + (ImGui::GetMouseDragDelta(0).y < 0.f ? -1 : 1);
if (other_index >= 0 && other_index < m_font_list.size()) { if (other_index >= 0 && other_index < m_font_list.size()) {
std::swap(m_font_list[index], m_font_list[other_index]); std::swap(m_font_list[index], m_font_list[other_index]);
// fix selected index
if (m_font_selected == other_index) m_font_selected = index;
else if (m_font_selected == index) m_font_selected = other_index;
ImGui::ResetMouseDragDelta(); ImGui::ResetMouseDragDelta();
} }
} }
// draw buttons rename and delete // draw buttons rename / duplicate / delete
ImGui::SameLine(); ImGui::SameLine(m_gui_cfg->rename_pos_x);
ImGui::SetCursorPosX(m_gui_cfg->rename_pos_x);
if (draw_button(IconType::rename)) rename_index = index; if (draw_button(IconType::rename)) rename_index = index;
ImGui::SameLine(); ImGui::SameLine(m_gui_cfg->duplicate_pos_x);
ImGui::SetCursorPosX(m_gui_cfg->delete_pos_x); if (draw_button(IconType::duplicate)) duplicate_index = index;
if (draw_button(IconType::erase, is_selected)) { ImGui::SameLine(m_gui_cfg->delete_pos_x);
if (draw_button(IconType::erase, is_selected)) delete_index = index;
ImGui::PopID();
}
ImGui::EndCombo();
}
// duplicate font item
if (duplicate_index.has_value()) {
size_t index = *duplicate_index;
FontItem fi = m_font_list[index]; // copy
make_unique_name(fi.name, m_font_list);
m_font_list.insert(m_font_list.begin() + index, fi);
// fix selected index
if (index < m_font_selected) ++m_font_selected;
store_font_list_to_app_config();
}
// delete font item
if (delete_index.has_value()) {
size_t index = *delete_index;
m_font_list.erase(m_font_list.begin() + index); m_font_list.erase(m_font_list.begin() + index);
// fix selected index // fix selected index
if (index < m_font_selected) --m_font_selected; if (index < m_font_selected) --m_font_selected;
store_font_list_to_app_config(); store_font_list_to_app_config();
} }
ImGui::PopID();
}
ImGui::EndCombo();
}
// rename modal window popup // rename modal window popup
const char *rename_popup_id = "Rename_font"; const char *rename_popup_id = "Rename_font";
@ -977,7 +997,7 @@ void GLGizmoEmboss::load_imgui_font()
m_imgui_font_atlas.TexID = (ImTextureID) (intptr_t) font_texture; m_imgui_font_atlas.TexID = (ImTextureID) (intptr_t) font_texture;
} }
static void make_unique_name(std::string &name, const FontList &list) void GLGizmoEmboss::make_unique_name(std::string &name, const FontList &list)
{ {
auto is_unique = [&list](const std::string &name)->bool { auto is_unique = [&list](const std::string &name)->bool {
for (const FontItem &fi : list) for (const FontItem &fi : list)
@ -988,6 +1008,13 @@ static void make_unique_name(std::string &name, const FontList &list)
if (name.empty()) name = "font"; if (name.empty()) name = "font";
if (is_unique(name)) return; if (is_unique(name)) return;
auto pos = name.find(" (");
if (pos != std::string::npos &&
name.find(")", pos) != std::string::npos) {
// short name by ord number
name = name.substr(0, pos);
}
int order = 1; // start with value 2 to represents same font name int order = 1; // start with value 2 to represents same font name
std::string new_name; std::string new_name;
do { do {
@ -1217,7 +1244,8 @@ bool GLGizmoEmboss::init_icons()
// icon order has to match the enum IconType // icon order has to match the enum IconType
std::vector<std::string> filenames = {path + "wrench.svg", std::vector<std::string> filenames = {path + "wrench.svg",
path + "delete.svg"}; path + "delete.svg",
path + "add_copies.svg"};
// state order has to match the enum IconState // state order has to match the enum IconState
std::vector<std::pair<int, bool>> states; std::vector<std::pair<int, bool>> states;
@ -1247,7 +1275,7 @@ void GLGizmoEmboss::draw_icon(IconType icon, IconState state)
ImTextureID tex_id = (void *) (intptr_t) (GLuint) icons_texture_id; ImTextureID tex_id = (void *) (intptr_t) (GLuint) icons_texture_id;
// ImVec2 image_size(tex_width, tex_height); // ImVec2 image_size(tex_width, tex_height);
size_t count_icons = 2; // wrench | delete size_t count_icons = 3; // wrench | delete | copy
size_t count_states = 3; // activable | hovered | disabled size_t count_states = 3; // activable | hovered | disabled
ImVec2 icon_size(tex_width / count_states, tex_height / count_icons); ImVec2 icon_size(tex_width / count_states, tex_height / count_icons);
@ -1284,22 +1312,23 @@ bool GLGizmoEmboss::draw_button(IconType icon, bool disable)
draw_icon(icon, IconState::activable); draw_icon(icon, IconState::activable);
if (ImGui::IsItemClicked()) return true; if (ImGui::IsItemClicked()) return true;
if (ImGui::IsItemHovered()) { if (ImGui::IsItemHovered()) {
std::string tooltip;
switch (icon) { switch (icon) {
case IconType::rename: case IconType::rename: tooltip = _u8L("rename"); break;
ImGui::SetTooltip("%s", _u8L("rename").c_str()); case IconType::erase: tooltip = _u8L("delete"); break;
break; case IconType::duplicate:tooltip = _u8L("duplicate"); break;
case IconType::erase:
ImGui::SetTooltip("%s", _u8L("delete").c_str());
break;
default: break; default: break;
} }
if (!tooltip.empty())
ImGui::SetTooltip("%s", tooltip.c_str());
// redraw image over previous // redraw image over previous
ImGui::SameLine(); ImGui::SameLine();
ImGui::SetCursorPosX(cursor_x); ImGui::SetCursorPosX(cursor_x);
draw_icon(icon, IconState::hovered); draw_icon(icon, IconState::hovered);
if (ImGui::IsItemClicked()) return true;
} }
return false; return false;
} }

View File

@ -113,6 +113,8 @@ private:
void load_imgui_font(); void load_imgui_font();
void check_imgui_font_range(); void check_imgui_font_range();
// TODO: move to fontList utils
static void make_unique_name(std::string &name, const FontList &list);
bool choose_font_by_wxdialog(); bool choose_font_by_wxdialog();
bool choose_true_type_file(); bool choose_true_type_file();
bool choose_svg_file(); bool choose_svg_file();
@ -152,9 +154,9 @@ private:
float combo_font_width = 0.f; float combo_font_width = 0.f;
float rename_pos_x = 0.f; float rename_pos_x = 0.f;
float delete_pos_x = 0.f; float delete_pos_x = 0.f;
float duplicate_pos_x = 0.f;
float max_font_name_width = 0.f; float max_font_name_width = 0.f;
float icon_width = 0.f; float icon_width = 0.f;
float icon_width_with_spacing = 0.f;
ImVec2 text_size; ImVec2 text_size;
GuiCfg() = default; GuiCfg() = default;
}; };
@ -191,7 +193,7 @@ private:
// drawing icons // drawing icons
GLTexture m_icons_texture; GLTexture m_icons_texture;
bool init_icons(); bool init_icons();
enum class IconType: unsigned { rename = 0, erase /*1*/}; enum class IconType: unsigned { rename = 0, erase /*1*/, duplicate /*2*/};
enum class IconState: unsigned { activable = 0, hovered /*1*/, disabled /*2*/}; enum class IconState: unsigned { activable = 0, hovered /*1*/, disabled /*2*/};
void draw_icon(IconType icon, IconState state); void draw_icon(IconType icon, IconState state);
bool draw_button(IconType icon, bool disable = false); bool draw_button(IconType icon, bool disable = false);