#include "SliceInfoPanel.hpp" #include "I18N.hpp" #include "Widgets/Label.hpp" #include "libslic3r/Utils.hpp" #include namespace Slic3r { namespace GUI { #define THUMBNAIL_SIZE (wxSize(FromDIP(60), FromDIP(60))) #define ICON_SIZE (wxSize(FromDIP(16), FromDIP(16))) #define PRINT_ICON_SIZE (wxSize(FromDIP(18), FromDIP(18))) wxIMPLEMENT_CLASS(SliceInfoPopup, PopupWindow); wxBEGIN_EVENT_TABLE(SliceInfoPopup, PopupWindow) EVT_MOUSE_EVENTS( SliceInfoPopup::OnMouse ) EVT_SIZE(SliceInfoPopup::OnSize) EVT_SET_FOCUS( SliceInfoPopup::OnSetFocus ) EVT_KILL_FOCUS( SliceInfoPopup::OnKillFocus ) wxEND_EVENT_TABLE() static wxColour BUTTON_BORDER_COL = wxColour(255, 255, 255); inline int hex_digit_to_int(const char c) { return (c >= '0' && c <= '9') ? int(c - '0') : (c >= 'A' && c <= 'F') ? int(c - 'A') + 10 : (c >= 'a' && c <= 'f') ? int(c - 'a') + 10 : -1; } inline float calc_gray(wxColour color) { return 0.299 * (float) color.Red() + 0.587 * (float) color.Green() + 0.114 * (float) color.Blue(); } static wxColour decode_color(const std::string &color) { std::array ret = {0, 0, 0}; const char * c = color.data() + 1; if (color.size() == 7 && color.front() == '#') { for (size_t j = 0; j < 3; ++j) { int digit1 = hex_digit_to_int(*c++); int digit2 = hex_digit_to_int(*c++); if (digit1 == -1 || digit2 == -1) break; ret[j] = float(digit1 * 16 + digit2); } } return wxColour(ret[0], ret[1], ret[2]); } SliceInfoPopup::SliceInfoPopup(wxWindow *parent, wxBitmap bmp, BBLSliceInfo *info) : PopupWindow(parent, wxBORDER_NONE | wxPU_CONTAINS_CONTROLS) { #ifdef __WINDOWS__ SetDoubleBuffered(true); #endif m_panel = new wxScrolledWindow(this, wxID_ANY); m_panel->SetBackgroundColour(*wxWHITE); m_panel->Bind(wxEVT_MOTION, &SliceInfoPopup::OnMouse, this); wxBoxSizer * main_sizer = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer * topSizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer * caption_sizer = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer * caption_left_sizer = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer * caption_right_sizer = new wxBoxSizer(wxHORIZONTAL); auto prediction_bitmap = new wxStaticBitmap(m_panel, wxID_ANY, create_scaled_bitmap("monitor_item_prediction", nullptr, 16)); wxString predict_text; if (info) predict_text = get_bbl_monitor_time_dhm(info->prediction); auto prediction = new wxStaticText(m_panel, wxID_ANY, predict_text, wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END); caption_left_sizer->Add(prediction_bitmap, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5)); caption_left_sizer->Add(prediction, 1, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5)); prediction->Wrap(-1); auto cost_bitmap = new wxStaticBitmap(m_panel, wxID_ANY, create_scaled_bitmap("monitor_item_cost", nullptr, 16)); wxString cost_text; if (info) { if (info->weight > 0) { cost_text = wxString::Format("%.2fg", info->weight); } else { cost_text = "0g"; } } auto used_g_text = new wxStaticText(m_panel, wxID_ANY, cost_text, wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END); caption_right_sizer->Add(cost_bitmap, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5)); caption_right_sizer->Add(used_g_text, 1, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5)); caption_sizer->Add(caption_left_sizer, 1, 0, FromDIP(5)); caption_sizer->Add(caption_right_sizer, 1, 0, FromDIP(5)); topSizer->Add(caption_sizer, 0, wxEXPAND | wxALL, 0); auto static_line = new StaticLine(m_panel); topSizer->Add(static_line, 0, wxEXPAND | wxALL, 0); wxGridSizer *grid_sizer = new wxGridSizer(2, wxSize(FromDIP(10), 0)); if (info) { for (auto f : info->filaments_info) { auto f_sizer = new wxBoxSizer(wxHORIZONTAL); auto f_type = new Button(m_panel, f.type); f_type->SetBorderColor(BUTTON_BORDER_COL); wxColour color = decode_color(f.color); f_type->SetBackgroundColor(color); auto textcolor = wxColour(0, 0, 0); if (calc_gray(color) <= 128) textcolor = wxColour(255, 255, 255); else textcolor = wxColour(0, 0, 0); f_type->SetTextColor(textcolor); f_type->SetSize(wxSize(FromDIP(40), FromDIP(20))); f_type->SetMinSize(wxSize(FromDIP(40), FromDIP(20))); f_type->SetMaxSize(wxSize(FromDIP(40), FromDIP(20))); f_type->SetCornerRadius(FromDIP(10)); wxString used_g_text = wxString::Format("%.1fg", f.used_g); auto f_used_g = new wxStaticText(m_panel, wxID_ANY, used_g_text, wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END); f_used_g->Wrap(-1); f_used_g->SetSize(wxSize(FromDIP(60), -1)); f_sizer->Add(f_type, 0, wxEXPAND | wxALL, FromDIP(5)); f_sizer->Add(f_used_g, 0, wxEXPAND | wxALL, FromDIP(5)); grid_sizer->Add(f_sizer, 0, wxEXPAND, 0); f_type->Bind(wxEVT_LEFT_DOWN, [this](auto &e) {}); } } topSizer->Add(grid_sizer, 0, wxALL, FromDIP(5)); main_sizer->Add(FromDIP(13), 0, 0, 0); main_sizer->Add(topSizer, 0, wxEXPAND | wxALL, 0); main_sizer->Add(FromDIP(13), 0, 0, 0); main_sizer->SetMinSize(wxSize(FromDIP(200), -1)); m_panel->SetSizer(main_sizer); m_panel->Layout(); main_sizer->Fit(m_panel); SetClientSize(m_panel->GetSize()); } void SliceInfoPopup::Popup(wxWindow *WXUNUSED(focus)) { PopupWindow::Popup(); } void SliceInfoPopup::OnDismiss() { PopupWindow::OnDismiss(); } bool SliceInfoPopup::ProcessLeftDown(wxMouseEvent &event) { return PopupWindow::ProcessLeftDown(event); } bool SliceInfoPopup::Show(bool show) { return PopupWindow::Show(show); } void SliceInfoPopup::OnSize(wxSizeEvent &event) { event.Skip(); } void SliceInfoPopup::OnSetFocus(wxFocusEvent &event) { event.Skip(); } void SliceInfoPopup::OnKillFocus(wxFocusEvent &event) { event.Skip(); } void SliceInfoPopup::OnMouse(wxMouseEvent &event) { event.Skip(); } SliceInfoPanel::SliceInfoPanel(wxWindow *parent, wxBitmap &prediction, wxBitmap &cost, wxBitmap &print, wxWindowID id, const wxPoint &pos, const wxSize &size, long style, const wxString &name) : wxPanel(parent, id, pos, size, style, name) { this->SetBackgroundColour(*wxWHITE); m_item_top_sizer = new wxBoxSizer(wxHORIZONTAL); m_bmp_item_thumbnail = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW | 0); m_bmp_item_thumbnail->SetMinSize(THUMBNAIL_SIZE); m_bmp_item_thumbnail->SetSize(THUMBNAIL_SIZE); m_item_top_sizer->Add(m_bmp_item_thumbnail, 0, wxALL, 0); wxBoxSizer *m_item_content_sizer; m_item_content_sizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *m_item_info_sizer = new wxBoxSizer(wxHORIZONTAL); m_bmp_item_prediction = new wxStaticBitmap(this, wxID_ANY, prediction); m_bmp_item_prediction->SetMinSize(ICON_SIZE); m_bmp_item_prediction->SetSize(ICON_SIZE); m_item_info_sizer->Add(m_bmp_item_prediction, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5)); m_text_item_prediction = new wxStaticText(this, wxID_ANY, "", wxDefaultPosition, wxSize(FromDIP(60), -1)); m_text_item_prediction->Wrap(-1); m_item_info_sizer->Add(m_text_item_prediction, 1, wxALIGN_CENTER_VERTICAL | wxALL, 0); m_bmp_item_cost = new wxStaticBitmap(this, wxID_ANY, cost); m_bmp_item_cost->SetMinSize(ICON_SIZE); m_bmp_item_cost->SetSize(ICON_SIZE); m_item_info_sizer->Add(m_bmp_item_cost, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5)); m_text_item_cost = new wxStaticText(this, wxID_ANY, "", wxDefaultPosition, wxSize(FromDIP(35), -1)); m_text_item_cost->Wrap(-1); m_item_info_sizer->Add(m_text_item_cost, 1, wxALIGN_CENTER_VERTICAL | wxALL, 0); m_item_content_sizer->Add(m_item_info_sizer, 0, wxEXPAND, 0); wxGridSizer *m_filament_info_sizer = new wxGridSizer(0, 3, 0, 8); m_item_content_sizer->Add(m_filament_info_sizer, 0, wxEXPAND, 0); m_item_top_sizer->Add(m_item_content_sizer, 0, wxEXPAND, 0); wxBoxSizer *m_item_right_sizer; m_item_right_sizer = new wxBoxSizer(wxVERTICAL); m_bmp_item_print = new wxStaticBitmap(this, wxID_ANY, print, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW | 0); m_bmp_item_print->SetMinSize(PRINT_ICON_SIZE); m_bmp_item_print->SetSize(PRINT_ICON_SIZE); m_item_right_sizer->Add(m_bmp_item_print, 0, wxALL, FromDIP(5)); m_item_right_sizer->Add(0, 0, 1, wxEXPAND, FromDIP(5)); m_text_plate_index = new wxStaticText(this, wxID_ANY, ""); m_text_plate_index->Wrap(-1); m_text_plate_index->SetForegroundColour(wxColour(107, 107, 107)); m_item_right_sizer->Add(m_text_plate_index, 0, wxALIGN_RIGHT | wxALL, FromDIP(5)); m_item_top_sizer->Add(m_item_right_sizer, 0, wxEXPAND, 0); this->SetSizer(m_item_top_sizer); this->Layout(); Bind(wxEVT_WEBREQUEST_STATE, &SliceInfoPanel::on_webrequest_state, this); // Connect Events m_bmp_item_thumbnail->Connect(wxEVT_ENTER_WINDOW, wxMouseEventHandler(SliceInfoPanel::on_thumbnail_enter), NULL, this); m_bmp_item_thumbnail->Connect(wxEVT_LEAVE_WINDOW, wxMouseEventHandler(SliceInfoPanel::on_thumbnail_leave), NULL, this); m_bmp_item_print->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(SliceInfoPanel::on_subtask_print), NULL, this); } SliceInfoPanel::~SliceInfoPanel() { // Disconnect Events m_bmp_item_thumbnail->Disconnect(wxEVT_ENTER_WINDOW, wxMouseEventHandler(SliceInfoPanel::on_thumbnail_enter), NULL, this); m_bmp_item_thumbnail->Disconnect(wxEVT_LEAVE_WINDOW, wxMouseEventHandler(SliceInfoPanel::on_thumbnail_leave), NULL, this); m_bmp_item_print->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(SliceInfoPanel::on_subtask_print), NULL, this); } void SliceInfoPanel::SetImages(wxBitmap &prediction, wxBitmap &cost, wxBitmap &printing) { m_bmp_item_prediction->SetBitmap(prediction); m_bmp_item_cost->SetBitmap(cost); m_bmp_item_print->SetBitmap(printing); } void SliceInfoPanel::on_subtask_print(wxCommandEvent &evt) { ; } void SliceInfoPanel::on_thumbnail_enter(wxMouseEvent &event) { /* m_slice_info_popup = std::make_shared(this); wxWindow *ctrl = (wxWindow *) event.GetEventObject(); wxPoint pos = ctrl->ClientToScreen(wxPoint(0, 0)); wxSize sz = ctrl->GetSize(); m_slice_info_popup->Position(pos, sz); m_slice_info_popup->Popup(); */ } void SliceInfoPanel::on_thumbnail_leave(wxMouseEvent &event) { if (m_thumbnail_popup) { m_thumbnail_popup->Hide(); } } void SliceInfoPanel::on_mouse_enter(wxMouseEvent &event) { ; } void SliceInfoPanel::on_mouse_leave(wxMouseEvent &event) { ; } void SliceInfoPanel::on_webrequest_state(wxWebRequestEvent &evt) { BOOST_LOG_TRIVIAL(trace) << "monitor: sub_task_panel web request state = " << evt.GetState(); switch (evt.GetState()) { case wxWebRequest::State_Completed: { m_thumbnail_img = *evt.GetResponse().GetStream(); wxImage resize_img = m_thumbnail_img.Scale(m_bmp_item_thumbnail->GetSize().x, m_bmp_item_thumbnail->GetSize().y); m_bmp_item_thumbnail->SetBitmap(resize_img); break; } case wxWebRequest::State_Failed: { break; } case wxWebRequest::State_Cancelled: case wxWebRequest::State_Unauthorized: case wxWebRequest::State_Active: case wxWebRequest::State_Idle: break; default: break; } } void SliceInfoPanel::update(BBLSliceInfo *info) { wxString prediction = wxString::Format("%s", get_bbl_time_dhms(info->prediction)); m_text_item_prediction->SetLabelText(prediction); wxString weight = wxString::Format("%.2fg", info->weight); m_text_item_cost->SetLabelText(weight); m_text_plate_index->SetLabelText(info->index); if (web_request.IsOk()) web_request.Cancel(); if (!info->thumbnail_url.empty()) { web_request = wxWebSession::GetDefault().CreateRequest(this, info->thumbnail_url); BOOST_LOG_TRIVIAL(trace) << "slice info: start reqeust thumbnail, url = " << info->thumbnail_url; web_request.Start(); } this->Layout(); } void SliceInfoPanel::msw_rescale() { m_bmp_item_prediction->SetMinSize(ICON_SIZE); m_bmp_item_prediction->SetSize(ICON_SIZE); m_bmp_item_cost->SetMinSize(ICON_SIZE); m_bmp_item_cost->SetSize(ICON_SIZE); m_bmp_item_print->SetMinSize(PRINT_ICON_SIZE); m_bmp_item_print->SetSize(PRINT_ICON_SIZE); this->Layout(); } } }