Next improvements of an undo/redo from a toolbar
This commit is contained in:
parent
fbf14b42e9
commit
1347e655c2
@ -3442,6 +3442,41 @@ bool GLCanvas3D::_is_shown_on_screen() const
|
||||
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()
|
||||
{
|
||||
if (!m_toolbar.is_enabled())
|
||||
@ -3627,37 +3662,19 @@ bool GLCanvas3D::_init_toolbar()
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
item.tooltip = _utf8(L("Undo")) + " [" + GUI::shortkey_ctrl_prefix() + "Z]";
|
||||
item.sprite_id = 11;
|
||||
item.action_callback = [this]()
|
||||
{
|
||||
item.is_toggable = false;
|
||||
item.action_callback = [this]() {
|
||||
if (m_canvas != nullptr) {
|
||||
wxPostEvent(m_canvas, SimpleEvent(EVT_GLCANVAS_UNDO));
|
||||
m_toolbar.set_imgui_visible();
|
||||
m_toolbar.activate_imgui(true);
|
||||
}
|
||||
};
|
||||
item.visibility_callback = []()->bool { return true; };
|
||||
item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_undo(); };
|
||||
item.render_callback = [this]()
|
||||
{
|
||||
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.enabled_state_callback = [this]()->bool {
|
||||
if (!wxGetApp().plater()->can_undo()) { m_toolbar.hide_imgui(true); return false; }
|
||||
return true;
|
||||
};
|
||||
item.render_callback = [this](float pos_x, float, float, float) { _render_undo_redo_stack(true, pos_x); };
|
||||
if (!m_toolbar.add_item(item))
|
||||
return false;
|
||||
|
||||
@ -3667,15 +3684,20 @@ bool GLCanvas3D::_init_toolbar()
|
||||
#endif // ENABLE_SVG_ICONS
|
||||
item.tooltip = _utf8(L("Redo")) + " [" + GUI::shortkey_ctrl_prefix() + "Y]";
|
||||
item.sprite_id = 12;
|
||||
item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLCANVAS_REDO)); };
|
||||
item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_redo(); };
|
||||
item.render_callback = []() {};
|
||||
item.action_callback = [this]() {
|
||||
if (m_canvas != nullptr) {
|
||||
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))
|
||||
return false;
|
||||
|
||||
if (!m_toolbar.add_separator())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -676,6 +676,7 @@ private:
|
||||
#endif // ENABLE_SHOW_CAMERA_TARGET
|
||||
void _render_sla_slices() 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;
|
||||
|
||||
|
@ -35,7 +35,7 @@ wxDEFINE_EVENT(EVT_GLVIEWTOOLBAR_PREVIEW, SimpleEvent);
|
||||
const GLToolbarItem::ActionCallback GLToolbarItem::Default_Action_Callback = [](){};
|
||||
const GLToolbarItem::VisibilityCallback GLToolbarItem::Default_Visibility_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()
|
||||
: 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));
|
||||
|
||||
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
|
||||
|
@ -37,7 +37,7 @@ public:
|
||||
typedef std::function<void()> ActionCallback;
|
||||
typedef std::function<bool()> VisibilityCallback;
|
||||
typedef std::function<bool()> EnabledStateCallback;
|
||||
typedef std::function<void()> RenderCallback;
|
||||
typedef std::function<void(float, float,float, float)> RenderCallback;
|
||||
|
||||
enum EType : unsigned char
|
||||
{
|
||||
@ -252,7 +252,10 @@ private:
|
||||
|
||||
MouseCapture m_mouse_capture;
|
||||
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:
|
||||
#if ENABLE_SVG_ICONS
|
||||
@ -309,8 +312,21 @@ public:
|
||||
|
||||
bool on_mouse(wxMouseEvent& evt, GLCanvas3D& parent);
|
||||
|
||||
void set_imgui_visible(bool visible = true) { m_imgui_visible = visible; }
|
||||
bool get_imgui_visible() { return m_imgui_visible; }
|
||||
// undo == true => "undo" imgui is activated
|
||||
// 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:
|
||||
void calc_layout() const;
|
||||
|
@ -342,25 +342,30 @@ bool ImGuiWrapper::combo(const wxString& label, const std::vector<std::string>&
|
||||
return res;
|
||||
}
|
||||
|
||||
// Getter for the const char*[]
|
||||
static bool StringGetter(void* data, int i, const char** out_text)
|
||||
bool ImGuiWrapper::undo_redo_list(const ImVec2& size, const bool is_undo, bool (*items_getter)(const bool , int , const char**), int& hovered, int& selected)
|
||||
{
|
||||
const std::vector<std::string>* v = (std::vector<std::string>*)data;
|
||||
if (out_text)
|
||||
*out_text = (*v)[i].c_str();
|
||||
return true;
|
||||
bool is_hovered = false;
|
||||
ImGui::ListBoxHeader("", size);
|
||||
|
||||
int i=0;
|
||||
const char* item_text;
|
||||
while (items_getter(is_undo, i, &item_text))
|
||||
{
|
||||
ImGui::Selectable(item_text, i < hovered);
|
||||
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip(item_text);
|
||||
hovered = i;
|
||||
is_hovered = true;
|
||||
}
|
||||
|
||||
bool ImGuiWrapper::multi_sel_list(const wxString& label, const std::vector<std::string>& options, int& selection)
|
||||
{
|
||||
// this is to force the label to the left of the widget:
|
||||
if (!label.IsEmpty())
|
||||
text(label);
|
||||
if (ImGui::IsItemClicked())
|
||||
selected = i;
|
||||
i++;
|
||||
}
|
||||
|
||||
bool res = false;
|
||||
ImGui::ListBox("", &selection, StringGetter, (void*)&options, (int)options.size());
|
||||
|
||||
return res;
|
||||
ImGui::ListBoxFooter();
|
||||
return is_hovered;
|
||||
}
|
||||
|
||||
void ImGuiWrapper::disabled_begin(bool disabled)
|
||||
|
@ -67,7 +67,7 @@ public:
|
||||
void text(const std::string &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 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_end();
|
||||
|
@ -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::undo() { p->undo(); }
|
||||
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)
|
||||
{
|
||||
|
@ -187,6 +187,7 @@ public:
|
||||
void take_snapshot(const wxString &snapshot_name);
|
||||
void undo();
|
||||
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_config_change(const DynamicPrintConfig &config);
|
||||
|
Loading…
Reference in New Issue
Block a user