G-code window optimization: parse g-code lines only when needed

This commit is contained in:
enricoturri1966 2021-03-04 13:23:24 +01:00
parent a820e8c22f
commit cee4ed9ff2
2 changed files with 64 additions and 33 deletions

View file

@ -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();
}
}

View file

@ -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;