Duplicate font item GUI
This commit is contained in:
parent
734026bf96
commit
310d53c1b9
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user