Next improvements of an undo/redo from a toolbar

This commit is contained in:
YuSanka 2019-07-09 15:27:28 +02:00
parent fbf14b42e9
commit 1347e655c2
8 changed files with 113 additions and 53 deletions

View file

@ -3442,6 +3442,41 @@ bool GLCanvas3D::_is_shown_on_screen() const
return (m_canvas != nullptr) ? m_canvas->IsShownOnScreen() : false; return (m_canvas != nullptr) ? m_canvas->IsShownOnScreen() : false;
} }
// Getter for the const char*[]
static bool string_getter(const bool is_undo, int idx, const char** out_text)
{
return wxGetApp().plater()->undo_redo_string_getter(is_undo, idx, out_text);
}
void GLCanvas3D::_render_undo_redo_stack(const bool is_undo, float pos_x)
{
if (m_canvas != nullptr && m_toolbar.get_imgui_visible(is_undo))
{
const wxString& stack_name = _(is_undo ? L("Undo") : L("Redo"));
ImGuiWrapper* imgui = wxGetApp().imgui();
const float x = pos_x * (float)get_camera().get_zoom() + 0.5f * (float)get_canvas_size().get_width();
imgui->set_next_window_pos(x, m_toolbar.get_height(), ImGuiCond_Always);
imgui->set_next_window_bg_alpha(0.5f);
imgui->begin(wxString::Format(_(L("%s Stack")), stack_name),
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
int hovered = m_toolbar.get_imgui_hovered_pos();
int selected = -1;
const float em = static_cast<float>(wxGetApp().em_unit());
if (imgui->undo_redo_list(ImVec2(12 * em, 20 * em), is_undo, &string_getter, hovered, selected))
m_toolbar.set_imgui_hovered_pos(hovered);
if (selected >= 0)
m_toolbar.hide_imgui(is_undo);
imgui->text(wxString::Format(_(L("%s %d Action")), stack_name, hovered + 1));
imgui->end();
}
}
bool GLCanvas3D::_init_toolbar() bool GLCanvas3D::_init_toolbar()
{ {
if (!m_toolbar.is_enabled()) if (!m_toolbar.is_enabled())
@ -3627,37 +3662,19 @@ bool GLCanvas3D::_init_toolbar()
#endif // ENABLE_SVG_ICONS #endif // ENABLE_SVG_ICONS
item.tooltip = _utf8(L("Undo")) + " [" + GUI::shortkey_ctrl_prefix() + "Z]"; item.tooltip = _utf8(L("Undo")) + " [" + GUI::shortkey_ctrl_prefix() + "Z]";
item.sprite_id = 11; item.sprite_id = 11;
item.action_callback = [this]() item.is_toggable = false;
{ item.action_callback = [this]() {
if (m_canvas != nullptr) { if (m_canvas != nullptr) {
wxPostEvent(m_canvas, SimpleEvent(EVT_GLCANVAS_UNDO)); wxPostEvent(m_canvas, SimpleEvent(EVT_GLCANVAS_UNDO));
m_toolbar.set_imgui_visible(); m_toolbar.activate_imgui(true);
} }
}; };
item.visibility_callback = []()->bool { return true; }; item.visibility_callback = []()->bool { return true; };
item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_undo(); }; item.enabled_state_callback = [this]()->bool {
item.render_callback = [this]() if (!wxGetApp().plater()->can_undo()) { m_toolbar.hide_imgui(true); return false; }
{ return true;
if (m_canvas != nullptr && m_toolbar.get_imgui_visible()) {
ImGuiWrapper* imgui = wxGetApp().imgui();
const float approx_height = m_toolbar.get_height();
imgui->set_next_window_pos(600, approx_height, ImGuiCond_Always);
imgui->set_next_window_bg_alpha(0.5f);
imgui->begin(_(L("Undo Stack")), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
std::vector <std::string> undo_stack = {"A", "B", "C", "D","A", "B", "C", "D","A", "B", "C", "D",};
int sel = 4;
imgui->multi_sel_list("", undo_stack, sel);
const bool undo_clicked = imgui->button(_(L("Undo N Action")));
imgui->end();
if (undo_clicked)
m_toolbar.set_imgui_visible(false);
}
}; };
item.render_callback = [this](float pos_x, float, float, float) { _render_undo_redo_stack(true, pos_x); };
if (!m_toolbar.add_item(item)) if (!m_toolbar.add_item(item))
return false; return false;
@ -3667,15 +3684,20 @@ bool GLCanvas3D::_init_toolbar()
#endif // ENABLE_SVG_ICONS #endif // ENABLE_SVG_ICONS
item.tooltip = _utf8(L("Redo")) + " [" + GUI::shortkey_ctrl_prefix() + "Y]"; item.tooltip = _utf8(L("Redo")) + " [" + GUI::shortkey_ctrl_prefix() + "Y]";
item.sprite_id = 12; item.sprite_id = 12;
item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLCANVAS_REDO)); }; item.action_callback = [this]() {
item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_redo(); }; if (m_canvas != nullptr) {
item.render_callback = []() {}; wxPostEvent(m_canvas, SimpleEvent(EVT_GLCANVAS_REDO));
m_toolbar.activate_imgui(false);
}
};
item.enabled_state_callback = [this]()->bool {
if (!wxGetApp().plater()->can_redo()) { m_toolbar.hide_imgui(false); return false; }
return true;
};
item.render_callback = [this](float pos_x, float, float, float) { _render_undo_redo_stack(false, pos_x); };
if (!m_toolbar.add_item(item)) if (!m_toolbar.add_item(item))
return false; return false;
if (!m_toolbar.add_separator())
return false;
return true; return true;
} }

View file

@ -676,6 +676,7 @@ private:
#endif // ENABLE_SHOW_CAMERA_TARGET #endif // ENABLE_SHOW_CAMERA_TARGET
void _render_sla_slices() const; void _render_sla_slices() const;
void _render_selection_sidebar_hints() const; void _render_selection_sidebar_hints() const;
void _render_undo_redo_stack(const bool is_undo, float pos_x);
void _update_volumes_hover_state() const; void _update_volumes_hover_state() const;

View file

@ -35,7 +35,7 @@ wxDEFINE_EVENT(EVT_GLVIEWTOOLBAR_PREVIEW, SimpleEvent);
const GLToolbarItem::ActionCallback GLToolbarItem::Default_Action_Callback = [](){}; const GLToolbarItem::ActionCallback GLToolbarItem::Default_Action_Callback = [](){};
const GLToolbarItem::VisibilityCallback GLToolbarItem::Default_Visibility_Callback = []()->bool { return true; }; const GLToolbarItem::VisibilityCallback GLToolbarItem::Default_Visibility_Callback = []()->bool { return true; };
const GLToolbarItem::EnabledStateCallback GLToolbarItem::Default_Enabled_State_Callback = []()->bool { return true; }; const GLToolbarItem::EnabledStateCallback GLToolbarItem::Default_Enabled_State_Callback = []()->bool { return true; };
const GLToolbarItem::RenderCallback GLToolbarItem::Default_Render_Callback = [](){}; const GLToolbarItem::RenderCallback GLToolbarItem::Default_Render_Callback = [](float, float, float, float){};
GLToolbarItem::Data::Data() GLToolbarItem::Data::Data()
: name("") : name("")
@ -84,7 +84,7 @@ void GLToolbarItem::render(unsigned int tex_id, float left, float right, float b
{ {
GLTexture::render_sub_texture(tex_id, left, right, bottom, top, get_uvs(tex_width, tex_height, icon_size)); GLTexture::render_sub_texture(tex_id, left, right, bottom, top, get_uvs(tex_width, tex_height, icon_size));
m_data.render_callback(); m_data.render_callback(left, right, bottom, top);
} }
GLTexture::Quad_UVs GLToolbarItem::get_uvs(unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const GLTexture::Quad_UVs GLToolbarItem::get_uvs(unsigned int tex_width, unsigned int tex_height, unsigned int icon_size) const

View file

@ -37,7 +37,7 @@ public:
typedef std::function<void()> ActionCallback; typedef std::function<void()> ActionCallback;
typedef std::function<bool()> VisibilityCallback; typedef std::function<bool()> VisibilityCallback;
typedef std::function<bool()> EnabledStateCallback; typedef std::function<bool()> EnabledStateCallback;
typedef std::function<void()> RenderCallback; typedef std::function<void(float, float,float, float)> RenderCallback;
enum EType : unsigned char enum EType : unsigned char
{ {
@ -252,7 +252,10 @@ private:
MouseCapture m_mouse_capture; MouseCapture m_mouse_capture;
std::string m_tooltip; std::string m_tooltip;
bool m_imgui_visible {false}; bool m_undo_imgui_visible {false};
bool m_redo_imgui_visible {false};
int m_imgui_hovered_pos { -1 };
int m_imgui_selected_pos { -1 };
public: public:
#if ENABLE_SVG_ICONS #if ENABLE_SVG_ICONS
@ -309,8 +312,21 @@ public:
bool on_mouse(wxMouseEvent& evt, GLCanvas3D& parent); bool on_mouse(wxMouseEvent& evt, GLCanvas3D& parent);
void set_imgui_visible(bool visible = true) { m_imgui_visible = visible; } // undo == true => "undo" imgui is activated
bool get_imgui_visible() { return m_imgui_visible; } // undo == false => "redo" imgui is activated
bool get_imgui_visible(const bool undo) const { return undo ? m_undo_imgui_visible : m_redo_imgui_visible; }
void hide_imgui(const bool undo) { undo ? m_undo_imgui_visible = false : m_redo_imgui_visible = false; }
void activate_imgui(const bool undo) {
m_undo_imgui_visible = undo;
m_redo_imgui_visible = !undo;
m_imgui_hovered_pos = m_imgui_selected_pos = -1;
}
void set_imgui_hovered_pos(int pos = -1) { m_imgui_hovered_pos = pos; }
int get_imgui_hovered_pos() const { return m_imgui_hovered_pos; }
void set_imgui_selected_pos(int pos = -1) { m_imgui_selected_pos = pos; }
int get_imgui_selected_pos() const { return m_imgui_selected_pos; }
private: private:
void calc_layout() const; void calc_layout() const;

View file

@ -342,25 +342,30 @@ bool ImGuiWrapper::combo(const wxString& label, const std::vector<std::string>&
return res; return res;
} }
// Getter for the const char*[] bool ImGuiWrapper::undo_redo_list(const ImVec2& size, const bool is_undo, bool (*items_getter)(const bool , int , const char**), int& hovered, int& selected)
static bool StringGetter(void* data, int i, const char** out_text)
{ {
const std::vector<std::string>* v = (std::vector<std::string>*)data; bool is_hovered = false;
if (out_text) ImGui::ListBoxHeader("", size);
*out_text = (*v)[i].c_str();
return true;
}
bool ImGuiWrapper::multi_sel_list(const wxString& label, const std::vector<std::string>& options, int& selection) int i=0;
{ const char* item_text;
// this is to force the label to the left of the widget: while (items_getter(is_undo, i, &item_text))
if (!label.IsEmpty()) {
text(label); ImGui::Selectable(item_text, i < hovered);
bool res = false; if (ImGui::IsItemHovered()) {
ImGui::ListBox("", &selection, StringGetter, (void*)&options, (int)options.size()); ImGui::SetTooltip(item_text);
hovered = i;
is_hovered = true;
}
return res; if (ImGui::IsItemClicked())
selected = i;
i++;
}
ImGui::ListBoxFooter();
return is_hovered;
} }
void ImGuiWrapper::disabled_begin(bool disabled) void ImGuiWrapper::disabled_begin(bool disabled)

View file

@ -67,7 +67,7 @@ public:
void text(const std::string &label); void text(const std::string &label);
void text(const wxString &label); void text(const wxString &label);
bool combo(const wxString& label, const std::vector<std::string>& options, int& selection); // Use -1 to not mark any option as selected bool combo(const wxString& label, const std::vector<std::string>& options, int& selection); // Use -1 to not mark any option as selected
bool multi_sel_list(const wxString& label, const std::vector<std::string>& options, int& selection); // Use -1 to not mark any option as selected bool undo_redo_list(const ImVec2& size, const bool is_undo, bool (*items_getter)(const bool, int, const char**), int& hovered, int& selected);
void disabled_begin(bool disabled); void disabled_begin(bool disabled);
void disabled_end(); void disabled_end();

View file

@ -4110,6 +4110,21 @@ void Plater::take_snapshot(const std::string &snapshot_name) { p->take_snapshot(
void Plater::take_snapshot(const wxString &snapshot_name) { p->take_snapshot(snapshot_name); } void Plater::take_snapshot(const wxString &snapshot_name) { p->take_snapshot(snapshot_name); }
void Plater::undo() { p->undo(); } void Plater::undo() { p->undo(); }
void Plater::redo() { p->redo(); } void Plater::redo() { p->redo(); }
bool Plater::undo_redo_string_getter(const bool is_undo, int idx, const char** out_text)
{
const size_t& active_snapshot_time = p->undo_redo_stack.active_snapshot_time();
const std::vector<UndoRedo::Snapshot>& ss_stack = p->undo_redo_stack.snapshots();
const auto it = std::lower_bound(ss_stack.begin(), ss_stack.end(), UndoRedo::Snapshot(active_snapshot_time));
const int idx_in_ss_stack = it - ss_stack.begin() + (is_undo ? -(++idx) : idx);
if (0 < idx_in_ss_stack && idx_in_ss_stack < ss_stack.size() - 1) {
*out_text = ss_stack[idx_in_ss_stack].name.c_str();
return true;
}
return false;
}
void Plater::on_extruders_change(int num_extruders) void Plater::on_extruders_change(int num_extruders)
{ {

View file

@ -187,6 +187,7 @@ public:
void take_snapshot(const wxString &snapshot_name); void take_snapshot(const wxString &snapshot_name);
void undo(); void undo();
void redo(); void redo();
bool undo_redo_string_getter(const bool is_undo, int idx, const char** out_text);
void on_extruders_change(int extruders_count); void on_extruders_change(int extruders_count);
void on_config_change(const DynamicPrintConfig &config); void on_config_change(const DynamicPrintConfig &config);