diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 6d5986690..3cbf3262f 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -314,6 +314,8 @@ void GCodeViewer::SequentialView::GCodeWindow::load_gcode() } m_file_size = static_cast<unsigned int>(m_gcode.size()); + m_last_line_id = 0; + m_last_lines_size = 0; } void GCodeViewer::SequentialView::GCodeWindow::start_mapping_file() @@ -328,6 +330,38 @@ void GCodeViewer::SequentialView::GCodeWindow::stop_mapping_file() void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, unsigned int curr_line_id) const { + auto update_lines = [this](unsigned int start_id, unsigned int end_id) { + std::vector<Line> ret; + ret.reserve(end_id - start_id + 1); + for (unsigned int id = start_id; id <= end_id; ++id) { + const std::string& gline = m_gcode[id - 1]; + + std::string command; + std::string parameters; + std::string comment; + + // extract comment + std::vector<std::string> tokens; + boost::split(tokens, gline, boost::is_any_of(";"), boost::token_compress_on); + command = tokens.front(); + if (tokens.size() > 1) + comment = ";" + tokens.back(); + + // extract gcode command and parameters + if (!command.empty()) { + boost::split(tokens, command, boost::is_any_of(" "), boost::token_compress_on); + command = tokens.front(); + if (tokens.size() > 1) { + for (size_t i = 1; i < tokens.size(); ++i) { + parameters += " " + tokens[i]; + } + } + } + ret.push_back({ command, parameters, comment }); + } + return ret; + }; + static const ImVec4 LINE_NUMBER_COLOR = ImGuiWrapper::COL_ORANGE_LIGHT; static const ImVec4 HIGHLIGHT_RECT_COLOR = ImGuiWrapper::COL_ORANGE_DARK; static const ImVec4 COMMAND_COLOR = { 0.8f, 0.8f, 0.0f, 1.0f }; @@ -340,12 +374,13 @@ void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, u const float text_height = ImGui::CalcTextSize("0").y; const ImGuiStyle& style = ImGui::GetStyle(); const float wnd_height = bottom - top; - if (wnd_height < 2.0f * (text_height + style.ItemSpacing.y + style.WindowPadding.y)) - return; // number of visible lines const unsigned int lines_count = (wnd_height - 2.0f * style.WindowPadding.y + style.ItemSpacing.y) / (text_height + style.ItemSpacing.y); + if (lines_count == 0) + return; + // visible range const unsigned int half_lines_count = lines_count / 2; unsigned int start_id = (curr_line_id >= half_lines_count) ? curr_line_id - half_lines_count : 0; @@ -355,6 +390,13 @@ void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, u start_id = end_id - lines_count + 1; } + if (m_last_line_id != curr_line_id || m_last_lines_size != static_cast<size_t>(end_id - start_id + 1)) { + // updates list of lines to show + *const_cast<std::vector<Line>*>(&m_lines) = update_lines(start_id, end_id); + *const_cast<unsigned int*>(&m_last_line_id) = curr_line_id; + *const_cast<size_t*>(&m_last_lines_size) = m_lines.size(); + } + // line id number column width const float id_width = ImGui::CalcTextSize(std::to_string(end_id).c_str()).x; @@ -368,33 +410,13 @@ void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, u ImDrawList* draw_list = ImGui::GetWindowDrawList(); + // center the text in the window by pushing down the first line const float f_lines_count = static_cast<float>(lines_count); ImGui::SetCursorPosY({ 0.5f * (wnd_height - f_lines_count * text_height - (f_lines_count - 1.0f) * style.ItemSpacing.y) }); + // render text lines for (unsigned int id = start_id; id <= end_id; ++id) { - const std::string& line = m_gcode[id - 1]; - - std::string command; - std::string parameters; - std::string comment; - - // extract comment - std::vector<std::string> tokens; - boost::split(tokens, line, boost::is_any_of(";"), boost::token_compress_on); - command = tokens.front(); - if (tokens.size() > 1) - comment = ";" + tokens.back(); - - // extract gcode command and parameters - if (!command.empty()) { - boost::split(tokens, command, boost::is_any_of(" "), boost::token_compress_on); - command = tokens.front(); - if (tokens.size() > 1) { - for (size_t i = 1; i < tokens.size(); ++i) { - parameters += " " + tokens[i]; - } - } - } + const Line& line = m_lines[id - start_id]; // rect for the current selected move if (id == curr_line_id) { @@ -414,28 +436,28 @@ void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, u imgui.text(id_str); ImGui::PopStyleColor(); - if (!command.empty() || !comment.empty()) + if (!line.command.empty() || !line.comment.empty()) ImGui::SameLine(); // render command - if (!command.empty()) { + if (!line.command.empty()) { ImGui::PushStyleColor(ImGuiCol_Text, COMMAND_COLOR); - imgui.text(command); + imgui.text(line.command); ImGui::PopStyleColor(); } // render command parameters - if (!parameters.empty()) { + if (!line.parameters.empty()) { ImGui::SameLine(0.0f, 0.0f); - imgui.text(parameters); + imgui.text(line.parameters); } // render comment - if (!comment.empty()) { - if (!command.empty()) + if (!line.comment.empty()) { + if (!line.command.empty()) ImGui::SameLine(0.0f, 0.0f); ImGui::PushStyleColor(ImGuiCol_Text, COMMENT_COLOR); - imgui.text(comment); + imgui.text(line.comment); ImGui::PopStyleColor(); } } diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index ada377d36..428a50e85 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -609,8 +609,17 @@ public: #if ENABLE_GCODE_WINDOW class GCodeWindow { + struct Line + { + std::string command; + std::string parameters; + std::string comment; + }; bool m_visible{ true }; unsigned int m_file_size{ 0 }; + unsigned int m_last_line_id{ 0 }; + size_t m_last_lines_size{ 0 }; + std::vector<Line> m_lines; std::string m_filename; std::vector<std::string> m_gcode;