OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::GUI::GCodeViewer::SequentialView::GCodeWindow Class Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/GUI/GCodeViewer.hpp>

Collaboration diagram for Slic3r::GUI::GCodeViewer::SequentialView::GCodeWindow:

Classes

struct  Line

Public Member Functions

 GCodeWindow ()=default
 ~GCodeWindow ()
void load_gcode (const std::string &filename, const std::vector< size_t > &lines_ends)
void reset ()
void render (float top, float bottom, float right, uint64_t curr_line_id) const
void on_change_color_mode (bool is_dark)
void stop_mapping_file ()

Public Attributes

float m_scale = 1.0f

Private Attributes

bool m_is_dark = false
uint64_t m_selected_line_id { 0 }
size_t m_last_lines_size { 0 }
std::string m_filename
boost::iostreams::mapped_file_source m_file
std::vector< size_t > m_lines_ends
std::vector< Line > m_lines

Detailed Description


Class Documentation

◆ Slic3r::GUI::GCodeViewer::SequentialView::GCodeWindow::Line

struct Slic3r::GUI::GCodeViewer::SequentialView::GCodeWindow::Line
Collaboration diagram for Slic3r::GUI::GCodeViewer::SequentialView::GCodeWindow::Line:
Class Members
string command
string comment
string parameters

Constructor & Destructor Documentation

◆ GCodeWindow()

Slic3r::GUI::GCodeViewer::SequentialView::GCodeWindow::GCodeWindow ( )
default

◆ ~GCodeWindow()

Slic3r::GUI::GCodeViewer::SequentialView::GCodeWindow::~GCodeWindow ( )
inline
void stop_mapping_file()
Definition GCodeViewer.cpp:1107

References stop_mapping_file().

Here is the call graph for this function:

Member Function Documentation

◆ load_gcode()

void Slic3r::GUI::GCodeViewer::SequentialView::GCodeWindow::load_gcode ( const std::string & filename,
const std::vector< size_t > & lines_ends )
875{
876 assert(! m_file.is_open());
877 if (m_file.is_open())
878 return;
879
880 m_filename = filename;
881 m_lines_ends = lines_ends;
882
885
886 try
887 {
888 m_file.open(boost::filesystem::path(m_filename));
889 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": mapping file " << m_filename;
890 }
891 catch (...)
892 {
893 BOOST_LOG_TRIVIAL(error) << "Unable to map file " << m_filename << ". Cannot show G-code window.";
894 reset();
895 }
896}
uint64_t m_selected_line_id
Definition GCodeViewer.hpp:141
std::string m_filename
Definition GCodeViewer.hpp:143
size_t m_last_lines_size
Definition GCodeViewer.hpp:142
std::vector< size_t > m_lines_ends
Definition GCodeViewer.hpp:146
void reset()
Definition GCodeViewer.hpp:155
boost::iostreams::mapped_file_source m_file
Definition GCodeViewer.hpp:144

References m_file, m_filename, m_last_lines_size, m_lines_ends, m_selected_line_id, and Slic3r::GUI::GCodeViewer::reset().

Here is the call graph for this function:

◆ on_change_color_mode()

void Slic3r::GUI::GCodeViewer::SequentialView::GCodeWindow::on_change_color_mode ( bool is_dark)
inline
168{ m_is_dark = is_dark; }
static bool is_dark()
Definition TextureImportDialog.cpp:85
bool m_is_dark
Definition GCodeViewer.hpp:140

References is_dark(), and m_is_dark.

Here is the call graph for this function:

◆ render()

void Slic3r::GUI::GCodeViewer::SequentialView::GCodeWindow::render ( float top,
float bottom,
float right,
uint64_t curr_line_id ) const
913{
914 // Orca: truncate long lines(>55 characters), add "..." at the end
915 auto update_lines = [this](uint64_t start_id, uint64_t end_id) {
916 std::vector<Line> ret;
917 ret.reserve(end_id - start_id + 1);
918 // Orca: m_lines_ends indexes into a memory mapping, so it must be clamped to the mapping. If the
919 // file was modified behind our back (an in-place post-processing script that shrank it), an
920 // unchecked read is an access violation, which the caller's try/catch cannot catch on Windows.
921 const size_t file_size = m_file.size();
922 for (uint64_t id = start_id; id <= end_id; ++id) {
923 // read line from file
924 // Keep one entry per id: render() indexes m_lines by (id - start_id).
925 const size_t start = id == 1 ? 0 : std::min(m_lines_ends[id - 2], file_size);
926 const size_t end = std::min(m_lines_ends[id - 1], file_size);
927 const size_t original_len = end > start ? end - start : 0;
928 // A character is four bytes at most, so 55 of them always fit in 220.
929 const size_t len = std::min(original_len, (size_t) 55 * 4);
930 std::string gline(m_file.data() + start, len);
931
932 // If original line is longer than 55 characters, truncate and append "...".
933 // The cut must land on a character boundary or it leaves half a character behind.
934 if (len < original_len || utf8_offset(gline, 55) < gline.size())
935 gline = gline.substr(0, utf8_offset(gline, 52)) + "...";
936
937 std::string command, parameters, comment;
938 const size_t comment_start = gline.find(';');
939 if (comment_start == std::string::npos)
940 command = gline;
941 else {
942 command = gline.substr(0, comment_start);
943 comment = gline.substr(comment_start);
944 }
945
946 // extract gcode command and parameters
947 if (!command.empty()) {
948 std::vector<std::string> tokens;
949 boost::split(tokens, command, boost::is_any_of(" "), boost::token_compress_on);
950 command = tokens.front();
951 if (tokens.size() > 1) {
952 for (size_t i = 1; i < tokens.size(); ++i) {
953 parameters += " " + tokens[i];
954 }
955 }
956 }
957 ret.push_back({command, parameters, comment});
958 }
959 return ret;
960 };
961
962 static const ImVec4 LINE_NUMBER_COLOR = ImGuiWrapper::COL_ORANGE_LIGHT;
963 static const ImVec4 SELECTION_RECT_COLOR = ImGuiWrapper::COL_ORANGE_DARK;
964 static const ImVec4 COMMAND_COLOR = {0.8f, 0.8f, 0.0f, 1.0f};
965 static const ImVec4 PARAMETERS_COLOR = { 1.0f, 1.0f, 1.0f, 1.0f };
966 static const ImVec4 COMMENT_COLOR = { 0.7f, 0.7f, 0.7f, 1.0f };
967
968 if (!wxGetApp().show_gcode_window() || m_filename.empty() || m_lines_ends.empty() || curr_line_id == 0)
969 return;
970
971 // window height
972 const float wnd_height = bottom - top;
973
974 // number of visible lines
975 const float text_height = ImGui::CalcTextSize("0").y;
976 const ImGuiStyle& style = ImGui::GetStyle();
977 const uint64_t lines_count = static_cast<uint64_t>((wnd_height - 2.0f * style.WindowPadding.y + style.ItemSpacing.y) / (text_height + style.ItemSpacing.y));
978
979 if (lines_count == 0)
980 return;
981
982 // visible range
983 const uint64_t half_lines_count = lines_count / 2;
984 uint64_t start_id = (curr_line_id >= half_lines_count) ? curr_line_id - half_lines_count : 0;
985 uint64_t end_id = start_id + lines_count - 1;
986 if (end_id >= static_cast<uint64_t>(m_lines_ends.size())) {
987 end_id = static_cast<uint64_t>(m_lines_ends.size()) - 1;
988 start_id = end_id - lines_count + 1;
989 }
990
991 // updates list of lines to show, if needed
992 if (m_selected_line_id != curr_line_id || m_last_lines_size != end_id - start_id + 1) {
993 try
994 {
995 *const_cast<std::vector<Line>*>(&m_lines) = update_lines(start_id, end_id);
996 }
997 catch (...)
998 {
999 BOOST_LOG_TRIVIAL(error) << "Error while loading from file " << m_filename << ". Cannot show G-code window.";
1000 return;
1001 }
1002 *const_cast<uint64_t*>(&m_selected_line_id) = curr_line_id;
1003 *const_cast<size_t*>(&m_last_lines_size) = m_lines.size();
1004 }
1005
1006 // line number's column width
1007 const float id_width = ImGui::CalcTextSize(std::to_string(end_id).c_str()).x;
1008
1009 float required_width = 0.0f;
1010 { // --- Compute required G-code window width ---
1011 float max_text_width = id_width;
1012 for (const Line& line : m_lines) {
1013 float w = 0.0f;
1014
1015 if (!line.command.empty())
1016 w += ImGui::CalcTextSize(line.command.c_str()).x;
1017
1018 if (!line.parameters.empty())
1019 w += ImGui::CalcTextSize(line.parameters.c_str()).x;
1020
1021 if (!line.comment.empty())
1022 w += ImGui::CalcTextSize(line.comment.c_str()).x;
1023
1024 // spacing between segments
1025 w += 3 * ImGui::GetStyle().ItemSpacing.x;
1026
1027 if (w > max_text_width)
1028 max_text_width = w;
1029 }
1030
1031 required_width = id_width + max_text_width;
1032 }
1033
1034 ImGuiWrapper& imgui = *wxGetApp().imgui();
1035
1036 //BBS: GUI refactor: move to right
1037 imgui.set_next_window_pos(right, top + 6 * m_scale, ImGuiCond_Always, 1.0f, 0.0f); // ORCA add a small gap between legend and code viewer
1038 ImGui::SetNextWindowSize(ImVec2(required_width, wnd_height), ImGuiCond_Always);
1039 ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 8.0f * m_scale); // ORCA add window rounding to modernize / match style
1040 ImGui::SetNextWindowBgAlpha(0.8f);
1041 imgui.begin(std::string("G-code"), ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove);
1042
1043 // center the text in the window by pushing down the first line
1044 const float f_lines_count = static_cast<float>(lines_count);
1045 ImGui::SetCursorPosY(0.5f * (wnd_height - f_lines_count * text_height - (f_lines_count - 1.0f) * style.ItemSpacing.y));
1046
1047 // render text lines
1048 for (uint64_t id = start_id; id <= end_id; ++id) {
1049 const Line& line = m_lines[id - start_id];
1050
1051 // rect around the current selected line
1052 if (id == curr_line_id) {
1053 //BBS: GUI refactor: move to right
1054 const float pos_y = ImGui::GetCursorScreenPos().y;
1055 const float pos_x = ImGui::GetCursorScreenPos().x;
1056 const float half_ItemSpacing_y = 0.5f * style.ItemSpacing.y;
1057 const float half_ItemSpacing_x = 0.5f * style.ItemSpacing.x;
1058 //ImGui::GetWindowDrawList()->AddRect({ half_padding_x, pos_y - half_ItemSpacing_y },
1059 // { ImGui::GetCurrentWindow()->Size.x - half_padding_x, pos_y + text_height + half_ItemSpacing_y },
1060 // ImGui::GetColorU32(SELECTION_RECT_COLOR));
1061 ImGui::GetWindowDrawList()->AddRect({ pos_x - half_ItemSpacing_x, pos_y - half_ItemSpacing_y },
1062 { right - half_ItemSpacing_x, pos_y + text_height + half_ItemSpacing_y },
1063 ImGui::GetColorU32(SELECTION_RECT_COLOR));
1064 }
1065
1066 // render line number
1067 const std::string id_str = std::to_string(id);
1068 // spacer to right align text
1069 ImGui::Dummy({ id_width - ImGui::CalcTextSize(id_str.c_str()).x, text_height });
1070 ImGui::SameLine(0.0f, 0.0f);
1071 ImGui::PushStyleColor(ImGuiCol_Text, LINE_NUMBER_COLOR);
1072 imgui.text(id_str);
1073 ImGui::PopStyleColor();
1074
1075 if (!line.command.empty() || !line.comment.empty())
1076 ImGui::SameLine();
1077
1078 // render command
1079 if (!line.command.empty()) {
1080 ImGui::PushStyleColor(ImGuiCol_Text, COMMAND_COLOR);
1081 imgui.text(line.command);
1082 ImGui::PopStyleColor();
1083 }
1084
1085 // render parameters
1086 if (!line.parameters.empty()) {
1087 ImGui::SameLine(0.0f, 0.0f);
1088 ImGui::PushStyleColor(ImGuiCol_Text, PARAMETERS_COLOR);
1089 imgui.text(line.parameters);
1090 ImGui::PopStyleColor();
1091 }
1092
1093 // render comment
1094 if (!line.comment.empty()) {
1095 if (!line.command.empty())
1096 ImGui::SameLine(0.0f, 0.0f);
1097 ImGui::PushStyleColor(ImGuiCol_Text, COMMENT_COLOR);
1098 imgui.text(line.comment);
1099 ImGui::PopStyleColor();
1100 }
1101 }
1102
1103 imgui.end();
1104 ImGui::PopStyleVar();
1105}
#define style
Definition WipeTowerDialog.cpp:101
float m_scale
Definition GCodeViewer.hpp:151
std::vector< Line > m_lines
Definition GCodeViewer.hpp:148
static const ImVec4 COL_ORANGE_LIGHT
Definition ImGuiWrapper.hpp:387
static const ImVec4 COL_ORANGE_DARK
Definition ImGuiWrapper.hpp:386
T * end(Slic3r::Mat< N, M, T > &mat)
Definition Point.hpp:841
static size_t utf8_offset(const std::string &str, size_t count)
Definition GCodeViewer.cpp:899
@ right
Definition MarchingSquares.hpp:190

References Slic3r::GUI::ImGuiWrapper::begin(), Slic3r::GUI::ImGuiWrapper::COL_ORANGE_DARK, Slic3r::GUI::ImGuiWrapper::COL_ORANGE_LIGHT, Slic3r::GUI::GCodeViewer::SequentialView::GCodeWindow::Line::command, Slic3r::GUI::GCodeViewer::SequentialView::GCodeWindow::Line::comment, Slic3r::GUI::ImGuiWrapper::end(), m_file, m_filename, m_last_lines_size, m_lines, m_lines_ends, m_scale, m_selected_line_id, Slic3r::GUI::GCodeViewer::SequentialView::GCodeWindow::Line::parameters, Slic3r::GUI::ImGuiWrapper::set_next_window_pos(), style, Slic3r::GUI::ImGuiWrapper::text(), and Slic3r::GUI::utf8_offset().

Here is the call graph for this function:

◆ reset()

void Slic3r::GUI::GCodeViewer::SequentialView::GCodeWindow::reset ( )
inline
155 {
157 m_lines_ends.clear();
158 m_lines_ends.shrink_to_fit();
159 m_lines.clear();
160 m_lines.shrink_to_fit();
161 m_filename.clear();
162 m_filename.shrink_to_fit();
163 }

References m_filename, m_lines, m_lines_ends, and stop_mapping_file().

Here is the call graph for this function:

◆ stop_mapping_file()

void Slic3r::GUI::GCodeViewer::SequentialView::GCodeWindow::stop_mapping_file ( )
1108{
1109 //BBS: add log to trace the gcode file issue
1110 if (m_file.is_open()) {
1111 m_file.close();
1112 BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": finished mapping file " << m_filename;
1113 }
1114}

References m_file, and m_filename.

Referenced by ~GCodeWindow(), and reset().

Here is the caller graph for this function:

Member Data Documentation

◆ m_file

boost::iostreams::mapped_file_source Slic3r::GUI::GCodeViewer::SequentialView::GCodeWindow::m_file
private

◆ m_filename

std::string Slic3r::GUI::GCodeViewer::SequentialView::GCodeWindow::m_filename
private

◆ m_is_dark

bool Slic3r::GUI::GCodeViewer::SequentialView::GCodeWindow::m_is_dark = false
private

Referenced by on_change_color_mode().

◆ m_last_lines_size

size_t Slic3r::GUI::GCodeViewer::SequentialView::GCodeWindow::m_last_lines_size { 0 }
private
142{ 0 };

Referenced by load_gcode(), and render().

◆ m_lines

std::vector<Line> Slic3r::GUI::GCodeViewer::SequentialView::GCodeWindow::m_lines
private

Referenced by render(), and reset().

◆ m_lines_ends

std::vector<size_t> Slic3r::GUI::GCodeViewer::SequentialView::GCodeWindow::m_lines_ends
private

Referenced by load_gcode(), render(), and reset().

◆ m_scale

float Slic3r::GUI::GCodeViewer::SequentialView::GCodeWindow::m_scale = 1.0f

Referenced by render().

◆ m_selected_line_id

uint64_t Slic3r::GUI::GCodeViewer::SequentialView::GCodeWindow::m_selected_line_id { 0 }
private
141{ 0 };

Referenced by load_gcode(), and render().


The documentation for this class was generated from the following files: