diff --git a/src/imgui/imgui.h b/src/imgui/imgui.h index 086ae77f27..4b3c13ac60 100644 --- a/src/imgui/imgui.h +++ b/src/imgui/imgui.h @@ -658,6 +658,7 @@ namespace ImGui IMGUI_API void EndMainMenuBar(); // only call EndMainMenuBar() if BeginMainMenuBar() returns true! IMGUI_API bool BeginMenu(const char* label, bool enabled = true); // create a sub-menu entry. only call EndMenu() if this returns true! IMGUI_API void EndMenu(); // only call EndMenu() if BeginMenu() returns true! + IMGUI_API bool BBLMenuItem(const char* label, const char* shortcut = NULL, bool selected = false, bool enabled = true); // return true when activated. IMGUI_API bool MenuItem(const char* label, const char* shortcut = NULL, bool selected = false, bool enabled = true); // return true when activated. IMGUI_API bool MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled = true); // return true when activated + toggle (*p_selected) if p_selected != NULL diff --git a/src/imgui/imgui_widgets.cpp b/src/imgui/imgui_widgets.cpp index b14c26487a..a9b59d241b 100644 --- a/src/imgui/imgui_widgets.cpp +++ b/src/imgui/imgui_widgets.cpp @@ -2078,7 +2078,7 @@ bool ImGui::BBLBeginCombo(const char *label, const char *preview_value, ImGuiCom const ImVec2 label_size = CalcTextSize(label, NULL, true); const float expected_w = CalcItemWidth(); const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : expected_w; - const ImRect frame_bb(window->DC.CursorPos - ImVec2(0.0, style.FramePadding.y), window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y)); + const ImRect frame_bb(window->DC.CursorPos - ImVec2(0.0, style.FramePadding.y), window->DC.CursorPos + ImVec2(w - arrow_size * 2, label_size.y + style.FramePadding.y)); const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); ItemSize(total_bb, style.FramePadding.y); if (!ItemAdd(total_bb, id, &frame_bb)) return false; @@ -2136,7 +2136,7 @@ bool ImGui::BBLBeginCombo(const char *label, const char *preview_value, ImGuiCom popup_max_height_in_items = 4; else if (flags & ImGuiComboFlags_HeightLarge) popup_max_height_in_items = 20; - SetNextWindowSizeConstraints(ImVec2(w, 0.0f), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items))); + SetNextWindowSizeConstraints(ImVec2(w - arrow_size * 2, 0.0f), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items))); } char name[16]; @@ -7104,7 +7104,11 @@ bool ImGui::BBLSelectable(const char *label, bool selected, ImGuiSelectableFlags bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags); if (hovered || g.ActiveId == id) { ImGui::PushStyleColor(ImGuiCol_Border, GetColorU32(ImGuiCol_BorderActive)); - RenderFrameBorder(ImVec2(bb.Min.x + style.ItemSpacing.x,bb.Min.y), ImVec2(bb.Max.x - style.ItemSpacing.x,bb.Max.y), style.FrameRounding); + if(arrow_size == 0) { + RenderFrameBorder(bb.Min, ImVec2(bb.Max.x - style.WindowPadding.x, bb.Max.y), style.FrameRounding); + } else { + RenderFrameBorder(ImVec2(bb.Min.x + style.WindowPadding.x,bb.Min.y), ImVec2(bb.Max.x - style.WindowPadding.x,bb.Max.y), style.FrameRounding); + } ImGui::PopStyleColor(1); } // Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard @@ -7126,7 +7130,11 @@ bool ImGui::BBLSelectable(const char *label, bool selected, ImGuiSelectableFlags if (held && (flags & ImGuiSelectableFlags_DrawHoveredWhenHeld)) hovered = true; if (hovered || selected) { const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); - RenderFrame(ImVec2(bb.Min.x + style.ItemSpacing.x, bb.Min.y), ImVec2(bb.Max.x - style.ItemSpacing.x, bb.Max.y), col, false, 0.0f); + if(arrow_size == 0) { + RenderFrame(bb.Min, ImVec2(bb.Max.x - style.WindowPadding.x, bb.Max.y), col, false, 0.0f); + } else { + RenderFrame(ImVec2(bb.Min.x + style.WindowPadding.x, bb.Min.y), ImVec2(bb.Max.x - style.WindowPadding.x, bb.Max.y), col, false, 0.0f); + } RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding); } @@ -7859,6 +7867,55 @@ void ImGui::EndMenu() EndPopup(); } +bool ImGui::BBLMenuItem(const char* label, const char* shortcut, bool selected, bool enabled) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + ImGuiStyle& style = g.Style; + ImVec2 pos = window->DC.CursorPos; + ImVec2 label_size = CalcTextSize(label, NULL, true); + + // We've been using the equivalent of ImGuiSelectableFlags_SetNavIdOnHover on all Selectable() since early Nav system days (commit 43ee5d73), + // but I am unsure whether this should be kept at all. For now moved it to be an opt-in feature used by menus only. + ImGuiSelectableFlags flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_SetNavIdOnHover | (enabled ? 0 : ImGuiSelectableFlags_Disabled); + bool pressed; + if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) + { + // Mimic the exact layout spacing of BeginMenu() to allow MenuItem() inside a menu bar, which is a little misleading but may be useful + // Note that in this situation: we don't render the shortcut, we render a highlight instead of the selected tick mark. + float w = label_size.x; + window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f); + PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y)); + pressed = BBLSelectable(label, selected, flags, ImVec2(w, 0.0f)); + PopStyleVar(); + window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). + } + else + { + // Menu item inside a vertical menu + // (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f. + // Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system. + float shortcut_w = shortcut ? CalcTextSize(shortcut, NULL).x : 0.0f; + float min_w = window->DC.MenuColumns.DeclColumns(label_size.x, shortcut_w, IM_FLOOR(g.FontSize * 1.20f)); // Feedback for next frame + float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w); + pressed = BBLSelectable(label, false, flags | ImGuiSelectableFlags_SpanAvailWidth | ImGuiComboFlags_NoArrowButton, ImVec2(min_w, 0.0f)); + if (shortcut_w > 0.0f) + { + PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); + RenderText(pos + ImVec2(window->DC.MenuColumns.Pos[1] + extra_w, 0.0f), shortcut, NULL, false); + PopStyleColor(); + } + if (selected) + RenderCheckMark(window->DrawList, pos + ImVec2(window->DC.MenuColumns.Pos[2] + extra_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f); + } + + IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.LastItemStatusFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0)); + return pressed; +} + bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, bool enabled) { ImGuiWindow* window = GetCurrentWindow(); diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 184e328a44..dca819da3f 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -3946,6 +3946,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv //BBS: GUI refactor: move to the right imgui.set_next_window_pos(float(canvas_width - right_margin * m_scale), 0.0f, ImGuiCond_Always, 1.0f, 0.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0,0.0)); ImGui::PushStyleColor(ImGuiCol_Separator, ImVec4(1.0f,1.0f,1.0f,0.6f)); ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.00f, 0.68f, 0.26f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.00f, 0.68f, 0.26f, 1.0f)); @@ -3979,8 +3980,15 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv const float percent_bar_size = 0; bool imperial_units = wxGetApp().app_config->get("use_inches") == "1"; + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + ImVec2 pos_rect = ImGui::GetCursorScreenPos(); + float window_padding = 4.0f * m_scale; - auto append_item = [icon_size, percent_bar_size, &imgui, imperial_units](EItemType type, const Color &color, const std::string &label, + draw_list->AddRectFilled(ImVec2(pos_rect.x,pos_rect.y - ImGui::GetStyle().WindowPadding.y), + ImVec2(pos_rect.x + ImGui::GetWindowWidth() + ImGui::GetFrameHeight(),pos_rect.y + ImGui::GetFrameHeight() + window_padding * 2.5), + ImGui::GetColorU32(ImVec4(0,0,0,0.3))); + + auto append_item = [icon_size, percent_bar_size, &imgui, imperial_units,&window_padding,&draw_list,this](EItemType type, const Color &color, const std::string &label, bool visible = true, const std::string& time = "", float percent = 0.0f, float max_percent = 0.0f, const std::array& offsets = { 0.0f, 0.0f, 0.0f, 0.0f }, double used_filament_m = 0.0, double used_filament_g = 0.0, std::function callback = nullptr) { @@ -3989,13 +3997,13 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.3333f); */ - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - ImVec2 pos = ImGui::GetCursorScreenPos(); - float dummy_size = icon_size; + ImVec2 pos = ImVec2(ImGui::GetCursorScreenPos().x + window_padding * 3, ImGui::GetCursorScreenPos().y); + float dummy_size = icon_size * m_scale; + switch (type) { default: case EItemType::Rect: { - draw_list->AddRectFilled({ pos.x + 1.0f, pos.y + 5.0f }, { pos.x + icon_size - 1.0f, pos.y + icon_size + 3.0f }, + draw_list->AddRectFilled({ pos.x + 1.0f * m_scale, pos.y + 3.0f * m_scale }, { pos.x + icon_size - 1.0f * m_scale, pos.y + icon_size + 1.0f * m_scale }, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f })); break; } @@ -4019,10 +4027,18 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv } // draw text - ImGui::Dummy({ dummy_size, dummy_size }); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(20.0, 6.0 * m_scale)); + ImGui::Dummy({ dummy_size, 0.0 }); ImGui::SameLine(); if (callback != nullptr) { - if (ImGui::MenuItem(label.c_str())) + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f * m_scale); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(20.0 * m_scale,0.0)); + ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(1.00f, 0.68f, 0.26f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_BorderActive, ImVec4(0.00f, 0.68f, 0.26f, 1.00f)); + bool b_menu_item = ImGui::BBLMenuItem(label.c_str()); + ImGui::PopStyleVar(2); + ImGui::PopStyleColor(2); + if (b_menu_item) callback(); else { // show tooltip @@ -4111,6 +4127,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv imgui.text(buf); }*/ } + ImGui::PopStyleVar(1); /* BBS GUI refactor */ /*if (!visible) @@ -4230,6 +4247,9 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv }; //BBS display Color Scheme + ImGui::Dummy({ window_padding, window_padding }); + ImGui::Dummy({ window_padding, window_padding }); + ImGui::SameLine(); std::wstring btn_name; if (m_fold) btn_name = ImGui::UnfoldButtonIcon + boost::nowide::widen(std::string("")); @@ -4249,8 +4269,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv ImGui::SameLine(); ImGui::Text(_u8L("Color Scheme").c_str()); push_combo_style(); - float combo_width = ImGui::GetContentRegionAvailWidth() - ImGui::CalcTextSize(_u8L("Color Scheme").c_str()).x - button_width - ImGui::GetStyle().FramePadding.x * 4; - ImGui::PushItemWidth(combo_width); + ImGui::SameLine(); const char* view_type_value = view_type_items_str[m_view_type_sel].c_str(); ImGuiComboFlags flags = 0; @@ -4276,11 +4295,13 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv ImGui::EndCombo(); } pop_combo_style(); + ImGui::SameLine(); + ImGui::Dummy({ window_padding, window_padding }); if (m_fold) { imgui.end(); ImGui::PopStyleColor(6); - ImGui::PopStyleVar(); + ImGui::PopStyleVar(2); return; } @@ -4355,6 +4376,8 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv } // extrusion paths section -> title + ImGui::Dummy({ window_padding, window_padding }); + ImGui::SameLine(); switch (m_view_type) { case EViewType::FeatureType: @@ -4467,6 +4490,8 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv case EViewType::Feedrate: { append_range(m_extrusions.ranges.feedrate, 0); ImGui::Spacing(); + ImGui::Dummy({ window_padding, window_padding }); + ImGui::SameLine(); append_headers({_u8L("Options"), "", "", "", _u8L("Display")}, offsets); const bool travel_visible = m_buffers[buffer_id(EMoveType::Travel)].visible; ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 3.0f)); @@ -4962,6 +4987,8 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv } } ImGui::Dummy(ImVec2(0.0f, ImGui::GetFontSize() * 0.1)); + ImGui::Dummy({ window_padding, window_padding }); + ImGui::SameLine(); imgui.title(time_title); std::string filament_str = _u8L("Filament"); std::string prepare_str = _u8L("Prepare time"); @@ -4976,6 +5003,8 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv } //BBS display filament cost + ImGui::Dummy({ window_padding, window_padding }); + ImGui::SameLine(); imgui.text(filament_str + ":"); ImGui::SameLine(max_len); @@ -4997,13 +5026,19 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv }; //BBS: start gcode is prepeare time if (role_time(erCustom) != 0.0f) { + ImGui::Dummy({ window_padding, window_padding }); + ImGui::SameLine(); imgui.text(prepare_str + ":"); ImGui::SameLine(max_len); imgui.text(short_time(get_time_dhms(role_time(erCustom)))); } + ImGui::Dummy({ window_padding, window_padding }); + ImGui::SameLine(); imgui.text(print_str + ":"); ImGui::SameLine(max_len); imgui.text(short_time(get_time_dhms(time_mode.time - role_time(erCustom)))); + ImGui::Dummy({ window_padding, window_padding }); + ImGui::SameLine(); imgui.text(total_str + ":"); ImGui::SameLine(max_len); imgui.text(short_time(get_time_dhms(time_mode.time))); @@ -5035,16 +5070,17 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv } } legend_height = ImGui::GetCurrentWindow()->Size.y; - + ImGui::Dummy({ window_padding, window_padding}); imgui.end(); ImGui::PopStyleColor(6); - ImGui::PopStyleVar(); + ImGui::PopStyleVar(2); } void GCodeViewer::push_combo_style() { ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.0,8.0)); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.0f, 0.0f, 0.0f, 0.3f)); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.0f, 0.0f, 0.0f, 0.3f)); ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0f, 0.0f, 0.0f, 0.3f)); @@ -5056,7 +5092,7 @@ void GCodeViewer::push_combo_style() } void GCodeViewer::pop_combo_style() { - ImGui::PopStyleVar(2); + ImGui::PopStyleVar(3); ImGui::PopStyleColor(8); }