Add icon instead of text for rename and delete font item

This commit is contained in:
Filip Sykala 2021-10-06 16:36:50 +02:00
parent 5aadd690be
commit c112feb858
2 changed files with 167 additions and 96 deletions

View File

@ -23,6 +23,8 @@
#include <wx/fontutil.h>
#include <wx/fontdlg.h>
#include <GL/glew.h>
#ifdef __APPLE__
#include <wx/uri.h>
#include <CoreText/CTFont.h>
@ -154,6 +156,9 @@ void GLGizmoEmboss::initialize()
if (m_is_initialized) return;
m_is_initialized = true;
// TODO: What to do when icon was NOT loaded?
bool success = init_icons();
load_font_list();
m_gui_cfg.emplace(GuiCfg());
@ -169,11 +174,9 @@ void GLGizmoEmboss::initialize()
m_font_selected = 0; // select first
is_font_loaded = load_font();
}
//sort_fonts();
set_default_configuration();
}
void GLGizmoEmboss::load_font_list()
{
AppConfig *cfg = wxGetApp().app_config;
@ -265,11 +268,13 @@ ModelVolume *GLGizmoEmboss::get_selected_volume(const Selection &selection,
// create_text_volume()
bool GLGizmoEmboss::process()
{
// exist loaded font?
if (!m_font.has_value()) return false;
ExPolygons shapes = Emboss::text2shapes(*m_font, m_text.c_str(), m_font_prop);
if (shapes.empty()) return false;
// exist 2d shape made by text ?
// (no shape means that font doesnt have any of text symbols)
if (shapes.empty()) return false;
float scale = m_font_prop.size_in_mm / m_font->ascent;
auto project = std::make_unique<Emboss::ProjectScale>(
std::make_unique<Emboss::ProjectZ>(m_font_prop.emboss / scale), scale);
@ -363,9 +368,10 @@ void GLGizmoEmboss::draw_window()
if (!m_font.has_value()) {
ImGui::Text(_L("Warning: No font is selected. Select correct one.").c_str());
}
float left, right, bottom, top;
draw_font_list();
//ImGui::SameLine();
//if (ImGui::Button(_L("use system font").c_str())) {
// wxSystemSettings ss;
@ -409,6 +415,8 @@ void GLGizmoEmboss::draw_font_list()
auto &current = m_font_list[m_font_selected];
std::optional<int> rename_index;
if (ImGui::BeginCombo("##font_selector", current.name.c_str())) {
float combo_width = ImGui::GetItemRectSize().x
- (ImGui::GetTextLineHeightWithSpacing() - ImGui::GetTextLineHeight());
// first line
#ifdef USE_FONT_DIALOG
if (ImGui::Button(_L("Choose font").c_str())) {
@ -433,31 +441,7 @@ void GLGizmoEmboss::draw_font_list()
f.name :
(f.name.substr(0, m_gui_cfg->max_font_name - 3) + " ..");
int index = &f - &m_font_list.front();
bool is_selected = index == static_cast<int>(m_font_selected);
// must be befor selectable to be focusable
// add delete button
if (!is_selected) {
auto pos_x = ImGui::GetCursorPosX();
// add rename button
ImGui::SetCursorPosX(140);
if (ImGui::Button("rename")) rename_index = index;
ImGui::SameLine();
ImGui::SetCursorPosX(200);
m_imgui->disabled_begin(is_selected);
if (ImGui::Button("del")) {
m_font_list.erase(m_font_list.begin() + index);
// fix selected index
if (index < m_font_selected) --m_font_selected;
store_font_list();
}
m_imgui->disabled_end(); // exist_rename || is_selected
ImGui::SameLine();
ImGui::SetCursorPosX(pos_x);
}
if (ImGui::Selectable(name.c_str(), is_selected)) {
size_t prev_font_selected = m_font_selected;
m_font_selected = index;
@ -467,30 +451,27 @@ void GLGizmoEmboss::draw_font_list()
process();
}
}
ImGui::SameLine();
auto pos = ImGui::GetCursorPos();
// add rename button
ImGui::SetCursorPosX(combo_width - 2*ImGui::GetTextLineHeightWithSpacing());
if (draw_button(IconType::rename, false)) rename_index = index;
ImGui::SameLine();
ImGui::SetCursorPosX(combo_width - ImGui::GetTextLineHeightWithSpacing());
if (draw_button(IconType::erase, is_selected)) {
m_font_list.erase(m_font_list.begin() + index);
// fix selected index
if (index < m_font_selected) --m_font_selected;
store_font_list();
}
//ImGui::SetCursorPosX(pos_x);
ImGui::PopID();
}
ImGui::EndCombo();
}
// when more collection add selector
if (m_font.has_value() && m_font->count > 1) {
ImGui::SameLine();
if (ImGui::BeginCombo("##font_collection_selector",
std::to_string(m_font->index).c_str())) {
for (unsigned int i = 0; i < m_font->count; ++i) {
ImGui::PushID(1 << 10 + i);
if (ImGui::Selectable(std::to_string(i).c_str(),
i == m_font->index)) {
m_font->index = i;
m_font->cache.clear();
process();
}
ImGui::PopID();
}
ImGui::EndCombo();
}
}
// rename modal window popup
const char *rename_popup_id = "Rename modal window";
static int rename_id;
@ -511,20 +492,38 @@ void GLGizmoEmboss::draw_font_list()
}
void GLGizmoEmboss::draw_advanced() {
if (ImGui::InputFloat("Size[in mm]", &m_font_prop.size_in_mm)) {
if (ImGui::InputFloat(_L("Size[in mm]").c_str(), &m_font_prop.size_in_mm)) {
if (m_font_prop.size_in_mm < 0.1) m_font_prop.size_in_mm = 10;
process();
}
if (ImGui::InputFloat("Emboss[in mm]", &m_font_prop.emboss)) process();
if (ImGui::InputFloat("Flatness", &m_font_prop.flatness)) {
if (ImGui::InputFloat(_L("Emboss[in mm]").c_str(), &m_font_prop.emboss)) process();
if (ImGui::InputFloat(_L("Flatness").c_str(), &m_font_prop.flatness)) {
if (m_font.has_value()) m_font->cache.clear();
process();
}
if (ImGui::InputInt("CharGap[in font points]", &m_font_prop.char_gap))
if (ImGui::InputInt(_L("CharGap[in font points]").c_str(), &m_font_prop.char_gap))
process();
if (ImGui::InputInt("LineGap[in font points]", &m_font_prop.line_gap))
if (ImGui::InputInt(_L("LineGap[in font points]").c_str(), &m_font_prop.line_gap))
process();
// when more collection add selector
if (m_font.has_value() && m_font->count > 1) {
if (ImGui::BeginCombo(_L("Font collection").c_str(),
std::to_string(m_font->index).c_str())) {
for (unsigned int i = 0; i < m_font->count; ++i) {
ImGui::PushID(1 << 10 + i);
if (ImGui::Selectable(std::to_string(i).c_str(),
i == m_font->index)) {
m_font->index = i;
m_font->cache.clear();
process();
}
ImGui::PopID();
}
ImGui::EndCombo();
}
}
// ImGui::InputFloat3("Origin", m_orientation.origin.data());
// if (ImGui::InputFloat3("Normal", m_normal.data())) m_normal.normalize();
// if (ImGui::InputFloat3("Up", m_up.data())) m_up.normalize();
@ -589,8 +588,7 @@ bool GLGizmoEmboss::choose_font_by_wxdialog()
MessageDialog not_loaded_font_message(nullptr, message, title, wxOK);
not_loaded_font_message.ShowModal();
return choose_font_by_wxdialog();
}
//sort_fonts();
}
return true;
}
@ -604,20 +602,24 @@ bool GLGizmoEmboss::choose_true_type_file()
wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST);
if (dialog.ShowModal() == wxID_OK) dialog.GetPaths(input_files);
if (input_files.IsEmpty()) return false;
FontList font_list;
font_list.reserve(input_files.size());
bool font_loaded = false;
for (auto &input_file : input_files) {
std::string path = std::string(input_file.c_str());
size_t pos = path.find_last_of('\\');
size_t pos2 = path.find_last_of('.');
std::string name = path.substr(pos + 1, pos2 - pos - 1);
font_list.emplace_back(name, path);
m_font_list.emplace_back(name, path);
// set first valid added font as active
if (!font_loaded) {
if (!load_font(m_font_list.size() - 1))
m_font_list.pop_back();
else
font_loaded = true;
}
}
// set last added font as active
m_font_selected = m_font_list.size() + font_list.size() - 1;
add_fonts(font_list);
return load_font();
if (font_loaded) process();
return font_loaded;
}
bool GLGizmoEmboss::choose_svg_file()
@ -653,32 +655,6 @@ bool GLGizmoEmboss::choose_svg_file()
return add_volume(name, its);
}
void GLGizmoEmboss::sort_fonts() {
// initialize original index locations
std::vector<size_t> idx(m_font_list.size());
std::iota(idx.begin(), idx.end(), 0);
std::stable_sort(idx.begin(), idx.end(),
[this](size_t i1, size_t i2) {
return m_font_list[i1].name < m_font_list[i2].name;
});
FontList font_list;
font_list.reserve(m_font_list.size());
size_t selected = 0;
for (const size_t &i : idx) {
if (i == m_font_selected) selected = &i - &idx.front();
font_list.emplace_back(m_font_list[i]);
}
m_font_list = font_list;
m_font_selected = selected;
}
void GLGizmoEmboss::add_fonts(const FontList &font_list) {
m_font_list.insert(m_font_list.end(), font_list.begin(), font_list.end());
sort_fonts();
}
TextConfiguration GLGizmoEmboss::create_configuration() {
return TextConfiguration(m_font_list[m_font_selected], m_font_prop, m_text);
}
@ -699,14 +675,15 @@ bool GLGizmoEmboss::load_configuration(ModelVolume *volume)
// when not in font list add to list
if (index >= m_font_list.size()) {
m_font_selected = m_font_list.size();
add_fonts({configuration.font_item});
// TODO: what to do with new font item?
m_font_list.emplace_back(configuration.font_item);
} else {
m_font_selected = index;
}
// When can't load font
if (!load_font()) {
// remove bad loadabled font, for correct prev index
m_font_list.erase(m_font_list.begin() + m_font_selected);
m_font_list.pop_back();
m_font_selected = prev_font_selected;
return false;
}
@ -726,6 +703,95 @@ std::string GLGizmoEmboss::create_volume_name()
(m_text.substr(0, max_len - 3) + " ..") : m_text);
}
bool GLGizmoEmboss::init_icons()
{
std::string path = resources_dir() + "/icons/white/";
// icon order has to match the enum IconType
std::vector<std::string> filenames = {
path +"wrench.svg",
path +"delete.svg"
};
// state order has to match the enum IconState
std::vector<std::pair<int, bool>> states;
states.push_back(std::make_pair(1, false)); // Activable
states.push_back(std::make_pair(0, true)); // Hovered
states.push_back(std::make_pair(2, false)); // Disabled
unsigned int sprite_size_px = std::ceil(ImGui::GetTextLineHeight());
// make size pair number
if (sprite_size_px % 2 != 0) ++sprite_size_px;
bool compress = false;
return m_icons_texture.load_from_svg_files_as_sprites_array(filenames, states, sprite_size_px, compress);
}
void GLGizmoEmboss::draw_icon(IconType icon, IconState state)
{
unsigned int icons_texture_id = m_icons_texture.get_id();
int tex_width = m_icons_texture.get_width();
int tex_height = m_icons_texture.get_height();
// is icon loaded
if ((icons_texture_id == 0) || (tex_width <= 1) || (tex_height <= 1))
return;
ImTextureID tex_id = (void *) (intptr_t) (GLuint) icons_texture_id;
// ImVec2 image_size(tex_width, tex_height);
size_t count_icons = 2; // wrench | delete
size_t count_states = 3; // activable | hovered | disabled
ImVec2 icon_size(tex_width / count_states, tex_height / count_icons);
ImVec2 start(
static_cast<unsigned>(state)*icon_size.x,
static_cast<unsigned>(icon)*icon_size.y);
ImVec2 uv0(
start.x/tex_width,
start.y/tex_height);
ImVec2 uv1(
(start.x + icon_size.x) / tex_width,
(start.y + icon_size.y) / tex_height);
ImGui::Image(tex_id, icon_size, uv0, uv1);
}
bool GLGizmoEmboss::draw_button(IconType icon, bool disable)
{
float line_spacing = ImGui::GetTextLineHeightWithSpacing() -
ImGui::GetTextLineHeight();
float cursor_pos_y = ImGui::GetCursorPosY();
ImGui::SetCursorPosY(cursor_pos_y - line_spacing/2);
ScopeGuard sg([cursor_pos_y]() { ImGui::SetCursorPosY(cursor_pos_y); ImGui::NewLine();});
if (disable) {
draw_icon(icon, IconState::disabled);
if (ImGui::IsItemHovered() && icon == IconType::erase)
ImGui::SetTooltip(_L("Active font can't be removed").c_str());
return false;
}
float cursor_x = ImGui::GetCursorPosX();
draw_icon(icon, IconState::activable);
if (ImGui::IsItemClicked()) return true;
if (ImGui::IsItemHovered()) {
switch (icon) {
case IconType::rename: ImGui::SetTooltip(_L("rename").c_str()); break;
case IconType::erase: ImGui::SetTooltip(_L("delete").c_str()); break;
default: break;
}
// redraw image over previous
ImGui::SameLine();
ImGui::SetCursorPosX(cursor_x);
draw_icon(icon, IconState::hovered);
if (ImGui::IsItemClicked()) return true;
}
return false;
}
std::optional<Emboss::Font> WxFontUtils::load_font(const FontItem &fi)
{
switch (fi.type) {

View File

@ -4,6 +4,7 @@
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code,
// which overrides our localization "L" macro.
#include "GLGizmoBase.hpp"
#include "slic3r/GUI/GLTexture.hpp"
#include "admesh/stl.h" // indexed_triangle_set
#include <optional>
@ -14,7 +15,6 @@
#include "libslic3r/Model.hpp"
namespace Slic3r::GUI {
class GLGizmoEmboss : public GLGizmoBase
{
public:
@ -58,9 +58,6 @@ private:
bool choose_true_type_file();
bool choose_svg_file();
void sort_fonts();
void add_fonts(const FontList &font_list);
// Create object described how to make a Volume
TextConfiguration create_configuration();
bool load_configuration(ModelVolume *volume);
@ -105,6 +102,14 @@ private:
// initialize when GL is accessible
bool m_is_initialized;
// drawing icons
GLTexture m_icons_texture;
bool init_icons();
enum class IconType: unsigned { rename = 0, erase /*1*/};
enum class IconState: unsigned { activable = 0, hovered /*1*/, disabled /*2*/};
void draw_icon(IconType icon, IconState state);
bool draw_button(IconType icon, bool disable);
static const std::string M_APP_CFG_FONT_LIST;
// only temporary solution
static const std::string M_ICON_FILENAME;