Files
OrcaSlicer/src/slic3r/GUI/StatusPanel.cpp
T
a5413efc37 refactor: printer agent infrastructure changes to work with other printer agents aside from bambu (#15710)
* Add developer flag for printer agents

* Parse user print info on the UI thread to prevent heap corruption (#119)

get_user_print_info()'s HTTP fetch can run on a worker thread (e.g. BindJob),
but parse_user_print_info() mutates userMachineList (insert/erase/delete
MachineObject). on_machine_alive (SSDP) mutates the same maps on the UI thread
without locking, so parsing off-thread races the map and frees MachineObjects
out from under it -> heap corruption.

Keep all device-list mutation on the UI thread: parse inline when already on
the main thread, otherwise marshal via CallAfter so it stays serialized with
on_machine_alive.

* Prevent loss of user access code on LAN reselect

Keep user access code intact to maintain access rights even if
device slot is unpopulated, ensuring continuous connection
and status message reception.

* Harden send flow and separate upload failure recovery (#111)

* fix(send): harden FT send path + IP pre-flight UX

* Remove early returns

* Working Moonraker and Qidi printer agent transport (#104)

Folds the Qidi AMS box-mapping print
overrides (apply_box_mapping +
start_* wrappers) that the transport
fix builds on.

* Add support for runtime error status in plugins

Distinguish a loaded plugin whose
capability errored (RuntimeError,
warn-styled, stays checked) from a
load-time Error. Status now derives
via resolve_plugin_status(); enum
ordinal keeps dialog sort priority.
Unloading clears stale errors.

* Resolve duplicate agent ID conflicts

Reject a printer-agent capability
whose agent ID is already owned by
another capability or built-in:
flag the plugin error, disable the
capability, and warn the user
instead of silently ignoring it.

* fix: checkbox should depend on plugin is_loaded status

* Replace fake-enum printer agent dropdown (#121)

A dedicated PrinterAgentChoice field
reads rows straight from the live
agent registry and stores the agent
id string, replacing the fake-coEnum
index mapping. The field moves to
TabPrinter and registers with the
searcher so UnsavedChanges renders
it; the PhysicalPrinterDialog copy
and its update hook are removed
(#125). switch_printer_agent now
resolves ids via
resolve_printer_agent_id.

* Reset device selection on agent swap or unload (#124)

set_live_printer_agent centralizes
the swap: deselect the machine,
clear stale sidebar state and the
previous agent's Other Devices, then
install the new agent (or null when
its provider vanished). Plugin
load/unload callbacks refresh the
dropdown and re-run agent selection.
load_last_machine no longer falls
back to the first available machine.

* Gate agent mode behind use_printer_agents toggle

Replace per-printer auto-activation
(is_current_printer_agent_plugin)
with a global experimental AppConfig
toggle, default off: legacy
print-host behavior is unchanged
until the user opts in. The toggle
drives device-tab routing, print
button defaults, connect-button
visibility and sidebar layout, and
dedups machine-select dialog opens.

* Track BBLPrinterAgentPlugin.py

* Add printer-agent and plugin status tests

Ports the agent lifecycle, duplicate
agent-id, built-in-id clash and
status-resolution tests. The loader
runs on a detached worker thread, so
the lifecycle tests live in their own
executable. Tests install the
production unload-side registry
wiring themselves (no GUI in the
test binary) and register agents
manually so concurrent loads stay
deterministic.

* fix: pin HTTP to prevent connection refusal

Set `use_ssl` to false to ensure Moonraker
connectivity, as the service uses HTTP rather
than HTTPS, preventing connection issues. Initialize
device info early for reliable name resolution.

* Bring Moonraker device panel to feature parity

The monitor panel showed wrong or missing
data for Moonraker printers, and its
controls did nothing.

Push payload now carries layer number and
total layers. Remaining time replaces the
wrong total_duration - print_duration
formula. The chamber light toggle maps to
Klipper SET_PIN / SET_LED, and pause,
resume and stop post to
/printer/print/{action}. Task thumbnails
resolve via /server/files/thumbnails onto
a new MachineObject thumbnail url.

Filament sync switches to pull mode so the
agent is queried on demand.

Not compiled or run.

* Stop blocking print on unreported nozzle data

* fix: make Klipper macro lamp control reliable

* Surface Moonraker webcams and gate unrunnable controls

* Keep Bambu AMS dialect out of the agent waist

M620 is Bambu firmware dialect, not a
neutral command. Composing it in
MachineObject let non-Bambu agents
(Moonraker/Klipper) forward it and
report success on firmware that
cannot run it.

Agents now own the dialect: the
default refusal on IPrinterAgent
returns not-supported so the UI
can say so; BBLPrinterAgent keeps
the byte-identical composition.

* Fix multi-color filament logic

Reuse color decoding across functions to improve
code readability and maintain consistency in
multi-color filament handling.

* Move Moonraker commands off the UI thread

Pause/resume/stop, g-code sends, temps, and
light ran synchronous HTTP on the UI thread,
freezing the app up to 10s per click on slow
or unreachable printers.

Run them on a single agent-owned FIFO worker
so g-code ordering is preserved, while command
translation stays synchronous so unsupported-
command dialogs still work.

Add a pending-disabled state to the pause,
resume, and abort buttons for Moonraker-family
printers: the icon only flips once the
WebSocket reports the real state, which also
rules out double-click races.

* Show Snapmaker U1 camera in Device tab

The U1 exposes no /server/webcams/list entry;
its camera only captures after an explicit
camera.start_monitor RPC, which the Moonraker
websocket executes unauthenticated but only
answers over MQTT - so the call is fire and
forget.

Start the camera when the camera view is
shown and renew every 300 s: the printer
retires the capture task at ~362 s and
stop_monitor is accepted but ineffective,
so teardown is simply to stop renewing.

Frames land in monitor.jpg as still JPEGs
(~2 fps at interval 0), so the webview loads
a local HTML wrapper that repolls with a
cache buster.

* fix: start stream when camera URL changes

* fix: stop Qidi slot parse throwing on null

* Keep printer-agent progress in sync

Keep the shared task progress aligned with agent
reports that lack Bambu cloud task identity.

Release the lazily allocated task during reset to
avoid leaks when machine objects reconnect.

* docs: document the printer-agent subsystem

* fix: merge access codes into one

* Reconcile implementation split with PR tip

* feat: abstract remaining gcode commands in devicemanager

* refactor: abstract bambu specific protocol to printer agent

* refactor: push bbl workflows to bbl printer agent

* remove unused

* fix: default impl

* fix callback error

* fix: remove redundant cache

* specify api for getting file transfer url

* revert file transfer abstraction

* fix: ams filament mapping workflow

* feat: update qidi to use subscription based filament sync mode

* fix: resolve stubgen byte header conflict

* fix: ams sync info and periodic ams sync via subscription workflow

* fix: skip filament sync dialog if filamentSyncMode is none

* feat: parse nozzle information for qidi and moonraker printer agents

* fix: extend access code requirements t 0, 8 or more characters.

* remove irrelevant docs

* fix: remove heavy includes from IPrinterAgent

* fix: defer filesystem and camera abstractions

* fix: remote do_fetch_filament_info from tests

* cleanup moonraker and snapmaker printer agents

* fix: access codes regression

* fix: tests

* fix: printer agent switching on preset change

* fix: remove unused variable

* fix: snapmaker U1 SelectMachineDialog blocking print

* fix: merge artifact

* fix: clear up some unrelated changes

* feat: connect to cloud printer and monitor

* feat: connect to cloud printer and monitor

* feat: generic camera stream support for http snapshot and rtsp

* fix: build & access code UI

* feat: generic camera stream support for http snapshot and rtsp

* fix: build & access code UI

* feat: connect to cloud printer and monitor

* feat: connect to cloud printer and monitor

* fix: build errors

* feat: camera via webrtc

* fix: build

* fix: cmake

* feat: remove frame assembler and change config to set protocol

* fix: orcaprinteragent refactor

* fix: LAN paths and camera stream

* feat: use ffmpeg to render http camera stream

* fix: make model_id/dev_type optional instead of blocking

* fix: connect via ip dialog

* feat: LAN impl for Orca Printer Agent

* fix: model_id resolution method for non bambu printers

* fix: ffmpeg http camera stream jittering due to incomplete frames

* fix: revert sdcard check

* feat: check printer storage status before sending

* fix: moonraker printer agent hang on printer power cut

* fix: shim layer for any compatibiliity changes

* fix: cloud printers were using the wrong MQTT endpoint

* feat: cloud download via HTTP

* temp: doc for intended change

* fix: warnings

* fix: warnings

* fix: camera auto-play on startup

* fix: split infra from impl

* fix: uninitialized ams state blocking print

* Fixes nullptr deref

* Log first before std::move

* fix: printer agent virutal optional functions

* fix: parameterize orcaslicer_copy_test_dlls() for printer_agent_plugin_tests

* Revert "fix: parameterize orcaslicer_copy_test_dlls() for printer_agent_plugin_tests"

This reverts commit 2f566e3779.

* Guard libdatachannel. Remove unused code

* fix: unit tests & unused variables

* fix(ci): deps build order for datachannel

* Resolve printer agent first before getting cloud printer agent

* fix(ci): set depends openssl

* fix: re-include apply header guarded by ifdef __APPLE__

* fix(ci): add libdatachannel to flatpak manifest

* fix: add internal_developer_mode chekc back to MediaPlayCtrl::load()

* fix: invoke js clearInterval on WebMediaController::stop

* fix: change rtc log level

* fix: inject provider, agent id and generation to get_user_print_info to ensure correct metadata

* fix: revert moonraker specific behavior

* fix: remove stale comment

* fix: use ORCA_CLOUD_PROVIDER instead of hardcoded string

* fix: remove hardcoded ICE servers

* feat: enable https camera stream mode

* fix: move non-mandatory printer agent function stubs to IPrinterAgent

* fix: dedupe compatible printer type check

* fix: stop the correct media controller

* fix: scope get_my_machine_list to printers listed under the current printer agent

* fix: move printer agent plugin tests into test_plugin_lifecycle.cpp

* fix: always build bundled DataChannel dep

* fix: disable unused DataChannel media support

* revert: filament sync work

* fix: wrap command_* with small wrapper

* fix: regression bug, connecting to bambu needs bblp username

* fix: default impl for vendor agnostic gcode commansd

* refactor: media controller playback routing and ownership

* fix: bump libdatachannel ver & update flatpak to use tar instead

* fix: stop flatpak DataChannel build from re-cloning over the sandboxed network

* fix: update windows ffmpeg prebuild

* fix: update printer agent plugin API

* fix: shift camera signaling channel to network agent

* fix: follow external-packages for flatpak libdatachannel deps & add flatpak path to use source_dir

* feat: add printer-agent.md doc to HLSD

* fix: guard DeviceManager command dispatch when no printer agent is bound

* fix: port BBL implementations from #15711

* refactor: connect_printer api and dialog

* fix(tests): make omitted printer agent operations answer like a missing agent

* fix: preserve printer agent defaults in PrinterAgentPluginCapabilityTrampoline

* test: cover printer agent default command dispatch

* fix: validate windows FFmpeg avformat library

* feat: extend optional printer model warnings to calibration & ams workflows

* fix: handle malformed printer progress values safely

* fix: clear webview document on stop

* chore: reduce diagnostic logging level to trace

* refactor: centralize printer compatibility checks

* tests: add device manager integration coverage

* tests: cover WebMediaController lifecycle with wxWebView stub

* fix: make integration tests headless

* refactor: collapse command_ams_refresh_rfid and command_ams_refresh_rfid2

* refactor: make printer connection SSL agent-specific

* fix: persist input printer host and port

* fix: use correct device id for Moonraker connections

* fix: make moonraker gcode commands asynchronous

* fix: preserve moonraker device names

* fix: add include for non BBL_RELEASE_TO_PUBLIC path in BBLPrinterAgent

---------

Co-authored-by: Andrew <159703254+andrewsoonqn@users.noreply.github.com>
Co-authored-by: SoftFever <softfeverever@gmail.com>
Co-authored-by: Lam Wei Lun <weilun.lam@gmail.com>
2026-10-01 00:30:44 +08:00

6226 lines
262 KiB
C++

#include "StatusPanel.hpp"
#include "I18N.hpp"
#include "Widgets/Label.hpp"
#include "Widgets/Button.hpp"
#include "Widgets/StepCtrl.hpp"
#include "Widgets/SideTools.hpp"
#include "Widgets/WebView.hpp"
#include "BitmapCache.hpp"
#include "GUI_App.hpp"
#include "MainFrame.hpp"
#include "MsgDialog.hpp"
#include "slic3r/Utils/Http.hpp"
#include "libslic3r/Thread.hpp"
#include "DeviceErrorDialog.hpp"
#include "RecenterDialog.hpp"
#include "CalibUtils.hpp"
#include <slic3r/GUI/Widgets/ProgressDialog.hpp>
#include <wx/display.h>
#include <wx/mstream.h>
#include <wx/sstream.h>
#include <wx/zstream.h>
#include <chrono>
#include "DeviceCore/DevBed.h"
#include "DeviceCore/DevCtrl.h"
#include "DeviceCore/DevFan.h"
#include "DeviceCore/DevFilaSystem.h"
#include "DeviceCore/DevLamp.h"
#include "DeviceCore/DevStorage.h"
#include "DeviceCore/DevConfig.h"
#include "DeviceCore/DevManager.h"
#include "DeviceCore/DevPrintTaskInfo.h"
#include "DeviceTab/wgtDeviceNozzleRack.h"
#include "PrintOptionsDialog.hpp"
#include "SafetyOptionsDialog.hpp"
#include "ThermalPreconditioningDialog.hpp"
namespace Slic3r { namespace GUI {
#define TEMP_THRESHOLD_VAL 2
#define TEMP_THRESHOLD_ALLOW_E_CTRL 170.0f
/* const strings */
static const wxString NA_STR = _L("N/A");
static const wxString TEMP_BLANK_STR = wxString("_");
static const wxFont SWITCH_FONT = Label::Body_10;
/* const values */
static const int bed_temp_range[2] = {20, 120};
static const int default_champer_temp_min = 20;
static const int default_champer_temp_max = 60;
/* colors */
static const wxColour STATUS_PANEL_BG = wxColour(238, 238, 238);
static const wxColour STATUS_TITLE_BG = wxColour(248, 248, 248);
static const wxColour STATIC_BOX_LINE_COL = wxColour(238, 238, 238);
static const wxColour BUTTON_NORMAL1_COL = wxColour(238, 238, 238);
static const wxColour BUTTON_NORMAL2_COL = wxColour(206, 206, 206);
static const wxColour BUTTON_PRESS_COL = wxColour(172, 172, 172);
static const wxColour BUTTON_HOVER_COL = wxColour(0, 150, 136);
static const wxColour DISCONNECT_TEXT_COL = wxColour(171, 172, 172);
static const wxColour NORMAL_TEXT_COL = wxColour(48,58,60);
static const wxColour NORMAL_FAN_TEXT_COL = wxColour(107, 107, 107);
static const wxColour WARNING_INFO_BG_COL = wxColour(255, 111, 0);
static const wxColour STAGE_TEXT_COL = wxColour(0, 150, 136);
static const wxColour GROUP_STATIC_LINE_COL = wxColour(206, 206, 206);
/* font and foreground colors */
static const wxFont PAGE_TITLE_FONT = Label::Body_14;
//static const wxFont GROUP_TITLE_FONT = Label::sysFont(17);
static wxColour PAGE_TITLE_FONT_COL = wxColour(107, 107, 107);
static wxColour GROUP_TITLE_FONT_COL = wxColour(172, 172, 172);
static wxColour TEXT_LIGHT_FONT_COL = wxColour(107, 107, 107);
static wxImage fail_image;
/* size */
#define PAGE_TITLE_HEIGHT FromDIP(36)
#define PAGE_TITLE_TEXT_WIDTH FromDIP(200)
#define PAGE_TITLE_LEFT_MARGIN FromDIP(17)
#define GROUP_TITLE_LEFT_MARGIN FromDIP(15)
#define GROUP_TITLE_LINE_MARGIN FromDIP(11)
#define GROUP_TITLE_RIGHT_MARGIN FromDIP(15)
#define NORMAL_SPACING FromDIP(5)
#define PAGE_SPACING FromDIP(10)
#define PAGE_MIN_WIDTH FromDIP(574)
#define PROGRESSBAR_HEIGHT FromDIP(8)
#define SWITCH_BUTTON_SIZE (wxSize(FromDIP(40), -1))
#define TASK_THUMBNAIL_SIZE (wxSize(FromDIP(120), FromDIP(120)))
#define TASK_BUTTON_SIZE (wxSize(FromDIP(48), FromDIP(24)))
#define TASK_BUTTON_SIZE2 (wxSize(-1, FromDIP(24)))
#define Z_BUTTON_SIZE (wxSize(FromDIP(44), FromDIP(40)))
#define MISC_BUTTON_PANEL_SIZE (wxSize(FromDIP(136), FromDIP(55)))
#define MISC_BUTTON_1FAN_SIZE (wxSize(FromDIP(132), FromDIP(51)))
#define MISC_BUTTON_2FAN_SIZE (wxSize(FromDIP(66), FromDIP(51)))
#define MISC_BUTTON_3FAN_SIZE (wxSize(FromDIP(44), FromDIP(51)))
#define TEMP_CTRL_MIN_SIZE_ALIGN_ONE_ICON (wxSize(FromDIP(125), FromDIP(52)))
#define TEMP_CTRL_MIN_SIZE_ALIGN_TWO_ICON (wxSize(FromDIP(145), FromDIP(48)))
#define AXIS_MIN_SIZE (wxSize(FromDIP(258), FromDIP(258)))
#define EXTRUDER_IMAGE_SIZE (wxSize(FromDIP(48), FromDIP(76)))
static void market_model_scoring_page(int design_id)
{
std::string url;
std::string country_code = GUI::wxGetApp().app_config->get_country_code();
std::string model_http_url = GUI::wxGetApp().get_model_http_url(country_code);
if (GUI::wxGetApp().getAgent()->get_model_mall_detail_url(&url, std::to_string(design_id)) == 0) {
std::string user_id = GUI::wxGetApp().getAgent()->get_user_id();
boost::algorithm::replace_first(url, "models", "u/" + user_id + "/rating");
// Prevent user_id from containing design_id
size_t sign_in = url.find("/rating");
std::string sub_url = url.substr(0, sign_in + 7);
url.erase(0, sign_in + 7);
boost::algorithm::replace_first(url, std::to_string(design_id), "");
url = sub_url + url;
try {
if (!url.empty()) { wxLaunchDefaultBrowser(url); }
} catch (...) {
return;
}
}
}
/*************************************************
Description:Extruder
**************************************************/
ExtruderImage::ExtruderImage(wxWindow* parent, wxWindowID id, int nozzle_num, const wxPoint& pos, const wxSize& size)
{
wxWindow::Create(parent, id, pos, wxSize(FromDIP(45), FromDIP(112)));
SetBackgroundColour(*wxWHITE);
m_nozzle_num = nozzle_num;
SetSize(wxSize(FromDIP(45), FromDIP(112)));
SetMinSize(wxSize(FromDIP(45), FromDIP(112)));
SetMaxSize(wxSize(FromDIP(45), FromDIP(112)));
m_pipe_filled_load = new ScalableBitmap(this, "pipe_of_loading_selected", 50);
m_pipe_filled_unload = new ScalableBitmap(this, "pipe_of_unloading_selected", 50);
m_pipe_empty_load = new ScalableBitmap(this, "pipe_of_empty", 50);
m_pipe_empty_unload = new ScalableBitmap(this, "pipe_of_empty", 50);
m_pipe_filled_load_unselected = new ScalableBitmap(this, "pipe_of_loading_unselected", 50);
m_pipe_filled_unload_unselected = new ScalableBitmap(this, "pipe_of_unloading_unselected", 50);
m_pipe_empty_load_unselected = new ScalableBitmap(this, "pipe_of_empty", 50);
m_pipe_empty_unload_unselected = new ScalableBitmap(this, "pipe_of_empty", 50);
m_left_extruder_active_filled = new ScalableBitmap(this, "left_extruder_active_filled", 62);
m_left_extruder_active_empty = new ScalableBitmap(this, "left_extruder_active_empty", 62);
m_left_extruder_unactive_filled = new ScalableBitmap(this, "left_extruder_unactive_filled", 62);
m_left_extruder_unactive_empty = new ScalableBitmap(this, "left_extruder_unactive_empty", 62);
m_right_extruder_active_filled = new ScalableBitmap(this, "right_extruder_active_filled", 62);
m_right_extruder_active_empty = new ScalableBitmap(this, "right_extruder_active_empty", 62);
m_right_extruder_unactive_filled = new ScalableBitmap(this, "right_extruder_unactive_filled", 62);
m_right_extruder_unactive_empty = new ScalableBitmap(this, "right_extruder_unactive_empty", 62);
m_extruder_single_nozzle_empty_load = new ScalableBitmap(this, "monitor_extruder_empty_load", 106);
m_extruder_single_nozzle_empty_unload = new ScalableBitmap(this, "monitor_extruder_empty_unload", 106);
m_extruder_single_nozzle_filled_load = new ScalableBitmap(this, "monitor_extruder_filled_load", 106);
m_extruder_single_nozzle_filled_unload = new ScalableBitmap(this, "monitor_extruder_filled_unload", 106);
Bind(wxEVT_PAINT, &ExtruderImage::paintEvent, this);
}
ExtruderImage::~ExtruderImage() {}
void ExtruderImage::msw_rescale()
{
//m_ams_extruder.SetSize(AMS_EXTRUDER_BITMAP_SIZE);
//auto image = m_ams_extruder.ConvertToImage();
//m_extruder_pipe = ScalableBitmap(this, "pipe_of_extruder_control", 50);
m_pipe_filled_load->msw_rescale();
m_pipe_filled_unload->msw_rescale();
m_pipe_empty_load->msw_rescale();
m_pipe_empty_unload->msw_rescale();
m_pipe_filled_load_unselected->msw_rescale();
m_pipe_filled_unload_unselected->msw_rescale();
m_pipe_empty_load_unselected->msw_rescale();
m_pipe_empty_unload_unselected->msw_rescale();
m_left_extruder_active_filled->msw_rescale();
m_left_extruder_active_empty->msw_rescale();
m_left_extruder_unactive_filled->msw_rescale();
m_left_extruder_unactive_empty->msw_rescale();
m_right_extruder_active_filled->msw_rescale();
m_right_extruder_active_empty->msw_rescale();
m_right_extruder_unactive_filled->msw_rescale();
m_right_extruder_unactive_empty->msw_rescale();
m_extruder_single_nozzle_empty_load->msw_rescale();
m_extruder_single_nozzle_empty_unload->msw_rescale();
m_extruder_single_nozzle_filled_load->msw_rescale();
m_extruder_single_nozzle_filled_unload->msw_rescale();
Layout();
Refresh();
}
void ExtruderImage::setExtruderCount(int nozzle_num)
{
m_nozzle_num = nozzle_num;
}
void ExtruderImage::setExtruderUsed(std::string loc)
{
//current_nozzle_idx = nozzle_id;
if (current_nozzle_loc == loc)
{
return;
}
current_nozzle_loc = loc;
Refresh();
}
void ExtruderImage::update(ExtruderState single_state)
{
m_single_ext_state = single_state;
}
void ExtruderImage::update(ExtruderState right_state, ExtruderState left_state) {
m_left_ext_state = left_state;
m_right_ext_state = right_state;
}
void ExtruderImage::paintEvent(wxPaintEvent& evt)
{
wxPaintDC dc(this);
render(dc);
}
void ExtruderImage::render(wxDC& dc)
{
#ifdef __WXMSW__
wxSize size = GetSize();
wxMemoryDC memdc;
wxBitmap bmp(size.x, size.y);
memdc.SelectObject(bmp);
memdc.Blit({ 0, 0 }, size, &dc, { 0, 0 });
{
wxGCDC dc2(memdc);
doRender(dc2);
}
memdc.SelectObject(wxNullBitmap);
dc.DrawBitmap(bmp, 0, 0);
#else
doRender(dc);
#endif
}
void ExtruderImage::doRender(wxDC& dc)
{
auto size = GetSize();
//dc.DrawRectangle(0, FromDIP(5), size.x, size.y - FromDIP(5) - FromDIP(2));
auto pot = wxPoint(size.x / 2, (size.y - m_pipe_filled_load->GetBmpSize().y - m_left_extruder_active_filled->GetBmpSize().y) / 2);
if (m_nozzle_num >= 2){
ScalableBitmap* left_nozzle_bmp;
ScalableBitmap* right_nozzle_bmp;
ScalableBitmap* left_pipe_bmp;
ScalableBitmap* right_pipe_bmp;
switch (m_right_ext_state)
{
case Slic3r::GUI::FILLED_LOAD:
right_pipe_bmp = current_nozzle_loc == "right" ? m_pipe_filled_load : m_pipe_filled_load_unselected;
right_nozzle_bmp = current_nozzle_loc == "right" ? m_right_extruder_active_filled : m_right_extruder_unactive_filled;
break;
case Slic3r::GUI::FILLED_UNLOAD:
right_pipe_bmp = current_nozzle_loc == "right" ? m_pipe_filled_unload : m_pipe_filled_unload_unselected;
right_nozzle_bmp = current_nozzle_loc == "right" ? m_right_extruder_active_filled : m_right_extruder_unactive_filled;
break;
case Slic3r::GUI::EMPTY_LOAD:
right_pipe_bmp = current_nozzle_loc == "right" ? m_pipe_empty_load : m_pipe_empty_load_unselected;
right_nozzle_bmp = current_nozzle_loc == "right" ? m_right_extruder_active_empty : m_right_extruder_unactive_empty;
break;
case Slic3r::GUI::EMPTY_UNLOAD:
right_pipe_bmp = current_nozzle_loc == "right" ? m_pipe_empty_unload : m_pipe_empty_unload_unselected;
right_nozzle_bmp = current_nozzle_loc == "right" ? m_right_extruder_active_empty : m_right_extruder_unactive_empty;
break;
default:
break;
}
switch (m_left_ext_state)
{
case Slic3r::GUI::FILLED_LOAD:
left_pipe_bmp = current_nozzle_loc == "left" ? m_pipe_filled_load : m_pipe_filled_load_unselected;
left_nozzle_bmp = current_nozzle_loc == "left" ? m_left_extruder_active_filled : m_left_extruder_unactive_filled;
break;
case Slic3r::GUI::FILLED_UNLOAD:
left_pipe_bmp = current_nozzle_loc == "left" ? m_pipe_filled_unload : m_pipe_filled_unload_unselected;
left_nozzle_bmp = current_nozzle_loc == "left" ? m_left_extruder_active_filled : m_left_extruder_unactive_filled;
break;
case Slic3r::GUI::EMPTY_LOAD:
left_pipe_bmp = current_nozzle_loc == "left" ? m_pipe_empty_load : m_pipe_empty_load_unselected;
left_nozzle_bmp = current_nozzle_loc == "left" ? m_left_extruder_active_empty : m_left_extruder_unactive_empty;
break;
case Slic3r::GUI::EMPTY_UNLOAD:
left_pipe_bmp = current_nozzle_loc == "left" ? m_pipe_empty_unload : m_pipe_empty_unload_unselected;
left_nozzle_bmp = current_nozzle_loc == "left" ? m_left_extruder_active_empty : m_left_extruder_unactive_empty;
break;
default:
break;
}
left_pipe_bmp = m_pipe_filled_load;
right_pipe_bmp = m_pipe_filled_load;
dc.DrawBitmap(left_pipe_bmp->bmp(), pot.x - left_nozzle_bmp->GetBmpWidth() / 2 - left_pipe_bmp->GetBmpWidth() / 2 + left_pipe_bmp->GetBmpWidth() / 5, pot.y);
dc.DrawBitmap(left_nozzle_bmp->bmp(), pot.x - left_nozzle_bmp->GetBmpWidth(), pot.y + left_pipe_bmp->GetBmpSize().y);
dc.DrawBitmap(right_pipe_bmp->bmp(), pot.x + right_nozzle_bmp->GetBmpWidth() / 2 - right_pipe_bmp->GetBmpWidth() / 2 - right_pipe_bmp->GetBmpWidth() / 5, pot.y);
dc.DrawBitmap(right_nozzle_bmp->bmp(), pot.x, pot.y + right_pipe_bmp->GetBmpSize().y);
}
else{
ScalableBitmap* nozzle_bmp = nullptr;
switch (m_single_ext_state)
{
case Slic3r::GUI::FILLED_LOAD: nozzle_bmp = m_extruder_single_nozzle_filled_load; break;
case Slic3r::GUI::FILLED_UNLOAD: nozzle_bmp = m_extruder_single_nozzle_filled_unload; break;
case Slic3r::GUI::EMPTY_LOAD: nozzle_bmp = m_extruder_single_nozzle_empty_load; break;
case Slic3r::GUI::EMPTY_UNLOAD: nozzle_bmp = m_extruder_single_nozzle_empty_unload; break;
default: break;
}
if (nozzle_bmp)
{
dc.DrawBitmap(nozzle_bmp->bmp(), pot.x - nozzle_bmp->GetBmpWidth() / 2, (size.y - nozzle_bmp->GetBmpHeight()) / 2);
}
}
}
#define SWITCHING_STATUS_BTN_SIZE wxSize(FromDIP(25), FromDIP(26))
ExtruderSwithingStatus::ExtruderSwithingStatus(wxWindow *parent)
: wxPanel(parent)
{
m_switching_status_label = new Label(this);
m_switching_status_label->SetFont(::Label::Body_13);
if (parent)
{ m_switching_status_label->SetBackgroundColour(parent->GetBackgroundColour());
}
m_button_quit = new Button(this, _L_CONTEXT(L_CONTEXT("Quit", "Quit_Switching"), "Quit_Switching"), "", 0, FromDIP(22));
m_button_quit->SetStyle(ButtonStyle::Regular, ButtonType::Window);
m_button_quit->Bind(wxEVT_BUTTON, &ExtruderSwithingStatus::on_quit, this);
m_button_retry = new Button(this, _L("Retry"), "", 0, FromDIP(22));
m_button_retry->SetStyle(ButtonStyle::Confirm, ButtonType::Window);
m_button_retry->Bind(wxEVT_BUTTON, &ExtruderSwithingStatus::on_retry, this);
wxBoxSizer *btn_sizer = new wxBoxSizer(wxHORIZONTAL);
btn_sizer->Add(m_button_quit, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(10));
btn_sizer->Add(m_button_retry, 0, wxALIGN_CENTER_VERTICAL, 0);
wxBoxSizer *main_sizer = new wxBoxSizer(wxVERTICAL);
main_sizer->Add(m_switching_status_label, 0, wxALIGN_CENTER_HORIZONTAL | wxTOP, FromDIP(10));
main_sizer->Add(btn_sizer, 0, wxALIGN_CENTER_HORIZONTAL | wxTOP, FromDIP(10));
SetSizer(main_sizer);
Layout();
}
void ExtruderSwithingStatus::updateBy(MachineObject *obj)
{
m_obj = obj;
if (!m_obj)
{
Show(false);
}
else
{
/*do not display while command sended in a mean while*/
if ((time(nullptr) - m_last_ctrl_time) > HOLD_TIME_6SEC)
{
updateBy(obj->GetExtderSystem());
}
}
}
void ExtruderSwithingStatus::updateBy(const DevExtderSystem* ext_system)
{
Show(ext_system->GetTotalExtderCount() > 1);
if (!IsShown()) { return; }
auto state = ext_system->GetSwitchState();
{
if (state == DevExtderSwitchState::ES_SWITCHING)
{
m_switching_status_label->SetLabel(_L("Switching..."));
m_switching_status_label->SetForegroundColour(StateColor::darkModeColorFor("#262E30"));
m_switching_status_label->Show(true);
}
else if (state == DevExtderSwitchState::ES_SWITCHING_FAILED)
{
m_switching_status_label->SetLabel(_L("Switching failed"));
m_switching_status_label->SetForegroundColour(StateColor::darkModeColorFor(*wxRED));
m_switching_status_label->Show(true);
}
else
{
m_switching_status_label->Show(false);
}
}
if (state != DevExtderSwitchState::ES_SWITCHING_FAILED)
{
showQuitBtn(false);
showRetryBtn(false);
return;
}
/*can not quit if it's printing*/
if (m_obj && !m_obj->is_in_printing() && !m_obj->is_in_printing_pause())
{
showQuitBtn(true);
}
showRetryBtn(true);
}
void ExtruderSwithingStatus::showQuitBtn(bool show)
{
if (m_button_quit->IsShown() != show)
{
m_button_quit->Show(show);
Layout();
}
}
void ExtruderSwithingStatus::showRetryBtn(bool show)
{
if (m_button_retry->IsShown() != show) {
m_button_retry->Show(show);
Layout();
}
}
bool ExtruderSwithingStatus::has_content_shown() const
{
if (!IsShown()) { return false; }
if (!m_switching_status_label->IsShown() && !m_button_quit->IsShown() && !m_button_retry->IsShown()) { return false; }
return true;
}
void ExtruderSwithingStatus::msw_rescale()
{
m_button_quit->Rescale(); // ORCA
m_button_retry->Rescale(); // ORCA
Layout();
}
void ExtruderSwithingStatus::on_quit(wxCommandEvent &event)
{
Show(false);
if (m_obj)
{
m_obj->command_ams_control("abort");
m_last_ctrl_time = time(nullptr);
}
}
void ExtruderSwithingStatus::on_retry(wxCommandEvent &event)
{
Show(false);
if (m_obj)
{
m_obj->command_ams_control("resume");
m_last_ctrl_time = time(nullptr);
}
}
PrintingTaskPanel::PrintingTaskPanel(wxWindow* parent, PrintingTaskType type)
: wxPanel(parent, wxID_ANY,wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL)
{
m_type = type;
m_question_button = nullptr;
create_panel(this);
SetBackgroundColour(*wxWHITE);
m_bitmap_background = ScalableBitmap(this, "thumbnail_grid", m_bitmap_thumbnail->GetSize().y);
m_bitmap_thumbnail->Bind(wxEVT_PAINT, &PrintingTaskPanel::paint, this);
}
PrintingTaskPanel::~PrintingTaskPanel()
{
if (m_question_button) {
delete m_question_button;
m_question_button = nullptr;
}
}
void PrintingTaskPanel::create_panel(wxWindow* parent)
{
wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *bSizer_printing_title = new wxBoxSizer(wxHORIZONTAL);
m_panel_printing_title = new wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(-1, PAGE_TITLE_HEIGHT), wxTAB_TRAVERSAL);
m_panel_printing_title->SetBackgroundColour(STATUS_TITLE_BG);
m_staticText_printing = new wxStaticText(m_panel_printing_title, wxID_ANY ,_L("Printing progress"));
m_staticText_printing->Wrap(-1);
//m_staticText_printing->SetFont(PAGE_TITLE_FONT);
m_staticText_printing->SetForegroundColour(PAGE_TITLE_FONT_COL);
bSizer_printing_title->Add(m_staticText_printing, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, PAGE_TITLE_LEFT_MARGIN);
bSizer_printing_title->Add(0, 0, 1, wxEXPAND, 0);
m_panel_printing_title->SetSizer(bSizer_printing_title);
m_panel_printing_title->Layout();
bSizer_printing_title->Fit(m_panel_printing_title);
m_bitmap_thumbnail = new wxStaticBitmap(parent, wxID_ANY, m_thumbnail_placeholder.bmp(), wxDefaultPosition, TASK_THUMBNAIL_SIZE, 0);
m_bitmap_thumbnail->SetMaxSize(TASK_THUMBNAIL_SIZE);
m_bitmap_thumbnail->SetMinSize(TASK_THUMBNAIL_SIZE);
wxBoxSizer *bSizer_subtask_info = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *bSizer_task_name = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *bSizer_task_name_hor = new wxBoxSizer(wxHORIZONTAL);
wxPanel* task_name_panel = new wxPanel(parent);
task_name_panel->SetBackgroundColour(*wxWHITE);
m_staticText_subtask_value = new wxStaticText(task_name_panel, wxID_ANY, _L("N/A"), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT | wxST_ELLIPSIZE_END);
m_staticText_subtask_value->SetMaxSize(wxSize(FromDIP(600), -1));
m_staticText_subtask_value->Wrap(-1);
#ifdef __WXOSX_MAC__
m_staticText_subtask_value->SetFont(::Label::Body_13);
#else
m_staticText_subtask_value->SetFont(wxFont(13, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxT("HarmonyOS Sans SC")));
#endif
m_staticText_subtask_value->SetForegroundColour(wxColour(44, 44, 46));
m_bitmap_static_use_time = new wxStaticBitmap(task_name_panel, wxID_ANY, m_bitmap_use_time.bmp(), wxDefaultPosition, wxSize(FromDIP(16), FromDIP(16)));
m_staticText_consumption_of_time = new wxStaticText(task_name_panel, wxID_ANY, "0m", wxDefaultPosition, wxDefaultSize, 0);
m_staticText_consumption_of_time->SetFont(::Label::Body_12);
m_staticText_consumption_of_time->SetForegroundColour(wxColour(0x68, 0x68, 0x68));
m_staticText_consumption_of_time->Wrap(-1);
m_bitmap_static_use_weight = new wxStaticBitmap(task_name_panel, wxID_ANY, m_bitmap_use_weight.bmp(), wxDefaultPosition, wxSize(FromDIP(16), FromDIP(16)));
m_staticText_consumption_of_weight = new wxStaticText(task_name_panel, wxID_ANY, "0g", wxDefaultPosition, wxDefaultSize, 0);
m_staticText_consumption_of_weight->SetFont(::Label::Body_12);
m_staticText_consumption_of_weight->SetForegroundColour(wxColour(0x68, 0x68, 0x68));
m_staticText_consumption_of_weight->Wrap(-1);
bSizer_task_name_hor->Add(m_staticText_subtask_value, 1, wxALL | wxEXPAND, 0);
bSizer_task_name_hor->Add(m_bitmap_static_use_time, 0, wxALIGN_CENTER_VERTICAL, 0);
bSizer_task_name_hor->Add(m_staticText_consumption_of_time, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, FromDIP(3));
bSizer_task_name_hor->Add(0, 0, 0, wxLEFT, FromDIP(10));
bSizer_task_name_hor->Add(m_bitmap_static_use_weight, 0, wxALIGN_CENTER_VERTICAL, 0);
bSizer_task_name_hor->Add(m_staticText_consumption_of_weight, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(3));
bSizer_task_name_hor->Add(0, 0, 0, wxRIGHT, FromDIP(10));
task_name_panel->SetSizer(bSizer_task_name_hor);
task_name_panel->Layout();
task_name_panel->Fit();
bSizer_task_name->Add(task_name_panel, 0, wxEXPAND, FromDIP(5));
m_staticText_profile_value = new wxStaticText(parent, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT | wxST_ELLIPSIZE_END);
m_staticText_profile_value->Wrap(-1);
#ifdef __WXOSX_MAC__
m_staticText_profile_value->SetFont(::Label::Body_11);
#else
m_staticText_profile_value->SetFont(wxFont(11, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxT("HarmonyOS Sans SC")));
#endif
m_staticText_profile_value->SetForegroundColour(0x6B6B6B);
auto progress_lr_panel = new wxPanel(parent, wxID_ANY);
progress_lr_panel->SetBackgroundColour(*wxWHITE);
m_gauge_progress = new ProgressBar(progress_lr_panel, wxID_ANY, 100, wxDefaultPosition, wxDefaultSize);
m_gauge_progress->SetValue(0);
m_gauge_progress->SetHeight(PROGRESSBAR_HEIGHT);
wxBoxSizer *bSizer_task_btn = new wxBoxSizer(wxHORIZONTAL);
bSizer_task_btn->Add(FromDIP(10), 0, 0);
StateColor white_bg(std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Disabled), std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Pressed),
std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Hovered), std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Enabled),
std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Normal));
m_button_partskip = new Button(progress_lr_panel, wxEmptyString, "print_control_partskip_disable", 0, 16, wxID_ANY); // ORCA match icon size
m_button_partskip->Enable(false);
m_button_partskip->Hide();
m_button_partskip->SetBackgroundColor(white_bg);
m_button_partskip->SetIcon("print_control_partskip_disable");
m_button_partskip->SetBorderColor(*wxWHITE);
m_button_partskip->SetFont(Label::Body_12);
m_button_partskip->SetCornerRadius(0);
m_button_partskip->SetToolTip(_L("Parts Skip"));
m_button_partskip->Bind(wxEVT_ENTER_WINDOW, [this](auto &e) { m_button_partskip->SetIcon("print_control_partskip_hover"); });
m_button_partskip->Bind(wxEVT_LEAVE_WINDOW, [this](auto &e) { m_button_partskip->SetIcon("print_control_partskip"); });
m_button_pause_resume = new ScalableButton(progress_lr_panel, wxID_ANY, "print_control_pause", wxEmptyString, wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER,true);
m_button_pause_resume->Bind(wxEVT_ENTER_WINDOW, [this](auto &e) {
if (m_button_pause_resume->GetToolTipText() == _L("Pause")) {
m_button_pause_resume->SetBitmap_("print_control_pause_hover");
}
if (m_button_pause_resume->GetToolTipText() == _L("Resume")) {
m_button_pause_resume->SetBitmap_("print_control_resume_hover");
}
});
m_button_pause_resume->Bind(wxEVT_LEAVE_WINDOW, [this](auto &e) {
auto buf = m_button_pause_resume->GetClientData();
if (m_button_pause_resume->GetToolTipText() == _L("Pause")) {
m_button_pause_resume->SetBitmap_("print_control_pause");
}
if (m_button_pause_resume->GetToolTipText() == _L("Resume")) {
m_button_pause_resume->SetBitmap_("print_control_resume");
}
});
m_button_abort = new ScalableButton(progress_lr_panel, wxID_ANY, "print_control_stop", wxEmptyString, wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER, true);
m_button_abort->SetToolTip(_L("Stop"));
m_button_abort->Bind(wxEVT_ENTER_WINDOW, [this](auto &e) {
m_button_abort->SetBitmap_("print_control_stop_hover");
});
m_button_abort->Bind(wxEVT_LEAVE_WINDOW, [this](auto &e) {
m_button_abort->SetBitmap_("print_control_stop"); }
);
wxBoxSizer *bSizer_buttons = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer *bSizer_text = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer *bSizer_finish_time = new wxBoxSizer(wxHORIZONTAL);
wxPanel* penel_text = new wxPanel(progress_lr_panel);
wxPanel* penel_finish_time = new wxPanel(progress_lr_panel);
penel_text->SetBackgroundColour(*wxWHITE);
penel_finish_time->SetBackgroundColour(*wxWHITE);
wxBoxSizer *sizer_percent = new wxBoxSizer(wxVERTICAL);
sizer_percent->Add(0, 0, 1, wxEXPAND, 0);
wxBoxSizer *sizer_percent_icon = new wxBoxSizer(wxVERTICAL);
sizer_percent_icon->Add(0, 0, 1, wxEXPAND, 0);
m_staticText_progress_percent = new wxStaticText(penel_text, wxID_ANY, "0", wxDefaultPosition, wxDefaultSize, 0);
m_staticText_progress_percent->SetFont(::Label::Head_18);
m_staticText_progress_percent->SetMaxSize(wxSize(-1, FromDIP(20)));
m_staticText_progress_percent->SetForegroundColour(wxColour(0, 150, 136));
m_staticText_progress_percent_icon = new wxStaticText(penel_text, wxID_ANY, "%", wxDefaultPosition, wxDefaultSize, 0);
m_staticText_progress_percent_icon->SetFont(::Label::Body_11);
m_staticText_progress_percent_icon->SetMaxSize(wxSize(-1, FromDIP(13)));
m_staticText_progress_percent_icon->SetForegroundColour(wxColour(0, 150, 136));
sizer_percent->Add(m_staticText_progress_percent, 0, 0, 0);
#ifdef __WXOSX_MAC__
sizer_percent_icon->Add(m_staticText_progress_percent_icon, 0, wxBOTTOM, FromDIP(2));
#else
sizer_percent_icon->Add(m_staticText_progress_percent_icon, 0, 0, 0);
#endif
m_staticText_progress_left = new wxStaticText(penel_text, wxID_ANY, _L("N/A"), wxDefaultPosition, wxDefaultSize, 0);
m_staticText_progress_left->Wrap(-1);
m_staticText_progress_left->SetFont(wxFont(12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxT("HarmonyOS Sans SC")));
m_staticText_progress_left->SetForegroundColour(wxColour(146, 146, 146));
m_staticText_layers = new wxStaticText(penel_text, wxID_ANY, _L("Layer: N/A"));
m_staticText_layers->SetFont(wxFont(12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxT("HarmonyOS Sans SC")));
m_staticText_layers->SetForegroundColour(wxColour(146, 146, 146));
m_staticText_layers->Hide();
bSizer_text->Add(sizer_percent, 0, wxEXPAND, 0);
bSizer_text->Add(sizer_percent_icon, 0, wxEXPAND, 0);
bSizer_text->Add(0, 0, 1, wxEXPAND, 0);
bSizer_text->Add(m_staticText_layers, 0, wxALIGN_CENTER_VERTICAL | wxALL, 0);
bSizer_text->Add(0, 0, 0, wxLEFT, FromDIP(20));
bSizer_text->Add(m_staticText_progress_left, 0, wxALIGN_CENTER_VERTICAL | wxALL, 0);
m_printing_stage_panel = new wxPanel(penel_finish_time);
m_printing_stage_panel->SetBackgroundColour(*wxWHITE);
wxBoxSizer *printingstage_vertical_sizer = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *printingstage_horizontal_sizer = new wxBoxSizer(wxHORIZONTAL);
m_printing_stage_underline = new wxPanel(m_printing_stage_panel);
m_printing_stage_underline->SetMaxSize(wxSize(-1, FromDIP(1)));
m_printing_stage_underline->SetMinSize(wxSize(-1, FromDIP(1)));
m_printing_stage_underline->SetBackgroundColour(wxColour(146, 146, 146));
m_printing_stage_underline->Hide();
m_printing_stage_value = new wxStaticText(m_printing_stage_panel, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT | wxST_ELLIPSIZE_END);
m_printing_stage_value->Wrap(-1);
m_printing_stage_value->SetMaxSize(wxSize(FromDIP(800), -1));
#ifdef __WXOSX_MAC__
m_printing_stage_value->SetFont(::Label::Body_11);
#else
m_printing_stage_value->SetFont(wxFont(11, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxT("HarmonyOS Sans SC")));
#endif
m_printing_stage_value->SetForegroundColour(STAGE_TEXT_COL);
m_printing_stage_value->Bind(wxEVT_LEFT_UP, &PrintingTaskPanel::on_stage_clicked, this);
m_printing_stage_value->Bind(wxEVT_ENTER_WINDOW, [this](wxMouseEvent &event) {
auto *dev_manager = wxGetApp().getDeviceManager();
MachineObject *obj = dev_manager ? dev_manager->get_selected_machine() : nullptr;
if (obj && obj->stage_curr == 58) {
m_printing_stage_value->SetCursor(wxCursor(wxCURSOR_HAND));
m_printing_stage_underline->Show();
} else {
m_printing_stage_value->SetCursor(wxCursor(wxCURSOR_ARROW));
m_printing_stage_underline->Hide();
}
m_printing_stage_panel->Layout();
Layout();
event.Skip();
});
m_printing_stage_value->Bind(wxEVT_LEAVE_WINDOW, [this](wxMouseEvent &event) {
auto *dev_manager = wxGetApp().getDeviceManager();
MachineObject *obj = dev_manager ? dev_manager->get_selected_machine() : nullptr;
if (obj && obj->stage_curr == 58) {
m_printing_stage_value->SetCursor(wxCURSOR_ARROW);
m_printing_stage_underline->Hide();
}
m_printing_stage_panel->Layout();
Layout();
event.Skip();
});
// penel_text->SetMaxSize(wxSize(FromDIP(600), -1));
penel_text->SetSizer(bSizer_text);
penel_text->Layout();
// Create question button
m_question_button = new ScalableButton(m_printing_stage_panel, wxID_ANY, "thermal_question", wxEmptyString, wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER, true);
m_question_button->SetToolTip(_L("Click to view thermal preconditioning explanation"));
m_question_button->SetBackgroundColour(wxColour(255, 255, 255));
m_question_button->Hide(); // Hide by default
m_question_button->Bind(wxEVT_LEFT_UP, &PrintingTaskPanel::on_stage_clicked, this);
m_question_button->Bind(wxEVT_ENTER_WINDOW, [this](wxMouseEvent &event) {
auto *dev_manager = wxGetApp().getDeviceManager();
MachineObject *obj = dev_manager ? dev_manager->get_selected_machine() : nullptr;
if (obj && obj->stage_curr == 58) {
m_question_button->SetCursor(wxCursor(wxCURSOR_HAND));
m_printing_stage_underline->Show();
}
event.Skip();
});
m_question_button->Bind(wxEVT_LEAVE_WINDOW, [this](wxMouseEvent &event) {
auto *dev_manager = wxGetApp().getDeviceManager();
MachineObject *obj = dev_manager ? dev_manager->get_selected_machine() : nullptr;
if (obj && obj->stage_curr == 58) {
m_question_button->SetCursor(wxCURSOR_ARROW);
m_printing_stage_underline->Hide();
event.Skip();
}
});
printingstage_horizontal_sizer->Add(m_printing_stage_value, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, 0);
printingstage_horizontal_sizer->Add(m_question_button, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(5));
printingstage_vertical_sizer->Add(printingstage_horizontal_sizer, 0, wxALIGN_CENTER_VERTICAL, 0);
printingstage_vertical_sizer->Add(m_printing_stage_underline, 0, wxEXPAND, 0);
m_printing_stage_panel->SetSizer(printingstage_vertical_sizer);
// Orca: display the end time of the print
m_staticText_progress_end = new wxStaticText(penel_finish_time, wxID_ANY, _L("N/A"), wxDefaultPosition, wxDefaultSize, 0);
m_staticText_progress_end->Wrap(-1);
m_staticText_progress_end->SetFont(
wxFont(12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxT("HarmonyOS Sans SC")));
m_staticText_progress_end->SetForegroundColour(wxColour(146, 146, 146));
bSizer_finish_time->Add(m_printing_stage_panel, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, 0);
bSizer_finish_time->Add(0, 0, 1, wxEXPAND, 0);
bSizer_finish_time->Add(m_staticText_progress_end, 0, wxLEFT | wxEXPAND, 0);
// penel_finish_time->SetMaxSize(wxSize(FromDIP(600), -1));
penel_finish_time->SetSizer(bSizer_finish_time);
penel_finish_time->Layout();
auto progress_lr_sizer = new wxBoxSizer(wxHORIZONTAL);
auto progress_left_sizer = new wxBoxSizer(wxVERTICAL);
auto progress_right_sizer = new wxBoxSizer(wxHORIZONTAL);
progress_left_sizer->Add(penel_text, 0, wxEXPAND | wxALL, 0);
progress_left_sizer->Add(m_gauge_progress, 0, wxEXPAND | wxTOP | wxBOTTOM, FromDIP(10));
progress_left_sizer->Add(penel_finish_time, 0, wxEXPAND |wxALL, 0);
// progress_left_sizer->SetMaxSize(wxSize(FromDIP(600), -1));
progress_right_sizer->Add(0, 0, 0, wxEXPAND | wxLEFT, FromDIP(18));
progress_right_sizer->Add(m_button_partskip, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(0));//5
progress_right_sizer->Add(0, 0, 0, wxEXPAND | wxLEFT, FromDIP(18));
progress_right_sizer->Add(m_button_pause_resume, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(0));
progress_right_sizer->Add(0, 0, 0, wxEXPAND | wxLEFT, FromDIP(18));
progress_right_sizer->Add(m_button_abort, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(0));
progress_right_sizer->Add(0, 0, 0, wxEXPAND | wxLEFT, FromDIP(18));
progress_lr_sizer->Add(progress_left_sizer, 1, wxEXPAND | wxALL, 0);
progress_lr_sizer->Add(progress_right_sizer, 0, wxEXPAND | wxALL , 0);
progress_lr_panel->SetSizer(progress_lr_sizer);
progress_lr_panel->SetMaxSize(wxSize(FromDIP(720), -1));
progress_lr_panel->Layout();
progress_lr_panel->Fit();
bSizer_subtask_info->Add(0, 0, 0, wxEXPAND | wxTOP, FromDIP(14));
bSizer_subtask_info->Add(bSizer_task_name, 0, wxEXPAND|wxRIGHT, FromDIP(18));
bSizer_subtask_info->Add(m_staticText_profile_value, 0, wxEXPAND | wxTOP, FromDIP(5));
bSizer_subtask_info->Add(progress_lr_panel, 0, wxEXPAND | wxTOP, FromDIP(5));
m_printing_sizer = new wxBoxSizer(wxHORIZONTAL);
m_printing_sizer->SetMinSize(wxSize(PAGE_MIN_WIDTH, -1));
m_printing_sizer->Add(m_bitmap_thumbnail, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT | wxLEFT, FromDIP(12));
m_printing_sizer->Add(FromDIP(8), 0, 0, wxEXPAND, 0);
m_printing_sizer->Add(bSizer_subtask_info, 1, wxALL | wxEXPAND, 0);
m_staticline = new wxPanel( parent, wxID_ANY);
m_staticline->SetBackgroundColour(wxColour(238,238,238));
m_staticline->Layout();
m_staticline->Hide();
m_panel_error_txt = new wxPanel(parent, wxID_ANY);
m_panel_error_txt->SetBackgroundColour(*wxWHITE);
wxBoxSizer *static_text_sizer = new wxBoxSizer(wxHORIZONTAL);
m_error_text = new Label(m_panel_error_txt, "", LB_AUTO_WRAP);
m_error_text->SetForegroundColour(wxColour(255, 0, 0));
static_text_sizer->Add(m_error_text, 1, wxEXPAND | wxLEFT, FromDIP(17));
m_button_clean = new Button(m_panel_error_txt, _L("Clear"));
m_button_clean->SetStyle(ButtonStyle::Regular, ButtonType::Window);
static_text_sizer->Add( FromDIP(10), 0, 0, 0, 0 );
static_text_sizer->Add(m_button_clean, 0, wxALIGN_CENTRE_VERTICAL|wxRIGHT, FromDIP(5));
m_panel_error_txt->SetSizer(static_text_sizer);
m_panel_error_txt->Hide();
sizer->Add(m_panel_printing_title, 0, wxEXPAND | wxALL, 0);
sizer->Add(0, FromDIP(12), 0);
sizer->Add(m_printing_sizer, 0, wxEXPAND | wxALL, 0);
sizer->Add(0, 0, 0, wxTOP, FromDIP(15));
sizer->Add(m_staticline, 0, wxEXPAND | wxALL, FromDIP(10));
sizer->Add(m_panel_error_txt, 0, wxEXPAND | wxALL, 0);
sizer->Add(0, FromDIP(12), 0);
m_score_staticline = new wxPanel(parent, wxID_ANY);
m_score_staticline->SetBackgroundColour(wxColour(238, 238, 238));
m_score_staticline->Layout();
m_score_staticline->Hide();
sizer->Add(0, 0, 0, wxTOP, FromDIP(15));
sizer->Add(m_score_staticline, 0, wxEXPAND | wxALL, FromDIP(10));
m_request_failed_panel = new wxPanel(parent, wxID_ANY);
m_request_failed_panel->SetBackgroundColour(*wxWHITE);
wxBoxSizer *static_request_failed_panel_sizer = new wxBoxSizer(wxHORIZONTAL);
m_request_failed_info = new wxStaticText(m_request_failed_panel, wxID_ANY, _L("You have completed printing the mall model, \nbut synchronizing rating information has failed."), wxDefaultPosition, wxDefaultSize, 0);
m_request_failed_info->Wrap(-1);
m_request_failed_info->SetForegroundColour(*wxRED);
m_request_failed_info->SetFont(::Label::Body_10);
static_request_failed_panel_sizer->Add(m_request_failed_info, 0, wxEXPAND | wxALL, FromDIP(10));
m_button_market_retry = new Button(m_request_failed_panel, _L("Retry"));
m_button_market_retry->SetStyle(ButtonStyle::Confirm, ButtonType::Window);
static_request_failed_panel_sizer->Add(0, 0, 1, wxEXPAND, 0);
static_request_failed_panel_sizer->Add(m_button_market_retry, 0, wxEXPAND | wxALL, FromDIP(10));
m_request_failed_panel->SetSizer(static_request_failed_panel_sizer);
m_request_failed_panel->Hide();
sizer->Add(m_request_failed_panel, 0, wxEXPAND | wxALL, FromDIP(10));
m_score_subtask_info = new wxPanel(parent, wxID_ANY);
m_score_subtask_info->SetBackgroundColour(*wxWHITE);
wxBoxSizer * static_score_sizer = new wxBoxSizer(wxVERTICAL);
wxStaticText *static_score_text = new wxStaticText(m_score_subtask_info, wxID_ANY, _L("How do you like this printing file?"), wxDefaultPosition, wxDefaultSize, 0);
static_score_text->Wrap(-1);
static_score_sizer->Add(static_score_text, 1, wxEXPAND | wxALL, FromDIP(10));
m_has_rated_prompt = new wxStaticText(m_score_subtask_info, wxID_ANY, _L("(The model has already been rated. Your rating will overwrite the previous rating.)"), wxDefaultPosition, wxDefaultSize, 0);
m_has_rated_prompt->Wrap(-1);
m_has_rated_prompt->SetForegroundColour(*wxBLACK);
m_has_rated_prompt->SetFont(::Label::Body_10);
m_has_rated_prompt->Hide();
m_star_count = 0;
wxBoxSizer *static_score_star_sizer = new wxBoxSizer(wxHORIZONTAL);
m_score_star.resize(5);
for (int i = 0; i < m_score_star.size(); ++i) {
m_score_star[i] = new ScalableButton(m_score_subtask_info, wxID_ANY, "score_star_dark", wxEmptyString, wxSize(FromDIP(26), FromDIP(26)), wxDefaultPosition,
wxBU_EXACTFIT | wxNO_BORDER, true, 26);
m_score_star[i]->SetMinSize(wxSize(FromDIP(26), FromDIP(26)));
m_score_star[i]->SetMaxSize(wxSize(FromDIP(26), FromDIP(26)));
m_score_star[i]->Bind(wxEVT_LEFT_DOWN, [this, i](auto &e) {
for (int j = 0; j < m_score_star.size(); ++j) {
ScalableBitmap light_star = ScalableBitmap(nullptr, "score_star_light", 26);
m_score_star[j]->SetBitmap(light_star.bmp());
if (m_score_star[j] == m_score_star[i]) {
m_star_count = j + 1;
break;
}
}
for (int k = m_star_count; k < m_score_star.size(); ++k) {
ScalableBitmap dark_star = ScalableBitmap(nullptr, "score_star_dark", 26);
m_score_star[k]->SetBitmap(dark_star.bmp());
}
m_star_count_dirty = true;
m_button_market_scoring->Enable(true);
});
static_score_star_sizer->Add(m_score_star[i], 1, wxEXPAND | wxLEFT, FromDIP(5));
}
m_button_market_scoring = new Button(m_score_subtask_info, _L("Rate"));
m_button_market_scoring->SetStyle(ButtonStyle::Confirm, ButtonType::Window);
m_button_market_scoring->Enable(false);
static_score_star_sizer->Add(0, 0, 1, wxEXPAND, 0);
static_score_star_sizer->Add(m_button_market_scoring, 0, wxEXPAND | wxRIGHT, FromDIP(10));
static_score_sizer->Add(static_score_star_sizer, 0, wxEXPAND, FromDIP(10));
static_score_sizer->Add(m_has_rated_prompt, 1, wxEXPAND | wxALL, FromDIP(10));
m_score_subtask_info->SetSizer(static_score_sizer);
m_score_subtask_info->Layout();
m_score_subtask_info->Hide();
sizer->Add(m_score_subtask_info, 0, wxEXPAND | wxALL, 0);
sizer->Add(0, FromDIP(12), 0);
if (m_type == CALIBRATION) {
m_panel_printing_title->Hide();
m_bitmap_thumbnail->Hide();
task_name_panel->Hide();
m_staticText_profile_value->Hide();
}
parent->SetSizer(sizer);
parent->Layout();
parent->Fit();
}
void PrintingTaskPanel::paint(wxPaintEvent&)
{
wxPaintDC dc(m_bitmap_thumbnail);
if (wxGetApp().dark_mode()) {
if (m_brightness_value > 0 && m_brightness_value < SHOW_BACKGROUND_BITMAP_PIXEL_THRESHOLD) {
dc.DrawBitmap(m_bitmap_background.bmp(), 0, 0);
dc.SetTextForeground(*wxBLACK);
}
else
dc.SetTextForeground(*wxWHITE);
}
else
dc.SetTextForeground(*wxBLACK);
if (m_thumbnail_bmp_display.IsOk()) {
dc.DrawBitmap(m_thumbnail_bmp_display, wxPoint(0, 0));
}
dc.SetFont(Label::Body_12);
if (m_plate_index >= 0) {
wxString plate_id_str = wxString::Format("%d", m_plate_index);
dc.DrawText(plate_id_str, wxPoint(4, 4));
}
}
void PrintingTaskPanel::set_has_reted_text(bool has_rated)
{
if (has_rated) {
m_has_rated_prompt->Show();
} else {
m_has_rated_prompt->Hide();
}
Layout();
Fit();
}
void PrintingTaskPanel::msw_rescale()
{
m_panel_printing_title->SetSize(wxSize(-1, FromDIP(PAGE_TITLE_HEIGHT)));
m_printing_sizer->SetMinSize(wxSize(PAGE_MIN_WIDTH, -1));
//m_staticText_printing->SetMinSize(wxSize(PAGE_TITLE_TEXT_WIDTH, PAGE_TITLE_HEIGHT));
m_gauge_progress->SetHeight(PROGRESSBAR_HEIGHT);
m_gauge_progress->Rescale();
m_button_pause_resume->msw_rescale();
m_button_abort->msw_rescale();
m_bitmap_thumbnail->SetSize(TASK_THUMBNAIL_SIZE);
}
void PrintingTaskPanel::init_bitmaps()
{
m_thumbnail_placeholder = ScalableBitmap(this, "monitor_placeholder", 120);
m_bitmap_use_time = ScalableBitmap(this, "print_info_time", 16);
m_bitmap_use_weight = ScalableBitmap(this, "print_info_weight", 16);
}
void PrintingTaskPanel::init_scaled_buttons()
{
m_button_clean->SetMinSize(wxSize(FromDIP(48), FromDIP(24)));
m_button_clean->SetCornerRadius(FromDIP(12));
}
void PrintingTaskPanel::error_info_reset()
{
if (m_panel_error_txt->IsShown()) {
m_staticline->Hide();
m_panel_error_txt->Hide();
m_panel_error_txt->GetParent()->Layout();
m_error_text->SetLabel(wxEmptyString);
}
}
void PrintingTaskPanel::show_error_msg(wxString msg)
{
m_staticline->Show();
m_panel_error_txt->Show();
m_error_text->SetLabel(msg);
}
void PrintingTaskPanel::reset_printing_value()
{
this->set_thumbnail_img(m_thumbnail_placeholder.bmp(), m_thumbnail_placeholder.name());
this->set_plate_index(-1);
}
void PrintingTaskPanel::enable_partskip_button(MachineObject* obj, bool enable)
{
int stage = 0;
bool in_calibration_mode = false;
if( obj && (obj->print_type == "system" || CalibUtils::get_calib_mode_by_name(obj->subtask_name, stage) != CalibMode::Calib_None)){
in_calibration_mode = true;
}
if (!enable || in_calibration_mode) {
m_button_partskip->Enable(false);
m_button_partskip->SetLabel("");
m_button_partskip->SetIcon("print_control_partskip_disable");
}else if(obj && obj->is_support_brtc){
m_button_partskip->Enable(true);
m_button_partskip->SetIcon("print_control_partskip");
}
}
void PrintingTaskPanel::enable_pause_resume_button(bool enable, std::string type)
{
if (!enable) {
m_button_pause_resume->Enable(false);
if (type == "pause_disable") {
m_button_pause_resume->SetBitmap_("print_control_pause_disable");
}
else if (type == "resume_disable") {
m_button_pause_resume->SetBitmap_("print_control_resume_disable");
}
}
else {
m_button_pause_resume->Enable(true);
if (type == "resume") {
m_button_pause_resume->SetBitmap_("print_control_resume");
if (m_button_pause_resume->GetToolTipText() != _L("Resume")) { m_button_pause_resume->SetToolTip(_L("Resume")); }
}
else if (type == "pause") {
m_button_pause_resume->SetBitmap_("print_control_pause");
if (m_button_pause_resume->GetToolTipText() != _L("Pause")) { m_button_pause_resume->SetToolTip(_L("Pause")); }
}
}
}
void PrintingTaskPanel::enable_abort_button(bool enable)
{
if (!enable) {
m_button_abort->Enable(false);
m_button_abort->SetBitmap_("print_control_stop_disable");
}
else {
m_button_abort->Enable(true);
m_button_abort->SetBitmap_("print_control_stop");
}
}
void PrintingTaskPanel::update_subtask_name(wxString name)
{
if (m_staticText_subtask_value->GetLabelText() != name)
{
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": " << name;
}
m_staticText_subtask_value->SetLabelText(name);
}
void PrintingTaskPanel::update_stage_value(wxString stage, int val)
{
m_printing_stage_value->SetLabelText(stage);
m_gauge_progress->SetValue(val);
}
void PrintingTaskPanel::update_stage_value_with_machine(wxString stage, int val, MachineObject *obj)
{
m_gauge_progress->SetValue(val);
m_printing_stage_value->SetLabelText(stage);
if (obj && obj->stage_curr == 58) {
m_question_button->Show(); // Show question button
} else {
m_question_button->Hide(); // Hide question button
m_printing_stage_underline->Hide();
}
m_printing_stage_panel->Layout();
Layout();
}
void PrintingTaskPanel::on_stage_clicked(wxMouseEvent &event)
{
auto *dev_manager = wxGetApp().getDeviceManager();
MachineObject *obj = dev_manager ? dev_manager->get_selected_machine() : nullptr;
if (obj && obj->stage_curr == 58) {
wxWindow *top = wxGetTopLevelParent(this);
ThermalPreconditioningDialog m_thermal_dialog(top ? top : this, obj->get_dev_id() , "Calculating...");
m_thermal_dialog.ShowModal();
}
event.Skip();
}
void PrintingTaskPanel::update_progress_percent(wxString percent, wxString icon)
{
m_staticText_progress_percent->SetLabelText(percent);
m_staticText_progress_percent_icon->SetLabelText(icon);
}
void PrintingTaskPanel::update_left_time(wxString time)
{
m_staticText_progress_left->SetLabelText(time);
}
void PrintingTaskPanel::update_left_time(int mc_left_time)
{
// update gcode progress
std::string left_time;
wxString left_time_text = NA_STR;
try {
left_time = get_bbl_monitor_time_dhm(mc_left_time);
}
catch (...) {
;
}
if (!left_time.empty()) left_time_text = wxString::Format("-%s", left_time);
update_left_time(left_time_text);
//Update end time
std::string end_time;
wxString end_time_text = NA_STR;
try {
end_time = get_bbl_monitor_end_time_dhm(mc_left_time);
} catch (...) {
;
}
if (!end_time.empty())
end_time_text = wxString::Format("%s", end_time);
else
end_time_text = NA_STR;
m_staticText_progress_end->SetLabelText(end_time_text);
}
void PrintingTaskPanel::update_layers_num(bool show, wxString num)
{
if ((show == m_staticText_layers->IsShown()) && (num == m_staticText_layers->GetLabelText()))
{
return;
}
if (show) {
m_staticText_layers->Show(true);
m_staticText_layers->SetLabelText(num);
}
else {
m_staticText_layers->Show(false);
m_staticText_layers->SetLabelText(num);
}
}
void PrintingTaskPanel::show_priting_use_info(bool show, wxString time /*= wxEmptyString*/, wxString weight /*= wxEmptyString*/)
{
if (show) {
if (!m_staticText_consumption_of_time->IsShown()) {
m_bitmap_static_use_time->Show();
m_staticText_consumption_of_time->Show();
}
if (!m_staticText_consumption_of_weight->IsShown()) {
m_bitmap_static_use_weight->Show();
m_staticText_consumption_of_weight->Show();
}
m_staticText_consumption_of_time->SetLabelText(time);
m_staticText_consumption_of_weight->SetLabelText(weight);
}
else {
m_staticText_consumption_of_time->SetLabelText("0m");
m_staticText_consumption_of_weight->SetLabelText("0g");
if (m_staticText_consumption_of_time->IsShown()) {
m_bitmap_static_use_time->Hide();
m_staticText_consumption_of_time->Hide();
}
if (m_staticText_consumption_of_weight->IsShown()) {
m_bitmap_static_use_weight->Hide();
m_staticText_consumption_of_weight->Hide();
} }
}
void PrintingTaskPanel::show_profile_info(bool show, wxString profile /*= wxEmptyString*/)
{
if (show) {
if (!m_staticText_profile_value->IsShown()) { m_staticText_profile_value->Show(); }
m_staticText_profile_value->SetLabelText(profile);
}
else {
m_staticText_profile_value->SetLabelText(wxEmptyString);
m_staticText_profile_value->Hide();
}
}
// the API will buff the bmp and bmp_name
// when bmp_name is empty, the API will replace the image on force
void PrintingTaskPanel::set_thumbnail_img(const wxBitmap& bmp, const std::string& bmp_name)
{
if (!bmp_name.empty() && m_thumbnail_bmp_display_name == bmp_name) {
return;
}
m_thumbnail_bmp_display_name = bmp_name;
m_thumbnail_bmp_display = bmp;
Refresh();
}
void PrintingTaskPanel::set_plate_index(int plate_idx)
{
m_plate_index = plate_idx;
}
void PrintingTaskPanel::market_scoring_show()
{
m_score_staticline->Show();
m_score_subtask_info->Show();
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " show market scoring page";
}
void PrintingTaskPanel::market_scoring_hide()
{
m_score_staticline->Hide();
m_score_subtask_info->Hide();
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " hide market scoring page";
}
void PrintingTaskPanel::set_star_count(int star_count)
{
m_star_count = star_count;
for (int i = 0; i < m_score_star.size(); ++i) {
if (i < star_count) {
ScalableBitmap light_star = ScalableBitmap(nullptr, "score_star_light", 26);
m_score_star[i]->SetBitmap(light_star.bmp());
} else {
ScalableBitmap dark_star = ScalableBitmap(nullptr, "score_star_dark", 26);
m_score_star[i]->SetBitmap(dark_star.bmp());
}
}
}
StatusBasePanel::StatusBasePanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, long style, const wxString &name)
: wxScrolledWindow(parent, id, pos, size, wxHSCROLL | wxVSCROLL)
{
SetScrollRate(25, FromDIP(20));
Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (!dev) return;
obj = dev->get_selected_machine();
init_bitmaps();
this->SetBackgroundColour(wxColour(0xEE, 0xEE, 0xEE));
wxBoxSizer *bSizer_status = new wxBoxSizer(wxVERTICAL);
auto m_panel_separotor_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, PAGE_SPACING), wxTAB_TRAVERSAL);
m_panel_separotor_top->SetBackgroundColour(STATUS_PANEL_BG);
bSizer_status->Add(m_panel_separotor_top, 0, wxEXPAND | wxALL, 0);
wxBoxSizer *bSizer_status_below = new wxBoxSizer(wxHORIZONTAL);
auto m_panel_separotor_left = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
m_panel_separotor_left->SetBackgroundColour(STATUS_PANEL_BG);
m_panel_separotor_left->SetMinSize(wxSize(PAGE_SPACING, -1));
bSizer_status_below->Add(m_panel_separotor_left, 0, wxEXPAND | wxALL, 0);
wxBoxSizer *bSizer_left = new wxBoxSizer(wxVERTICAL);
// The sizers are nested here so each step only appends to its own.
add_build_step([this, bSizer_left] {
auto m_monitoring_sizer = create_monitoring_page();
bSizer_left->Add(m_monitoring_sizer, 1, wxEXPAND | wxALL, 0);
auto m_panel_separotor1 = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
m_panel_separotor1->SetBackgroundColour(STATUS_PANEL_BG);
m_panel_separotor1->SetMinSize(wxSize(-1, PAGE_SPACING));
m_panel_separotor1->SetMaxSize(wxSize(-1, PAGE_SPACING));
m_monitoring_sizer->Add(m_panel_separotor1, 0, wxEXPAND, 0);
m_project_task_panel = new PrintingTaskPanel(this, PrintingTaskType::PRINGINT);
m_project_task_panel->init_bitmaps();
m_monitoring_sizer->Add(m_project_task_panel, 0, wxALL | wxEXPAND , 0);
});
// auto m_panel_separotor2 = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
// m_panel_separotor2->SetBackgroundColour(STATUS_PANEL_BG);
// m_panel_separotor2->SetMinSize(wxSize(-1, PAGE_SPACING));
// bSizer_left->Add(m_panel_separotor2, 1, wxEXPAND, 0);
bSizer_status_below->Add(bSizer_left, 1, wxALL | wxEXPAND, 0);
auto m_panel_separator_middle = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE | wxTAB_TRAVERSAL);
m_panel_separator_middle->SetBackgroundColour(STATUS_PANEL_BG);
m_panel_separator_middle->SetMinSize(wxSize(PAGE_SPACING, -1));
bSizer_status_below->Add(m_panel_separator_middle, 0, wxEXPAND | wxALL, 0);
m_machine_ctrl_panel = new wxPanel(this);
m_machine_ctrl_panel->SetBackgroundColour(*wxWHITE);
m_machine_ctrl_panel->SetDoubleBuffered(true);
auto m_machine_control = create_machine_control_page(m_machine_ctrl_panel);
m_machine_ctrl_panel->SetSizer(m_machine_control);
add_build_step([this, m_machine_control] {
m_machine_ctrl_panel->Layout();
m_machine_control->Fit(m_machine_ctrl_panel);
});
bSizer_status_below->Add(m_machine_ctrl_panel, 0, wxALL, 0);
m_panel_separator_right = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(PAGE_SPACING, -1), wxTAB_TRAVERSAL);
m_panel_separator_right->SetBackgroundColour(STATUS_PANEL_BG);
bSizer_status_below->Add(m_panel_separator_right, 0, wxEXPAND | wxALL, 0);
bSizer_status->Add(bSizer_status_below, 1, wxALL | wxEXPAND, 0);
m_panel_separotor_bottom = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, PAGE_SPACING), wxTAB_TRAVERSAL);
m_panel_separotor_bottom->SetBackgroundColour(STATUS_PANEL_BG);
bSizer_status->Add(m_panel_separotor_bottom, 0, wxEXPAND | wxALL, 0);
this->SetSizer(bSizer_status);
add_build_step([this, bSizer_status] {
bSizer_status->SetSizeHints(this);
this->Layout();
});
}
StatusBasePanel::~StatusBasePanel()
{
delete m_media_play_ctrl;
if (m_custom_camera_view) {
delete m_custom_camera_view;
m_custom_camera_view = nullptr;
}
}
void StatusBasePanel::init_bitmaps()
{
static Slic3r::GUI::BitmapCache cache;
m_bitmap_item_prediction = create_scaled_bitmap("monitor_item_prediction", nullptr, 16);
m_bitmap_item_cost = create_scaled_bitmap("monitor_item_cost", nullptr, 16);
m_bitmap_item_print = create_scaled_bitmap("monitor_item_print", nullptr, 18);
m_bitmap_axis_home = ScalableBitmap(this, "monitor_axis_home", 32);
m_bitmap_lamp_on = ScalableBitmap(this, "monitor_lamp_on", 24);
m_bitmap_lamp_off = ScalableBitmap(this, "monitor_lamp_off", 24);
m_bitmap_fan_on = ScalableBitmap(this, "monitor_fan_on", 22);
m_bitmap_fan_off = ScalableBitmap(this, "monitor_fan_off", 22);
m_bitmap_speed = ScalableBitmap(this, "monitor_speed", 24);
m_bitmap_speed_active = ScalableBitmap(this, "monitor_speed_active", 24);
m_thumbnail_brokenimg = ScalableBitmap(this, "monitor_brokenimg", 120);
m_thumbnail_sdcard = ScalableBitmap(this, "monitor_sdcard_thumbnail", 120);
//m_bitmap_camera = create_scaled_bitmap("monitor_camera", nullptr, 18);
m_bitmap_extruder_empty_load = *cache.load_png("monitor_extruder_empty_load", FromDIP(28), FromDIP(70), false, false);
m_bitmap_extruder_filled_load = *cache.load_png("monitor_extruder_filled_load", FromDIP(28), FromDIP(70), false, false);
m_bitmap_extruder_empty_unload = *cache.load_png("monitor_extruder_empty_unload", FromDIP(28), FromDIP(70), false, false);
m_bitmap_extruder_filled_unload = *cache.load_png("monitor_extruder_filled_unload", FromDIP(28), FromDIP(70), false, false);
m_bitmap_sdcard_state_abnormal = ScalableBitmap(this, wxGetApp().dark_mode() ? "sdcard_state_abnormal_dark" : "sdcard_state_abnormal", 20);
m_bitmap_sdcard_state_normal = ScalableBitmap(this, wxGetApp().dark_mode() ? "sdcard_state_normal_dark" : "sdcard_state_normal", 20);
m_bitmap_sdcard_state_no = ScalableBitmap(this, wxGetApp().dark_mode() ? "sdcard_state_no_dark" : "sdcard_state_no", 20);
m_bitmap_recording_on = ScalableBitmap(this, wxGetApp().dark_mode() ? "monitor_recording_on_dark" : "monitor_recording_on", 20);
m_bitmap_recording_off = ScalableBitmap(this, wxGetApp().dark_mode() ? "monitor_recording_off_dark" : "monitor_recording_off", 20);
m_bitmap_timelapse_on = ScalableBitmap(this, wxGetApp().dark_mode() ? "monitor_timelapse_on_dark" : "monitor_timelapse_on", 20);
m_bitmap_timelapse_off = ScalableBitmap(this, wxGetApp().dark_mode() ? "monitor_timelapse_off_dark" : "monitor_timelapse_off", 20);
m_bitmap_vcamera_on = ScalableBitmap(this, wxGetApp().dark_mode() ? "monitor_vcamera_on_dark" : "monitor_vcamera_on", 20);
m_bitmap_vcamera_off = ScalableBitmap(this, wxGetApp().dark_mode() ? "monitor_vcamera_off_dark" : "monitor_vcamera_off", 20);
m_bitmap_switch_camera = ScalableBitmap(this, wxGetApp().dark_mode() ? "camera_switch_dark" : "camera_switch", 20);
}
wxBoxSizer *StatusBasePanel::create_monitoring_page()
{
wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
m_panel_monitoring_title = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, PAGE_TITLE_HEIGHT), wxTAB_TRAVERSAL);
m_panel_monitoring_title->SetBackgroundColour(STATUS_TITLE_BG);
wxBoxSizer *bSizer_monitoring_title;
bSizer_monitoring_title = new wxBoxSizer(wxHORIZONTAL);
m_staticText_monitoring = new Label(m_panel_monitoring_title, _L("Camera"));
m_staticText_monitoring->Wrap(-1);
//m_staticText_monitoring->SetFont(PAGE_TITLE_FONT);
m_staticText_monitoring->SetForegroundColour(PAGE_TITLE_FONT_COL);
bSizer_monitoring_title->Add(m_staticText_monitoring, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, PAGE_TITLE_LEFT_MARGIN);
bSizer_monitoring_title->Add(FromDIP(13), 0, 0, 0);
bSizer_monitoring_title->AddStretchSpacer();
m_staticText_timelapse = new wxStaticText(m_panel_monitoring_title, wxID_ANY, _L("Timelapse"), wxDefaultPosition, wxDefaultSize, 0);
m_staticText_timelapse->Wrap(-1);
m_staticText_timelapse->Hide();
bSizer_monitoring_title->Add(m_staticText_timelapse, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5));
m_mqtt_source = new wxStaticText(m_panel_monitoring_title, wxID_ANY, "MqttSource", wxDefaultPosition, wxDefaultSize, 0);
m_mqtt_source->Wrap(-1);
m_mqtt_source->Hide();
bSizer_monitoring_title->Add(m_mqtt_source, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5));
m_bmToggleBtn_timelapse = new SwitchButton(m_panel_monitoring_title);
m_bmToggleBtn_timelapse->SetMinSize(SWITCH_BUTTON_SIZE);
m_bmToggleBtn_timelapse->Hide();
bSizer_monitoring_title->Add(m_bmToggleBtn_timelapse, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5));
#if !BBL_RELEASE_TO_PUBLIC
m_staticText_timelapse->Show();
m_bmToggleBtn_timelapse->Show();
m_bmToggleBtn_timelapse->Bind(wxEVT_TOGGLEBUTTON, [](wxCommandEvent &e) {
if (e.IsChecked())
wxGetApp().getAgent()->start_subscribe("tunnel");
else
wxGetApp().getAgent()->stop_subscribe("tunnel");
});
#endif
//m_bitmap_camera_img = new wxStaticBitmap(m_panel_monitoring_title, wxID_ANY, m_bitmap_camera , wxDefaultPosition, wxSize(FromDIP(32), FromDIP(18)), 0);
//m_bitmap_camera_img->SetMinSize(wxSize(FromDIP(32), FromDIP(18)));
//bSizer_monitoring_title->Add(m_bitmap_camera_img, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5));
m_bitmap_sdcard_img = new wxStaticBitmap(m_panel_monitoring_title, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize(FromDIP(38), FromDIP(24)), 0);
m_bitmap_sdcard_img->SetMinSize(wxSize(FromDIP(38), FromDIP(24)));
m_bitmap_timelapse_img = new wxStaticBitmap(m_panel_monitoring_title, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize(FromDIP(38), FromDIP(24)), 0);
m_bitmap_timelapse_img->SetMinSize(wxSize(FromDIP(38), FromDIP(24)));
m_bitmap_timelapse_img->Hide();
m_bitmap_recording_img = new wxStaticBitmap(m_panel_monitoring_title, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize(FromDIP(38), FromDIP(24)), 0);
m_bitmap_recording_img->SetMinSize(wxSize(FromDIP(38), FromDIP(24)));
m_bitmap_timelapse_img->Hide();
m_bitmap_vcamera_img = new wxStaticBitmap(m_panel_monitoring_title, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize(FromDIP(38), FromDIP(24)), 0);
m_bitmap_vcamera_img->SetMinSize(wxSize(FromDIP(38), FromDIP(24)));
m_bitmap_vcamera_img->Hide();
m_setting_button = new CameraItem(m_panel_monitoring_title, "camera_setting", "camera_setting_hover");
m_setting_button->SetMinSize(wxSize(FromDIP(38), FromDIP(24)));
m_setting_button->SetBackgroundColour(STATUS_TITLE_BG);
// m_camera_switch_button = new wxStaticBitmap(m_panel_monitoring_title, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize(FromDIP(38), FromDIP(24)), 0);
// m_camera_switch_button->SetMinSize(wxSize(FromDIP(38), FromDIP(24)));
// m_camera_switch_button->SetBackgroundColour(STATUS_TITLE_BG);
// m_camera_switch_button->SetBitmap(m_bitmap_switch_camera.bmp());
// m_camera_switch_button->Bind(wxEVT_RIGHT_DOWN, [this](auto& e) {
// const std::string js_request_pip = R"(
// document.querySelector('video').requestPictureInPicture();
// )";
// m_custom_camera_view->RunScript(js_request_pip);
// });
// m_camera_switch_button->Hide();
m_bitmap_sdcard_img->SetToolTip(_L("Storage"));
m_bitmap_timelapse_img->SetToolTip(_L("Timelapse"));
m_bitmap_recording_img->SetToolTip(_L("Video"));
m_bitmap_vcamera_img->SetToolTip(_L("Go Live"));
m_setting_button->SetToolTip(_L("Camera Setting"));
// m_camera_switch_button->SetToolTip(_L("Switch Camera View"));
// bSizer_monitoring_title->Add(m_camera_switch_button, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5));
bSizer_monitoring_title->Add(m_bitmap_sdcard_img, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5));
bSizer_monitoring_title->Add(m_bitmap_timelapse_img, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5));
bSizer_monitoring_title->Add(m_bitmap_recording_img, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5));
bSizer_monitoring_title->Add(m_bitmap_vcamera_img, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5));
bSizer_monitoring_title->Add(m_setting_button, 0, wxALIGN_CENTER_VERTICAL | wxALL, FromDIP(5));
bSizer_monitoring_title->Add(FromDIP(13), 0, 0);
m_panel_monitoring_title->SetSizer(bSizer_monitoring_title);
m_panel_monitoring_title->Layout();
bSizer_monitoring_title->Fit(m_panel_monitoring_title);
sizer->Add(m_panel_monitoring_title, 0, wxEXPAND | wxALL, 0);
// media_ctrl_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize);
// media_ctrl_panel->SetBackgroundColour(*wxBLACK);
// wxBoxSizer *bSizer_monitoring = new wxBoxSizer(wxVERTICAL);
m_media_ctrl = new wxMediaCtrl3(this);
m_media_ctrl->SetMinSize(wxSize(PAGE_MIN_WIDTH, FromDIP(288)));
m_custom_camera_view = WebView::CreateWebView(this, wxEmptyString);
m_custom_camera_view->EnableContextMenu(false);
Bind(wxEVT_WEBVIEW_NAVIGATING, &StatusBasePanel::on_webview_navigating, this, m_custom_camera_view->GetId());
m_web_media_controller = std::make_unique<WebMediaController>(m_custom_camera_view);
m_media_play_ctrl = new MediaPlayCtrl(this, m_media_ctrl, wxDefaultPosition, wxSize(-1, FromDIP(40)));
m_media_play_ctrl->SetWebMediaController(m_web_media_controller.get());
m_custom_camera_view->Hide();
// m_custom_camera_view->Bind(wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, [this](wxWebViewEvent& evt) {
// if (evt.GetString() == "leavepictureinpicture") {
// // When leaving PiP, video gets paused in some cases and toggling play
// // programmatically does not work.
// m_custom_camera_view->Reload();
// }
// });
sizer->Add(m_media_ctrl, 1, wxEXPAND | wxALL, 0);
sizer->Add(m_custom_camera_view, 1, wxEXPAND | wxALL, 0);
sizer->Add(m_media_play_ctrl, 0, wxEXPAND | wxALL, 0);
// media_ctrl_panel->SetSizer(bSizer_monitoring);
// media_ctrl_panel->Layout();
//
// sizer->Add(media_ctrl_panel, 1, wxEXPAND | wxALL, 1);
return sizer;
}
void StatusBasePanel::on_webview_navigating(wxWebViewEvent& evt) {
wxGetApp().CallAfter([this] {
remove_controls();
});
}
wxBoxSizer *StatusBasePanel::create_machine_control_page(wxWindow *parent)
{
wxBoxSizer *bSizer_right = new wxBoxSizer(wxVERTICAL);
m_panel_control_title = new wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(-1, PAGE_TITLE_HEIGHT), wxTAB_TRAVERSAL);
m_panel_control_title->SetBackgroundColour(STATUS_TITLE_BG);
wxBoxSizer *bSizer_control_title = new wxBoxSizer(wxHORIZONTAL);
m_staticText_control = new Label(m_panel_control_title,_L("Control"));
m_staticText_control->Wrap(-1);
//m_staticText_control->SetFont(PAGE_TITLE_FONT);
m_staticText_control->SetForegroundColour(PAGE_TITLE_FONT_COL);
m_parts_btn = new Button(m_panel_control_title, _L("Printer Parts"));
m_parts_btn->SetStyle(ButtonStyle::Confirm, ButtonType::Window);
m_options_btn = new Button(m_panel_control_title, _L("Print Options"));
m_options_btn->SetStyle(ButtonStyle::Confirm, ButtonType::Window);
m_safety_btn = new Button(m_panel_control_title, _L("Safety Options"));
m_safety_btn->SetStyle(ButtonStyle::Confirm, ButtonType::Window);
m_calibration_btn = new Button(m_panel_control_title, _L("Calibration"));
m_calibration_btn->SetStyle(ButtonStyle::Confirm, ButtonType::Window);
m_calibration_btn->EnableTooltipEvenDisabled();
m_options_btn->Hide();
m_safety_btn->Hide();
bSizer_control_title->Add(m_staticText_control, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, PAGE_TITLE_LEFT_MARGIN);
bSizer_control_title->Add(0, 0, 1, wxEXPAND, 0);
bSizer_control_title->Add(m_parts_btn, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(10));
bSizer_control_title->Add(m_options_btn, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(10));
bSizer_control_title->Add(m_safety_btn, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(10));
bSizer_control_title->Add(m_calibration_btn, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(10));
m_panel_control_title->SetSizer(bSizer_control_title);
m_panel_control_title->Layout();
bSizer_control_title->Fit(m_panel_control_title);
bSizer_right->Add(m_panel_control_title, 0, wxALL | wxEXPAND, 0);
wxBoxSizer *bSizer_control = new wxBoxSizer(wxVERTICAL);
// The slot sizers keep each group's place in bSizer_control.
wxBoxSizer *temp_axis_slot = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *filament_slot = new wxBoxSizer(wxVERTICAL);
/* ams control box or live nozzle-rack panel (rack printers switch between the two) */
wxSizer *ams_rack_sizer = new wxBoxSizer(wxHORIZONTAL);
add_build_step([this, parent, temp_axis_slot, filament_slot] {
temp_axis_slot->Add(create_temp_axis_group(parent), 0, wxEXPAND);
filament_slot->Add(create_filament_group(parent), 0, wxEXPAND);
});
add_build_step([this, parent, ams_rack_sizer] {
ams_rack_sizer->Add(create_ams_group(parent), 0, wxEXPAND | wxLEFT);
});
add_build_step([this, parent, ams_rack_sizer] {
m_panel_nozzle_rack = new wgtDeviceNozzleRack(parent);
m_panel_nozzle_rack->Show(false);
ams_rack_sizer->Add(m_panel_nozzle_rack, 0, wxEXPAND | wxLEFT);
});
m_ams_rack_switch = new SwitchBoard(parent, _L("Filament"), _L("Hotends"), wxSize(FromDIP(126), FromDIP(26)));
m_ams_rack_switch->updateState("left");
m_ams_rack_switch->Hide();
m_ams_rack_switch->Bind(wxCUSTOMEVT_SWITCH_POS, &StatusBasePanel::on_ams_rack_switch, this);
bSizer_control->Add(0, 0, 0, wxTOP, FromDIP(8));
bSizer_control->Add(temp_axis_slot, 0, wxALIGN_CENTER|wxLEFT|wxRIGHT, FromDIP(8));
bSizer_control->Add(m_ams_rack_switch, 0, wxALIGN_CENTRE|wxTOP, FromDIP(6));
bSizer_control->Add(0, 0, 0, wxTOP, FromDIP(6));
bSizer_control->Add(ams_rack_sizer, 0, wxALIGN_CENTER|wxLEFT|wxRIGHT, FromDIP(8));
bSizer_control->Add(0, 0, 0, wxTOP, FromDIP(6));
bSizer_control->Add(filament_slot, 0, wxALIGN_CENTER|wxLEFT|wxRIGHT, FromDIP(8));
bSizer_control->Add(0, 0, 0, wxTOP, FromDIP(4));
bSizer_right->Add(bSizer_control, 1, wxEXPAND | wxALL, 0);
return bSizer_right;
}
wxBoxSizer *StatusBasePanel::create_temp_axis_group(wxWindow *parent)
{
auto sizer = new wxBoxSizer(wxVERTICAL);
auto box = new StaticBox(parent);
StateColor box_colour(std::pair<wxColour, int>(*wxWHITE, StateColor::Normal));
StateColor box_border_colour(std::pair<wxColour, int>(STATUS_PANEL_BG, StateColor::Normal));
box->SetBackgroundColor(box_colour);
box->SetBorderColor(box_border_colour);
box->SetCornerRadius(5);
box->SetMinSize(wxSize(FromDIP(586), -1));
box->SetMaxSize(wxSize(FromDIP(586), -1));
wxBoxSizer *content_sizer = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer *m_temp_ctrl = create_temp_control(box);
m_temp_temp_line = new wxPanel(box);
m_temp_temp_line->SetMaxSize(wxSize(FromDIP(1), -1));
m_temp_temp_line->SetMinSize(wxSize(FromDIP(1), -1));
m_temp_temp_line->SetBackgroundColour(STATIC_BOX_LINE_COL);
auto m_axis_sizer = create_axis_control(box);
auto bedPanel = create_bed_control(box);
wxBoxSizer *extruder_sizer = create_extruder_control(box);
wxBoxSizer* axis_and_bed_control_sizer = new wxBoxSizer(wxVERTICAL);
axis_and_bed_control_sizer->Add(m_axis_sizer, 0, wxEXPAND | wxALL, 0);
axis_and_bed_control_sizer->Add(bedPanel, 0, wxALIGN_CENTER, 0);
content_sizer->Add(m_temp_ctrl, 0, wxEXPAND | wxALL, FromDIP(5));
content_sizer->Add(m_temp_temp_line, 0, wxEXPAND, 1);
//content_sizer->Add(FromDIP(9), 0, 0, wxEXPAND, 1);
/*content_sizer->Add(0, 0, 0, wxLEFT, FromDIP(18));
content_sizer->Add(m_axis_sizer, 0, wxALIGN_CENTER_VERTICAL | wxALL, 0);
content_sizer->Add(0, 0, 0, wxLEFT, FromDIP(18));
content_sizer->Add(bed_sizer, 0, wxEXPAND | wxLEFT | wxTOP | wxBOTTOM, FromDIP(12));*/
content_sizer->Add(axis_and_bed_control_sizer, 1, wxALIGN_CENTER, 0);
//content_sizer->Add(0, 0, 0, wxLEFT, FromDIP(18));
m_temp_extruder_line = new wxPanel(box);
m_temp_extruder_line->SetMaxSize(wxSize(FromDIP(1), -1));
m_temp_extruder_line->SetMinSize(wxSize(FromDIP(1), -1));
m_temp_extruder_line->SetBackgroundColour(STATIC_BOX_LINE_COL);
content_sizer->Add(m_temp_extruder_line, 0, wxEXPAND, 1);
content_sizer->Add(extruder_sizer, 0, wxEXPAND | wxTOP | wxBOTTOM, FromDIP(12));
content_sizer->Add(0, 0, 0, wxRIGHT, FromDIP(3));
box->SetSizer(content_sizer);
sizer->Add(box, 0, wxEXPAND | wxALL, FromDIP(9));
return sizer;
}
wxBoxSizer *StatusBasePanel::create_temp_control(wxWindow *parent)
{
auto sizer = new wxBoxSizer(wxVERTICAL);
wxWindowID nozzle_id = wxWindow::NewControlId();
m_tempCtrl_nozzle = new TempInput(parent, nozzle_id, TEMP_BLANK_STR, TempInputType::TEMP_OF_NORMAL_TYPE, TEMP_BLANK_STR, wxString("monitor_nozzle_temp"),
wxString("monitor_nozzle_temp_active"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER);
m_tempCtrl_nozzle->SetMinSize(TEMP_CTRL_MIN_SIZE_ALIGN_TWO_ICON);
m_tempCtrl_nozzle->AddTemp(0); // zero is default temp
m_tempCtrl_nozzle->SetMinTemp(20);
m_tempCtrl_nozzle->SetMaxTemp(300);
m_tempCtrl_nozzle->SetBorderWidth(FromDIP(2));
StateColor tempinput_text_colour(std::make_pair(DISCONNECT_TEXT_COL, (int) StateColor::Disabled), std::make_pair(NORMAL_TEXT_COL, (int) StateColor::Normal));
StateColor tempinput_border_colour(std::make_pair(*wxWHITE, (int)StateColor::Disabled), std::make_pair(BUTTON_HOVER_COL, (int)StateColor::Focused),
std::make_pair(BUTTON_HOVER_COL, (int)StateColor::Hovered), std::make_pair(*wxWHITE, (int)StateColor::Normal));
m_tempCtrl_nozzle->SetTextColor(tempinput_text_colour);
m_tempCtrl_nozzle->SetBorderColor(tempinput_border_colour);
m_tempCtrl_nozzle_deputy = new TempInput(parent, nozzle_id, TEMP_BLANK_STR, TempInputType::TEMP_OF_NORMAL_TYPE, TEMP_BLANK_STR, wxString("monitor_nozzle_temp"), wxString("monitor_nozzle_temp_active"),
wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER);
m_tempCtrl_nozzle_deputy->SetMinSize(TEMP_CTRL_MIN_SIZE_ALIGN_TWO_ICON);
m_tempCtrl_nozzle_deputy->AddTemp(0); // zero is default temp
m_tempCtrl_nozzle_deputy->SetMinTemp(20);
m_tempCtrl_nozzle_deputy->SetMaxTemp(300);
m_tempCtrl_nozzle_deputy->SetBorderWidth(FromDIP(2));
m_tempCtrl_nozzle_deputy->SetTextColor(tempinput_text_colour);
m_tempCtrl_nozzle_deputy->SetBorderColor(tempinput_border_colour);
sizer->Add(m_tempCtrl_nozzle_deputy, 0, wxEXPAND | wxALL, 1);
sizer->Add(m_tempCtrl_nozzle, 0, wxEXPAND | wxALL, 1);
m_tempCtrl_nozzle_deputy->Hide();
m_line_nozzle = new StaticLine(parent);
m_line_nozzle->SetLineColour(STATIC_BOX_LINE_COL);
m_line_nozzle->SetSize(wxSize(FromDIP(1), -1));
sizer->Add(m_line_nozzle, 0, wxEXPAND | wxLEFT | wxRIGHT, 12);
wxWindowID bed_id = wxWindow::NewControlId();
m_tempCtrl_bed = new TempInput(parent, bed_id, TEMP_BLANK_STR, TempInputType::TEMP_OF_NORMAL_TYPE, TEMP_BLANK_STR, wxString("monitor_bed_temp"),
wxString("monitor_bed_temp_active"), wxDefaultPosition,wxDefaultSize, wxALIGN_CENTER);
m_tempCtrl_bed->AddTemp(0); // zero is default temp
m_tempCtrl_bed->SetMinTemp(bed_temp_range[0]);
m_tempCtrl_bed->SetMaxTemp(bed_temp_range[1]);
m_tempCtrl_bed->SetMinSize(TEMP_CTRL_MIN_SIZE_ALIGN_ONE_ICON);
m_tempCtrl_bed->SetBorderWidth(FromDIP(2));
m_tempCtrl_bed->SetTextColor(tempinput_text_colour);
m_tempCtrl_bed->SetBorderColor(tempinput_border_colour);
sizer->Add(m_tempCtrl_bed, 0, wxEXPAND | wxALL, 1);
auto line = new StaticLine(parent);
line->SetLineColour(STATIC_BOX_LINE_COL);
sizer->Add(line, 0, wxEXPAND | wxLEFT | wxRIGHT, 12);
wxWindowID frame_id = wxWindow::NewControlId();
m_tempCtrl_chamber = new TempInput(parent, frame_id, TEMP_BLANK_STR, TempInputType::TEMP_OF_NORMAL_TYPE, TEMP_BLANK_STR, wxString("monitor_frame_temp"),
wxString("monitor_frame_temp_active"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER);
m_tempCtrl_chamber->AddTemp(0); // zero is default temp
m_tempCtrl_chamber->SetReadOnly(true);
m_tempCtrl_chamber->SetMinTemp(default_champer_temp_min);
m_tempCtrl_chamber->SetMaxTemp(default_champer_temp_max);
m_tempCtrl_chamber->SetMinSize(TEMP_CTRL_MIN_SIZE_ALIGN_ONE_ICON);
m_tempCtrl_chamber->SetBorderWidth(FromDIP(2));
m_tempCtrl_chamber->SetTextColor(tempinput_text_colour);
m_tempCtrl_chamber->SetBorderColor(tempinput_border_colour);
sizer->Add(m_tempCtrl_chamber, 0, wxEXPAND | wxALL, 1);
m_misc_ctrl_sizer = create_misc_control(parent);
sizer->Add(m_misc_ctrl_sizer, 0, wxEXPAND, 0);
return sizer;
}
wxBoxSizer *StatusBasePanel::create_misc_control(wxWindow *parent)
{
wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *line_sizer = new wxBoxSizer(wxHORIZONTAL);
/* create speed control */
m_switch_speed = new ImageSwitchButton(parent, m_bitmap_speed_active, m_bitmap_speed);
m_switch_speed->SetLabels("100%", "100%");
m_switch_speed->SetMinSize(MISC_BUTTON_2FAN_SIZE);
m_switch_speed->SetMaxSize(MISC_BUTTON_2FAN_SIZE);
m_switch_speed->SetPadding(FromDIP(3));
m_switch_speed->SetBorderWidth(FromDIP(2));
m_switch_speed->SetFont(Label::Head_13);
m_switch_speed->SetTextColor(StateColor(std::make_pair(DISCONNECT_TEXT_COL, (int) StateColor::Disabled), std::make_pair(NORMAL_TEXT_COL, (int) StateColor::Normal)));
m_switch_speed->SetValue(false);
line_sizer->Add(m_switch_speed, 1, wxALIGN_CENTER | wxALL, 0);
auto line = new StaticLine(parent, true);
line->SetLineColour(STATIC_BOX_LINE_COL);
line_sizer->Add(line, 0, wxEXPAND | wxTOP | wxBOTTOM, 4);
/* create lamp control */
m_switch_lamp = new ImageSwitchButton(parent, m_bitmap_lamp_on, m_bitmap_lamp_off);
m_switch_lamp->SetLabels(_L("Lamp"), _L("Lamp"));
m_switch_lamp->SetMinSize(MISC_BUTTON_2FAN_SIZE);
m_switch_lamp->SetMaxSize(MISC_BUTTON_2FAN_SIZE);
m_switch_lamp->SetPadding(FromDIP(3));
m_switch_lamp->SetBorderWidth(FromDIP(2));
m_switch_lamp->SetFont(Label::Head_13);
m_switch_lamp->SetTextColor(StateColor(std::make_pair(DISCONNECT_TEXT_COL, (int) StateColor::Disabled), std::make_pair(NORMAL_TEXT_COL, (int) StateColor::Normal)));
line_sizer->Add(m_switch_lamp, 1, wxALIGN_CENTER | wxALL, 0);
//sizer->Add(line_sizer, 0, wxEXPAND, FromDIP(5));
line = new StaticLine(parent);
line->SetLineColour(STATIC_BOX_LINE_COL);
sizer->Add(line, 0, wxEXPAND | wxLEFT | wxRIGHT, 12);
m_fan_panel = new StaticBox(parent);
m_fan_panel->SetMinSize(MISC_BUTTON_PANEL_SIZE);
m_fan_panel->SetMaxSize(MISC_BUTTON_PANEL_SIZE);
m_fan_panel->SetBackgroundColor(*wxWHITE);
m_fan_panel->SetBorderWidth(0);
m_fan_panel->SetCornerRadius(0);
auto fan_line_sizer = new wxBoxSizer(wxHORIZONTAL);
m_switch_fan = new FanSwitchButton(m_fan_panel, m_bitmap_fan_on, m_bitmap_fan_off);
m_switch_fan->SetValue(false);
m_switch_fan->SetMinSize(MISC_BUTTON_1FAN_SIZE);
m_switch_fan->SetMaxSize(MISC_BUTTON_1FAN_SIZE);
m_switch_fan->SetPadding(FromDIP(1));
m_switch_fan->SetBorderWidth(0);
m_switch_fan->SetCornerRadius(0);
m_switch_fan->SetFont(::Label::Body_10);
m_switch_fan->UseTextFan();
m_switch_fan->SetTextColor(
StateColor(std::make_pair(DISCONNECT_TEXT_COL, (int)StateColor::Disabled), std::make_pair(NORMAL_FAN_TEXT_COL, (int)StateColor::Normal)));
m_switch_fan->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {
m_fan_panel->SetBackgroundColor(wxColour(0, 150, 136));
});
m_switch_fan->Bind(wxEVT_LEAVE_WINDOW, [this, parent](auto& e) {
m_fan_panel->SetBackgroundColor(parent->GetBackgroundColour());
});
fan_line_sizer->Add(m_switch_fan, 1, wxEXPAND|wxALL, FromDIP(2));
m_fan_panel->SetSizer(fan_line_sizer);
m_fan_panel->Layout();
m_fan_panel->Fit();
sizer->Add(m_fan_panel, 0, wxEXPAND, FromDIP(5));
line = new StaticLine(parent);
line->SetLineColour(STATIC_BOX_LINE_COL);
sizer->Add(line, 0, wxEXPAND | wxLEFT | wxRIGHT, 12);
sizer->Add(line_sizer, 0, wxEXPAND, FromDIP(5));
return sizer;
}
void StatusBasePanel::reset_temp_misc_control()
{
// reset temp string
m_tempCtrl_nozzle->SetIconNormal();
m_tempCtrl_nozzle->SetLabel(TEMP_BLANK_STR);
m_tempCtrl_nozzle->GetTextCtrl()->SetValue(TEMP_BLANK_STR);
m_tempCtrl_nozzle_deputy->SetIconNormal();
m_tempCtrl_nozzle_deputy->SetLabel(TEMP_BLANK_STR);
m_tempCtrl_nozzle_deputy->GetTextCtrl()->SetValue(TEMP_BLANK_STR);
m_tempCtrl_bed->SetIconNormal();
m_tempCtrl_bed->SetLabel(TEMP_BLANK_STR);
m_tempCtrl_bed->GetTextCtrl()->SetValue(TEMP_BLANK_STR);
m_tempCtrl_chamber->SetIconNormal();
m_tempCtrl_chamber->SetLabel(TEMP_BLANK_STR);
m_tempCtrl_chamber->GetTextCtrl()->SetValue(TEMP_BLANK_STR);
m_tempCtrl_nozzle->Enable(true);
m_tempCtrl_nozzle_deputy->Enable(true);
m_tempCtrl_chamber->Enable(true);
m_tempCtrl_bed->Enable(true);
// reset misc control
m_switch_speed->SetLabels("100%", "100%");
m_switch_speed->SetValue(false);
m_switch_lamp->SetLabels(_L("Lamp"), _L("Lamp"));
m_switch_lamp->SetValue(false);
/*m_switch_nozzle_fan->SetValue(false);
m_switch_printing_fan->SetValue(false);
m_switch_cham_fan->SetValue(false);*/
}
wxBoxSizer *StatusBasePanel::create_axis_control(wxWindow *parent)
{
auto sizer = new wxBoxSizer(wxVERTICAL);
sizer->AddStretchSpacer();
m_bpButton_xy = new AxisCtrlButton(parent, m_bitmap_axis_home);
m_bpButton_xy->SetTextColor(StateColor(std::make_pair(DISCONNECT_TEXT_COL, (int) StateColor::Disabled), std::make_pair(NORMAL_TEXT_COL, (int) StateColor::Normal)));
m_bpButton_xy->SetMinSize(AXIS_MIN_SIZE);
m_bpButton_xy->SetSize(AXIS_MIN_SIZE);
sizer->AddStretchSpacer();
sizer->Add(m_bpButton_xy, 0, wxALIGN_CENTER | wxALL, 0);
sizer->AddStretchSpacer();
return sizer;
}
wxPanel *StatusBasePanel::create_bed_control(wxWindow *parent)
{
wxBoxSizer *bSizer_z_ctrl = new wxBoxSizer(wxHORIZONTAL);
auto panel = new wxPanel(parent, wxID_ANY);
panel->SetBackgroundColour(*wxWHITE);
StateColor z_10_ctrl_bg(std::pair<wxColour, int>(BUTTON_PRESS_COL, StateColor::Pressed), std::pair<wxColour, int>(BUTTON_NORMAL1_COL, StateColor::Normal));
StateColor z_10_ctrl_bd(std::pair<wxColour, int>(BUTTON_HOVER_COL, StateColor::Hovered), std::pair<wxColour, int>(BUTTON_NORMAL1_COL, StateColor::Normal));
StateColor z_1_ctrl_bg(std::pair<wxColour, int>(BUTTON_PRESS_COL, StateColor::Pressed), std::pair<wxColour, int>(BUTTON_NORMAL2_COL, StateColor::Normal));
StateColor z_1_ctrl_bd(std::pair<wxColour, int>(BUTTON_HOVER_COL, StateColor::Hovered), std::pair<wxColour, int>(BUTTON_NORMAL2_COL, StateColor::Normal));
m_bpButton_z_10 = new Button(panel, wxString("10"), "monitor_bed_up", 0, 15); // Orca Dont scale icon size
m_bpButton_z_10->SetFont(::Label::Body_12);
m_bpButton_z_10->SetBorderWidth(0);
m_bpButton_z_10->SetBackgroundColor(z_10_ctrl_bg);
m_bpButton_z_10->SetBorderColor(z_10_ctrl_bd);
m_bpButton_z_10->SetTextColor(StateColor(std::make_pair(DISCONNECT_TEXT_COL, (int) StateColor::Disabled), std::make_pair(NORMAL_TEXT_COL, (int) StateColor::Normal)));
m_bpButton_z_10->SetMinSize(Z_BUTTON_SIZE);
m_bpButton_z_10->SetSize(Z_BUTTON_SIZE);
m_bpButton_z_10->SetCornerRadius(0);
m_bpButton_z_1 = new Button(panel, wxString(" 1"), "monitor_bed_up", 0, 15); // Orca Dont scale icon size
m_bpButton_z_1->SetFont(::Label::Body_12);
m_bpButton_z_1->SetBorderWidth(0);
m_bpButton_z_1->SetBackgroundColor(z_1_ctrl_bg);
m_bpButton_z_1->SetBorderColor(z_1_ctrl_bd);
m_bpButton_z_1->SetMinSize(Z_BUTTON_SIZE);
m_bpButton_z_1->SetSize(Z_BUTTON_SIZE);
m_bpButton_z_1->SetTextColor(StateColor(std::make_pair(DISCONNECT_TEXT_COL, (int) StateColor::Disabled), std::make_pair(NORMAL_TEXT_COL, (int) StateColor::Normal)));
//bSizer_z_ctrl->Add(0, FromDIP(6), 0, wxEXPAND, 0);
m_staticText_z_tip = new wxStaticText(panel, wxID_ANY, _L("Bed"), wxDefaultPosition, wxDefaultSize, 0);
m_staticText_z_tip->SetFont(::Label::Body_12);
if (wxGetApp().app_config->get("language") == "de_DE") m_staticText_z_tip->SetFont(::Label::Body_11);
m_staticText_z_tip->Wrap(-1);
m_staticText_z_tip->SetForegroundColour(TEXT_LIGHT_FONT_COL);
m_bpButton_z_down_1 = new Button(panel, wxString(" 1"), "monitor_bed_down", 0, 15); // Orca Dont scale icon size
m_bpButton_z_down_1->SetFont(::Label::Body_12);
m_bpButton_z_down_1->SetBorderWidth(0);
m_bpButton_z_down_1->SetBackgroundColor(z_1_ctrl_bg);
m_bpButton_z_down_1->SetBorderColor(z_1_ctrl_bd);
m_bpButton_z_down_1->SetMinSize(Z_BUTTON_SIZE);
m_bpButton_z_down_1->SetSize(Z_BUTTON_SIZE);
m_bpButton_z_down_1->SetTextColor(StateColor(std::make_pair(DISCONNECT_TEXT_COL, (int) StateColor::Disabled), std::make_pair(NORMAL_TEXT_COL, (int) StateColor::Normal)));
m_bpButton_z_down_10 = new Button(panel, wxString("10"), "monitor_bed_down", 0, 15); // Orca Dont scale icon size
m_bpButton_z_down_10->SetFont(::Label::Body_12);
m_bpButton_z_down_10->SetBorderWidth(0);
m_bpButton_z_down_10->SetBackgroundColor(z_10_ctrl_bg);
m_bpButton_z_down_10->SetBorderColor(z_10_ctrl_bd);
m_bpButton_z_down_10->SetMinSize(Z_BUTTON_SIZE);
m_bpButton_z_down_10->SetSize(Z_BUTTON_SIZE);
m_bpButton_z_down_10->SetTextColor(StateColor(std::make_pair(DISCONNECT_TEXT_COL, (int) StateColor::Disabled), std::make_pair(NORMAL_TEXT_COL, (int) StateColor::Normal)));
bSizer_z_ctrl->Add(m_bpButton_z_10, 0, wxEXPAND | wxLEFT | wxRIGHT, 0);
bSizer_z_ctrl->Add(m_bpButton_z_1, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(2));
bSizer_z_ctrl->Add(m_staticText_z_tip, 0, wxALIGN_CENTRE, FromDIP(5));
bSizer_z_ctrl->Add(m_bpButton_z_down_1, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(2));
bSizer_z_ctrl->Add(m_bpButton_z_down_10, 0, wxEXPAND | wxLEFT | wxRIGHT, 0);
panel->SetSizer(bSizer_z_ctrl);
panel->Layout();
panel->Fit();
return panel;
}
wxBoxSizer *StatusBasePanel::create_extruder_control(wxWindow *parent)
{
wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *bSizer_e_ctrl = new wxBoxSizer(wxVERTICAL);
auto panel = new wxPanel(parent,wxID_ANY);
panel->SetBackgroundColour(*wxWHITE);
panel->SetSize(wxSize(FromDIP(143), -1));
panel->SetMinSize(wxSize(FromDIP(143), -1));
panel->SetMaxSize(wxSize(FromDIP(143), -1));
StateColor e_ctrl_bg(std::pair<wxColour, int>(BUTTON_PRESS_COL, StateColor::Pressed), std::pair<wxColour, int>(BUTTON_NORMAL1_COL, StateColor::Normal));
StateColor e_ctrl_bd(std::pair<wxColour, int>(BUTTON_HOVER_COL, StateColor::Hovered), std::pair<wxColour, int>(BUTTON_NORMAL1_COL, StateColor::Normal));
m_nozzle_btn_panel = new SwitchBoard(panel, _L_CONTEXT("Left", "Nozzle position"), _L_CONTEXT("Right", "Nozzle position"), wxSize(FromDIP(126), FromDIP(26)));
m_nozzle_btn_panel->SetAutoDisableWhenSwitch();
m_bpButton_e_10 = new Button(panel, "", "monitor_extruder_up", 0, 22); // Orca Dont scale icon size
m_bpButton_e_10->SetBorderWidth(2);
m_bpButton_e_10->SetBackgroundColor(e_ctrl_bg);
m_bpButton_e_10->SetBorderColor(e_ctrl_bd);
m_bpButton_e_10->SetMinSize(wxSize(FromDIP(40), FromDIP(40)));
m_extruder_book = new wxSimplebook(panel, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(45), FromDIP(112)), 0);
m_extruder_book->InsertPage(0, new wxPanel(panel), "");
for (int nozzle_num = 1; nozzle_num <= 2; nozzle_num++) {
auto extruder_img = new ExtruderImage(m_extruder_book, wxID_ANY, nozzle_num);
m_extruder_book->InsertPage(nozzle_num, extruder_img, "");
m_extruderImage.push_back(extruder_img);
}
m_extruder_book->SetSelection(0);
m_bpButton_e_down_10 = new Button(panel, "", "monitor_extruder_down", 0, 22); // Orca Dont scale icon size
m_bpButton_e_down_10->SetBorderWidth(2);
m_bpButton_e_down_10->SetBackgroundColor(e_ctrl_bg);
m_bpButton_e_down_10->SetBorderColor(e_ctrl_bd);
m_bpButton_e_down_10->SetMinSize(wxSize(FromDIP(40), FromDIP(40)));
m_extruder_switching_status = new ExtruderSwithingStatus(panel);
m_extruder_switching_status->SetForegroundColour(TEXT_LIGHT_FONT_COL);
m_extruder_label = new ::Label(panel, _L("Extruder"));
m_extruder_label->SetFont(::Label::Body_13);
m_extruder_label->SetForegroundColour(TEXT_LIGHT_FONT_COL);
bSizer_e_ctrl->Add(0, 0, 0, wxTOP, FromDIP(15));
bSizer_e_ctrl->Add(m_nozzle_btn_panel, 0, wxALIGN_CENTER_HORIZONTAL, 0);
bSizer_e_ctrl->Add(0, 0, 0, wxTOP, FromDIP(15));
bSizer_e_ctrl->Add(m_bpButton_e_10, 0, wxALIGN_CENTER_HORIZONTAL, 0);
bSizer_e_ctrl->Add(0, 0, 0, wxTOP, FromDIP(7));
bSizer_e_ctrl->Add(m_extruder_book, 0, wxALIGN_CENTER_HORIZONTAL, 0);
bSizer_e_ctrl->Add(0, 0, 0, wxTOP, FromDIP(7));
bSizer_e_ctrl->Add(m_bpButton_e_down_10, 0, wxALIGN_CENTER_HORIZONTAL, 0);
bSizer_e_ctrl->Add(0, 0, 1, wxEXPAND, 0);
bSizer_e_ctrl->Add(m_extruder_switching_status, 0, wxALIGN_CENTER_HORIZONTAL, 0);
bSizer_e_ctrl->Add(m_extruder_label, 0, wxTOP | wxALIGN_CENTER_HORIZONTAL, FromDIP(10));
panel->SetSizer(bSizer_e_ctrl);
panel->Layout();
sizer->Add(panel, 1, wxEXPAND, 0);
return sizer;
}
wxBoxSizer *StatusBasePanel::create_ams_group(wxWindow *parent)
{
auto sizer = new wxBoxSizer(wxVERTICAL);
auto sizer_box = new wxBoxSizer(wxVERTICAL);
m_ams_control_box = new StaticBox(parent);
StateColor box_colour(std::pair<wxColour, int>(*wxWHITE, StateColor::Normal));
StateColor box_border_colour(std::pair<wxColour, int>(STATUS_PANEL_BG, StateColor::Normal));
m_ams_control_box->SetBackgroundColor(box_colour);
m_ams_control_box->SetBorderColor(box_border_colour);
m_ams_control_box->SetCornerRadius(5);
m_ams_control_box->SetMinSize(wxSize(FromDIP(586), -1));
m_ams_control_box->SetBackgroundColour(*wxWHITE);
#if !BBL_RELEASE_TO_PUBLIC
m_ams_debug = new wxStaticText(m_ams_control_box, wxID_ANY, _L("Debug Info"), wxDefaultPosition, wxDefaultSize, 0);
sizer_box->Add(m_ams_debug, 0, wxALIGN_CENTER_HORIZONTAL, 0);
m_ams_debug->Hide();
#endif
m_ams_control = new AMSControl(m_ams_control_box, wxID_ANY);
//m_ams_control->SetMinSize(wxSize(FromDIP(510), FromDIP(286)));
m_ams_control->SetDoubleBuffered(true);
sizer_box->Add(m_ams_control, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, FromDIP(10));
m_ams_control_box->SetBackgroundColour(*wxWHITE);
m_ams_control_box->SetSizer(sizer_box);
m_ams_control_box->Layout();
m_ams_control_box->Fit();
sizer->Add(m_ams_control_box, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, FromDIP(0));
return sizer;
}
wxBoxSizer* StatusBasePanel::create_filament_group(wxWindow* parent)
{
auto sizer = new wxBoxSizer(wxVERTICAL);
auto sizer_scale_panel = new wxBoxSizer(wxHORIZONTAL);
m_scale_panel = new wxPanel(parent);
m_scale_panel->SetMinSize(wxSize(FromDIP(586), FromDIP(40)));
m_scale_panel->SetMaxSize(wxSize(FromDIP(586), FromDIP(40)));
m_scale_panel->SetBackgroundColour(*wxWHITE);
auto m_title_filament_loading = new Label(m_scale_panel, _L("Filament loading..."));
m_title_filament_loading->SetBackgroundColour(*wxWHITE);
m_title_filament_loading->SetForegroundColour(wxColour(0, 137, 123));
m_title_filament_loading->SetFont(::Label::Body_14);
m_img_filament_loading = new wxStaticBitmap(m_scale_panel, wxID_ANY, create_scaled_bitmap("filament_load_fold", this, 24), wxDefaultPosition, wxSize(FromDIP(24), FromDIP(24)), 0);
sizer_scale_panel->Add(0, 0, 0, wxLEFT, FromDIP(20));
sizer_scale_panel->Add(m_title_filament_loading, 0, wxALIGN_CENTER, 0);
sizer_scale_panel->Add(m_img_filament_loading, 0, wxALIGN_CENTER, 0);
m_scale_panel->SetSizer(sizer_scale_panel);
m_scale_panel->Layout();
m_scale_panel->Fit();
m_scale_panel->Hide();
m_title_filament_loading->Bind(wxEVT_LEFT_DOWN, &StatusBasePanel::expand_filament_loading, this);
m_scale_panel->Bind(wxEVT_LEFT_DOWN, &StatusBasePanel::expand_filament_loading, this);
auto sizer_box = new wxBoxSizer(wxVERTICAL);
StateColor box_colour(std::pair<wxColour, int>(*wxWHITE, StateColor::Normal));
StateColor box_border_colour(std::pair<wxColour, int>(STATUS_PANEL_BG, StateColor::Normal));
m_filament_load_box = new StaticBox(parent);
m_filament_load_box->SetBackgroundColor(box_colour);
m_filament_load_box->SetBorderColor(box_border_colour);
m_filament_load_box->SetCornerRadius(5);
m_filament_load_box->SetMinSize(wxSize(FromDIP(586), -1));
m_filament_load_box->SetMaxSize(wxSize(FromDIP(586), -1));
m_filament_load_box->SetBackgroundColour(*wxWHITE);
m_filament_load_box->SetSizer(sizer_box);
m_filament_step = new FilamentLoad(m_filament_load_box, wxID_ANY);
m_filament_step->SetDoubleBuffered(true);
m_filament_step->set_min_size(wxSize(wxSize(FromDIP(300), FromDIP(215))));
m_filament_step->set_max_size(wxSize(wxSize(FromDIP(300), FromDIP(215))));
m_filament_step->SetBackgroundColour(*wxWHITE);
m_filament_load_img = new wxStaticBitmap(m_filament_load_box, wxID_ANY, wxNullBitmap);
m_filament_load_img->SetBackgroundColour(*wxWHITE);
wxBoxSizer *steps_sizer = new wxBoxSizer(wxHORIZONTAL);
steps_sizer->Add(m_filament_step, 0, wxALIGN_LEFT, FromDIP(20));
steps_sizer->Add(m_filament_load_img, 0, wxALIGN_TOP, FromDIP(30));
steps_sizer->AddStretchSpacer();
m_button_retry = new Button(m_filament_load_box, _L("Retry"));
m_button_retry->SetStyle(ButtonStyle::Confirm, ButtonType::Choice);
//m_button_retry->Hide();
m_button_retry->Bind(wxEVT_BUTTON, [this](wxCommandEvent &e) {
BOOST_LOG_TRIVIAL(info) << "on_ams_retry";
if (obj) { obj->command_ams_control("resume"); }
});
// Orca: filament-change Stop button (aborts an in-progress filament change)
m_fila_change_abort = new Button(m_filament_load_box, _L("Stop"));
m_fila_change_abort->SetStyle(ButtonStyle::Regular, ButtonType::Choice);
m_fila_change_abort->Hide();
m_fila_change_abort->Bind(wxEVT_BUTTON, [this](wxCommandEvent &e) {
BOOST_LOG_TRIVIAL(info) << "on_ams_abort";
if (obj) { obj->command_ams_control("abort"); }
});
wxBoxSizer *fila_change_sizer = new wxBoxSizer(wxHORIZONTAL);
fila_change_sizer->Add(m_button_retry, 0, wxRIGHT, FromDIP(7));
fila_change_sizer->Add(m_fila_change_abort, 0, wxLEFT, FromDIP(7));
sizer_box->Add(steps_sizer, 0, wxEXPAND | wxTOP, FromDIP(5));
sizer_box->Add(fila_change_sizer, 0, wxLEFT, FromDIP(28));
sizer_box->Add(0, 0, 0, wxTOP, FromDIP(5));
m_filament_load_box->SetBackgroundColour(*wxWHITE);
m_filament_load_box->Layout();
m_filament_load_box->Fit();
m_filament_load_box->Hide();
sizer->Add(m_scale_panel, 0, wxALIGN_CENTER_HORIZONTAL | wxTOP, FromDIP(5));
sizer->Add(m_filament_load_box, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 0);
return sizer;
}
void StatusBasePanel::expand_filament_loading(wxMouseEvent& e)
{
auto tag_show = false;
if (m_filament_load_box->IsShown()) {
tag_show = false;
m_img_filament_loading->SetBitmap(create_scaled_bitmap("filament_load_fold", this, 24));
} else {
tag_show = true;
m_img_filament_loading->SetBitmap(create_scaled_bitmap("filament_load_expand", this, 24));
}
if (obj)
{
static int load_img_size = 215;
if (obj->is_series_n())
{
m_filament_load_img->SetBitmap(create_scaled_bitmap("filament_load_n_series", this, load_img_size));
}
else if (obj->is_series_x())
{
m_filament_load_img->SetBitmap(create_scaled_bitmap("filament_load_x_series", this, load_img_size));
}
else if (obj->is_series_p())
{
m_filament_load_img->SetBitmap(create_scaled_bitmap("filament_load_p_series", this, load_img_size));
}
else if (obj->is_series_o())
{
const auto& ext_system = obj->GetExtderSystem();
// Prefer the config-driven filament-load image: H2C ships per-extruder bitmaps, and a printer
// fitted with an induction hotend rack picks the rack-specific set (filament_load_image_nozzle_rack).
// Printers whose profile carries no such key (e.g. H2D) get an empty name here and fall through to
// the generic O-series bitmaps below, so their monitor page stays byte-identical. Rack-driven, so
// there is no behavior change for any non-rack printer.
int cur_ext_id = (ext_system && ext_system->GetTotalExtderCount() > 1) ? ext_system->GetCurrentExtderId() : 0;
bool has_nozzle_rack = obj->GetNozzleSystem()->GetNozzleRack()->IsSupported();
std::string img_name = DevPrinterConfigUtil::get_filament_load_img(obj->printer_type, cur_ext_id, has_nozzle_rack);
if (!img_name.empty())
{
m_filament_load_img->SetBitmap(create_scaled_bitmap(img_name, this, load_img_size));
}
else if (ext_system->GetTotalExtderCount() == 2)
{
int cur_extder_id = ext_system->GetCurrentExtderId();
if (cur_extder_id == MAIN_EXTRUDER_ID)
{
m_filament_load_img->SetBitmap(create_scaled_bitmap("filament_load_o_series_right", this, load_img_size));
}
else if (cur_extder_id == DEPUTY_EXTRUDER_ID)
{
m_filament_load_img->SetBitmap(create_scaled_bitmap("filament_load_o_series_left", this, load_img_size));
}
}
else
{
m_filament_load_img->SetBitmap(create_scaled_bitmap("filament_load_o_series", this, load_img_size));
}
}
}
m_filament_load_box->Show(tag_show);
///m_button_retry->Show(tag_show);
m_filament_step->Show(tag_show);
Layout();
Fit();
if (MonitorPanel* monitor = MonitorPanel::if_built()) {
monitor->get_status_panel()->Layout();
monitor->Layout();
}
}
void StatusBasePanel::show_ams_group(bool show)
{
if (m_ams_control->IsShown() != show) {
m_ams_control->Show(show);
m_ams_control->Layout();
m_ams_control->Fit();
Layout();
Fit();
if (MonitorPanel* monitor = MonitorPanel::if_built())
monitor->Layout();
}
// On rack printers, don't clobber the rack view when the user has the switch on "Hotends".
// Inert for every non-rack printer: the switch stays hidden, so this guard never triggers.
if (show && m_ams_rack_switch->IsShown() && (m_ams_rack_switch->switch_left != true)) { return; }
if (m_ams_control_box->IsShown() != show) {
m_ams_control_box->Show(show);
m_ams_control->Layout();
m_ams_control->Fit();
Layout();
Fit();
if (MonitorPanel* monitor = MonitorPanel::if_built())
monitor->Layout();
}
}
void StatusBasePanel::show_filament_load_group(bool show)
{
if (m_scale_panel->IsShown() != show) {
m_scale_panel->Show(show);
if (!show) {
m_img_filament_loading->SetBitmap(create_scaled_bitmap("filament_load_fold", this, 24));
m_img_filament_loading->Refresh();
}
// m_scale_panel control the display of m_filament_load_box
if (!show && m_filament_load_box->IsShown()) {
m_filament_load_box->Show(false);
}
auto cur_ext = obj->GetExtderSystem()->GetCurrentExtder();
m_filament_step->SetupSteps(obj, cur_ext ? cur_ext->HasFilamentInExt() : false);
Layout();
Fit();
if (MonitorPanel* monitor = MonitorPanel::if_built()) {
monitor->get_status_panel()->Layout();
monitor->Layout();
}
}
}
void StatusBasePanel::jump_to_Rack()
{
if (obj && obj->GetNozzleSystem()->GetNozzleRack()->IsSupported()) {
m_ams_rack_switch->updateState("right");
m_ams_control_box->Show(false);
m_panel_nozzle_rack->Show(true);
Layout();
}
}
void StatusBasePanel::on_ams_rack_switch(wxCommandEvent &e)
{
if (!m_ams_control_box->IsShown() && e.GetInt() == 1) {
m_ams_control_box->Show(e.GetInt() == 1);
m_panel_nozzle_rack->Show(e.GetInt() == 0);
Layout();
} else if (!m_panel_nozzle_rack->IsShown() && e.GetInt() == 0) {
m_ams_control_box->Show(e.GetInt() == 1);
m_panel_nozzle_rack->Show(e.GetInt() == 0);
Layout();
}
e.Skip();
}
void StatusPanel::update_camera_state(MachineObject* obj)
{
if (!obj) return;
auto agent = wxGetApp().getAgent();
const auto camera_mode = agent ? agent->get_camera_stream_mode() : CameraStreamMode::none;
const bool use_webview = camera_mode == CameraStreamMode::http_snapshot;
if (use_webview) {
//m_camera_switch_button->Hide();
if (!m_custom_camera_view->IsShown()) {
// why: do not reload the WebView URL per tick, or redirects can cause a reload loop.
// MediaPlayCtrl (via its WebMediaController) owns loading/playing the stream itself.
m_custom_camera_view->Show();
m_media_ctrl->Hide();
}
} else {
if (m_custom_camera_view->IsShown()) {
m_custom_camera_view->Hide();
// Stop the snapshot WebView before switching to native playback
// or leaving the camera mode.
m_media_play_ctrl->StopWebStream();
}
m_media_ctrl->Show();
}
//sdcard
auto sdcard_state = obj->GetStorage()->get_sdcard_state();
if (m_last_sdcard != sdcard_state) {
if (sdcard_state == DevStorage::NO_SDCARD) {
m_bitmap_sdcard_img->SetBitmap(m_bitmap_sdcard_state_no.bmp());
m_bitmap_sdcard_img->SetToolTip(_L("No Storage"));
} else if (sdcard_state == DevStorage::HAS_SDCARD_NORMAL) {
m_bitmap_sdcard_img->SetBitmap(m_bitmap_sdcard_state_normal.bmp());
m_bitmap_sdcard_img->SetToolTip(_L("Storage"));
} else if (sdcard_state == DevStorage::HAS_SDCARD_ABNORMAL) {
m_bitmap_sdcard_img->SetBitmap(m_bitmap_sdcard_state_abnormal.bmp());
m_bitmap_sdcard_img->SetToolTip(_L("Storage Abnormal"));
} else {
m_bitmap_sdcard_img->SetBitmap(m_bitmap_sdcard_state_normal.bmp());
m_bitmap_sdcard_img->SetToolTip(_L("Storage"));
}
m_last_sdcard = sdcard_state;
m_panel_monitoring_title->Layout();
}
//recording
if (m_last_recording != (obj->is_recording() ? 1 : 0)) {
if (obj->is_recording()) {
m_bitmap_recording_img->SetBitmap(m_bitmap_recording_on.bmp());
}
else {
m_bitmap_recording_img->SetBitmap(m_bitmap_recording_off.bmp());
}
m_last_recording = obj->is_recording() ? 1 : 0;
}
if (use_webview) {
if (m_bitmap_recording_img->IsShown()) {
m_bitmap_recording_img->Hide();
m_panel_monitoring_title->Layout();
}
} else if (!m_bitmap_recording_img->IsShown()) {
m_bitmap_recording_img->Show();
m_panel_monitoring_title->Layout();
}
/*if (m_bitmap_recording_img->IsShown())
m_bitmap_recording_img->Hide();*/
//timelapse
if (obj->is_support_timelapse) {
if (m_last_timelapse != (obj->is_timelapse() ? 1: 0)) {
if (obj->is_timelapse()) {
m_bitmap_timelapse_img->SetBitmap(m_bitmap_timelapse_on.bmp());
} else {
m_bitmap_timelapse_img->SetBitmap(m_bitmap_timelapse_off.bmp());
}
m_last_timelapse = obj->is_timelapse() ? 1 : 0;
}
if (!m_bitmap_timelapse_img->IsShown()) {
m_bitmap_timelapse_img->Show();
m_panel_monitoring_title->Layout();
}
} else {
if (m_bitmap_timelapse_img->IsShown()) {
m_bitmap_timelapse_img->Hide();
m_panel_monitoring_title->Layout();
}
}
//vcamera
if (obj->virtual_camera) {
if (m_last_vcamera != (m_media_play_ctrl->IsStreaming() ? 1: 0)) {
if (m_media_play_ctrl->IsStreaming()) {
m_bitmap_vcamera_img->SetBitmap(m_bitmap_vcamera_on.bmp());
} else {
m_bitmap_vcamera_img->SetBitmap(m_bitmap_vcamera_off.bmp());
}
m_last_vcamera = m_media_play_ctrl->IsStreaming() ? 1 : 0;
}
if (!m_bitmap_vcamera_img->IsShown()) {
m_bitmap_vcamera_img->Show();
m_panel_monitoring_title->Layout();
}
} else {
if (m_bitmap_vcamera_img->IsShown()) {
m_bitmap_vcamera_img->Hide();
m_panel_monitoring_title->Layout();
}
}
//camera setting
if (m_camera_popup && m_camera_popup->IsShown()) {
bool show_vcamera = m_media_play_ctrl->IsStreaming();
m_camera_popup->update(show_vcamera);
}
m_setting_button->Show(!use_webview);
}
StatusPanel::StatusPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, long style, const wxString &name)
: StatusBasePanel(parent, id, pos, size, style)
{
// Wires the controls the base class builds in steps, so it is the last step.
add_build_step([this] { wire_controls(); });
}
void StatusPanel::wire_controls()
{
init_scaled_buttons();
m_buttons.push_back(m_bpButton_z_10);
m_buttons.push_back(m_bpButton_z_1);
m_buttons.push_back(m_bpButton_z_down_1);
m_buttons.push_back(m_bpButton_z_down_10);
m_buttons.push_back(m_bpButton_e_10);
m_buttons.push_back(m_bpButton_e_down_10);
obj = nullptr;
m_score_data = new ScoreData;
m_score_data->rating_id = -1;
/* set default values */
m_switch_lamp->SetValue(false);
/*m_switch_printing_fan->SetValue(false);
m_switch_nozzle_fan->SetValue(false);
m_switch_cham_fan->SetValue(false);*/
//m_switch_fan->SetValue(false);
/* set default enable state */
m_project_task_panel->enable_partskip_button(nullptr, false);
m_project_task_panel->enable_pause_resume_button(false, "resume_disable");
m_project_task_panel->enable_abort_button(false);
Bind(wxEVT_WEBREQUEST_STATE, &StatusPanel::on_webrequest_state, this);
Bind(wxCUSTOMEVT_SET_TEMP_FINISH, [this](wxCommandEvent e) {
int id = e.GetInt();
if (id == m_tempCtrl_bed->GetType()) {
on_set_bed_temp();
} else if (id == m_tempCtrl_nozzle->GetType()) {
if (e.GetString() == wxString::Format("%d", MAIN_EXTRUDER_ID)) {
on_set_nozzle_temp(MAIN_EXTRUDER_ID);
} else if (e.GetString() == wxString::Format("%d", DEPUTY_EXTRUDER_ID)) {
on_set_nozzle_temp(DEPUTY_EXTRUDER_ID);
} else {
on_set_nozzle_temp(UNIQUE_EXTRUDER_ID);//there is only one nozzle
}
} else if (id == m_tempCtrl_chamber->GetType()) {
if (!m_tempCtrl_chamber->IsOnChanging()) {
m_tempCtrl_chamber->SetOnChanging();
on_set_chamber_temp();
m_tempCtrl_chamber->ReSetOnChanging();
}
}
});
// Connect Events
m_project_task_panel->get_bitmap_thumbnail()->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(StatusPanel::refresh_thumbnail_webrequest), NULL, this);
m_project_task_panel->get_partskip_button()->Connect(wxEVT_LEFT_DOWN, wxCommandEventHandler(StatusPanel::on_subtask_partskip), NULL, this);
m_project_task_panel->get_pause_resume_button()->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_subtask_pause_resume), NULL, this);
m_project_task_panel->get_abort_button()->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_subtask_abort), NULL, this);
m_project_task_panel->get_market_scoring_button()->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_market_scoring), NULL, this);
m_project_task_panel->get_market_retry_buttom()->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_market_retry), NULL, this);
m_project_task_panel->get_clean_button()->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_print_error_clean), NULL, this);
m_setting_button->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(StatusPanel::on_camera_enter), NULL, this);
m_setting_button->Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(StatusPanel::on_camera_enter), NULL, this);
m_tempCtrl_bed->Connect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_bed_temp_kill_focus), NULL, this);
m_tempCtrl_bed->Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_bed_temp_set_focus), NULL, this);
m_tempCtrl_nozzle->Connect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_kill_focus), NULL, this);
m_tempCtrl_nozzle->Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_set_focus), NULL, this);
m_tempCtrl_nozzle_deputy->Connect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_kill_focus), NULL, this);
m_tempCtrl_nozzle_deputy->Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_set_focus), NULL, this);
m_tempCtrl_chamber->Connect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_cham_temp_kill_focus), NULL, this);
m_tempCtrl_chamber->Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_cham_temp_set_focus), NULL, this);
m_switch_lamp->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_lamp_switch), NULL, this);
//m_switch_nozzle_fan->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this); // TODO
//m_switch_printing_fan->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this);
//m_switch_cham_fan->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this);
m_switch_fan->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this); // TODO
//m_switch_fan->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this);
//m_switch_fan->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this);
m_bpButton_xy->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_xy), NULL, this); // TODO
m_bpButton_z_10->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_z_up_10), NULL, this);
m_bpButton_z_1->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_z_up_1), NULL, this);
m_bpButton_z_down_1->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_z_down_1), NULL, this);
m_bpButton_z_down_10->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_z_down_10), NULL, this);
m_bpButton_e_10->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_e_up_10), NULL, this);
m_bpButton_e_down_10->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_e_down_10), NULL, this);
m_nozzle_btn_panel->Connect(wxCUSTOMEVT_SWITCH_POS, wxCommandEventHandler(StatusPanel::on_nozzle_selected), NULL, this);
Bind(EVT_AMS_EXTRUSION_CALI, &StatusPanel::on_filament_extrusion_cali, this);
Bind(EVT_AMS_LOAD, &StatusPanel::on_ams_load, this);
Bind(EVT_AMS_UNLOAD, &StatusPanel::on_ams_unload, this);
Bind(EVT_AMS_SWITCH, &StatusPanel::on_ams_switch, this);
Bind(EVT_AMS_FILAMENT_BACKUP, &StatusPanel::on_ams_filament_backup, this);
Bind(EVT_AMS_SETTINGS, &StatusPanel::on_ams_setting_click, this);
Bind(EVT_AMS_REFRESH_RFID, &StatusPanel::on_ams_refresh_rfid, this);
Bind(EVT_AMS_ON_SELECTED, &StatusPanel::on_ams_selected, this);
Bind(EVT_AMS_ON_FILAMENT_EDIT, &StatusPanel::on_filament_edit, this);
Bind(EVT_VAMS_ON_FILAMENT_EDIT, &StatusPanel::on_ext_spool_edit, this);
Bind(EVT_AMS_GUIDE_WIKI, &StatusPanel::on_ams_guide, this);
Bind(EVT_AMS_RETRY, &StatusPanel::on_ams_retry, this);
Bind(EVT_FAN_CHANGED, &StatusPanel::on_fan_changed, this);
Bind(EVT_SECONDARY_CHECK_RESUME, &StatusPanel::on_subtask_pause_resume, this);
Bind(EVT_SECONDARY_CHECK_RETRY, [this](auto &e) { if (m_ams_control) { m_ams_control->on_retry(); }});
m_switch_speed->Connect(wxEVT_LEFT_DOWN, wxCommandEventHandler(StatusPanel::on_switch_speed), NULL, this);
m_calibration_btn->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_start_calibration), NULL, this);
m_options_btn->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_show_print_options), NULL, this);
m_safety_btn->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_show_safety_options), NULL, this);
m_parts_btn->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_show_parts_options), NULL, this);
}
StatusPanel::~StatusPanel()
{
// The controls only exist once the last build step has run.
if (built()) {
// Disconnect Events
m_project_task_panel->get_bitmap_thumbnail()->Disconnect(wxEVT_LEFT_DOWN, wxMouseEventHandler(StatusPanel::refresh_thumbnail_webrequest), NULL, this);
m_project_task_panel->get_partskip_button()->Disconnect(wxEVT_LEFT_DOWN, wxCommandEventHandler(StatusPanel::on_subtask_partskip), NULL, this);
m_project_task_panel->get_pause_resume_button()->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_subtask_pause_resume), NULL, this);
m_project_task_panel->get_abort_button()->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_subtask_abort), NULL, this);
m_project_task_panel->get_market_scoring_button()->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_market_scoring), NULL, this);
m_project_task_panel->get_market_retry_buttom()->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_market_retry), NULL, this);
m_project_task_panel->get_clean_button()->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_print_error_clean), NULL, this);
m_setting_button->Disconnect(wxEVT_LEFT_DOWN, wxMouseEventHandler(StatusPanel::on_camera_enter), NULL, this);
m_setting_button->Disconnect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(StatusPanel::on_camera_enter), NULL, this);
m_tempCtrl_bed->Disconnect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_bed_temp_kill_focus), NULL, this);
m_tempCtrl_bed->Disconnect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_bed_temp_set_focus), NULL, this);
m_tempCtrl_nozzle->Disconnect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_kill_focus), NULL, this);
m_tempCtrl_nozzle->Disconnect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_set_focus), NULL, this);
m_tempCtrl_nozzle_deputy->Disconnect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_kill_focus), NULL, this);
m_tempCtrl_nozzle_deputy->Disconnect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_set_focus), NULL, this);
m_switch_lamp->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_lamp_switch), NULL, this);
/*m_switch_nozzle_fan->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this);
m_switch_printing_fan->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this);
m_switch_cham_fan->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this);*/
//m_switch_fan->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this);
//m_switch_fan->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this);
m_switch_fan->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this);
m_bpButton_xy->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_xy), NULL, this);
m_bpButton_z_10->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_z_up_10), NULL, this);
m_bpButton_z_1->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_z_up_1), NULL, this);
m_bpButton_z_down_1->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_z_down_1), NULL, this);
m_bpButton_z_down_10->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_z_down_10), NULL, this);
m_bpButton_e_10->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_e_up_10), NULL, this);
m_bpButton_e_down_10->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_e_down_10), NULL, this);
m_nozzle_btn_panel->Disconnect(wxCUSTOMEVT_SWITCH_POS, wxCommandEventHandler(StatusPanel::on_nozzle_selected), NULL, this);
m_switch_speed->Disconnect(wxEVT_LEFT_DOWN, wxCommandEventHandler(StatusPanel::on_switch_speed), NULL, this);
m_calibration_btn->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_start_calibration), NULL, this);
m_options_btn->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_show_print_options), NULL, this);
m_safety_btn->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_show_safety_options), NULL, this);
m_parts_btn->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_show_parts_options), NULL, this);
}
// remove warning dialogs
if (abort_dlg != nullptr)
delete abort_dlg;
if (ctrl_e_hint_dlg != nullptr)
delete ctrl_e_hint_dlg;
if (sdcard_hint_dlg != nullptr)
delete sdcard_hint_dlg;
if (m_score_data != nullptr) {
delete m_score_data;
}
}
void StatusPanel::init_scaled_buttons()
{
if (!m_project_task_panel) return;
m_project_task_panel->init_scaled_buttons();
m_bpButton_z_10->SetMinSize(Z_BUTTON_SIZE);
m_bpButton_z_10->SetCornerRadius(0);
m_bpButton_z_1->SetMinSize(Z_BUTTON_SIZE);
m_bpButton_z_1->SetCornerRadius(0);
m_bpButton_z_down_1->SetMinSize(Z_BUTTON_SIZE);
m_bpButton_z_down_1->SetCornerRadius(0);
m_bpButton_z_down_10->SetMinSize(Z_BUTTON_SIZE);
m_bpButton_z_down_10->SetCornerRadius(0);
m_bpButton_e_10->SetMinSize(wxSize(FromDIP(40), FromDIP(40)));
m_bpButton_e_10->SetCornerRadius(FromDIP(12));
m_bpButton_e_down_10->SetMinSize(wxSize(FromDIP(40), FromDIP(40)));
m_bpButton_e_down_10->SetCornerRadius(FromDIP(12));
}
void StatusPanel::on_market_scoring(wxCommandEvent &event) {
if (obj && obj->is_makeworld_subtask() && obj->rating_info && obj->rating_info->request_successful) { // model is mall model and has rating_id
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": on_market_scoring" ;
if (m_score_data && m_score_data->rating_id == obj->rating_info->rating_id) { // current score data for model is same as mall model
if (m_score_data->star_count != m_project_task_panel->get_star_count()) m_score_data->star_count = m_project_task_panel->get_star_count();
ScoreDialog m_score_dlg(this, m_score_data);
int ret = m_score_dlg.ShowModal();
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": old data";
if (ret == wxID_OK) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": old data is upload";
m_score_data->rating_id = -1;
m_project_task_panel->set_star_count_dirty(false);
if (obj) obj->get_model_mall_result_need_retry = true;
return;
}
if (m_score_data != nullptr) {
delete m_score_data;
m_score_data = nullptr;
}
m_score_data = new ScoreData(m_score_dlg.get_score_data()); // when user do not submit score, store the data for next opening the score dialog
m_project_task_panel->set_star_count(m_score_data->star_count);
} else {
int star_count = m_project_task_panel->get_star_count_dirty() ? m_project_task_panel->get_star_count() : obj->rating_info->start_count;
bool success_print = obj->rating_info->success_printed;
ScoreDialog m_score_dlg(this, obj->get_modeltask()->design_id, obj->get_modeltask()->model_id, obj->get_modeltask()->profile_id, obj->rating_info->rating_id,
success_print, star_count);
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": new data";
std::string comment = obj->rating_info->content;
if (!comment.empty()) { m_score_dlg.set_comment(comment); }
std::vector<std::string> images_json_array;
images_json_array = obj->rating_info->image_url_paths;
if (!images_json_array.empty()) m_score_dlg.set_cloud_bitmap(images_json_array);
int ret = m_score_dlg.ShowModal();
if (ret == wxID_OK) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": new data is upload";
m_score_data->rating_id = -1;
m_project_task_panel->set_star_count_dirty(false);
if (obj) obj->get_model_mall_result_need_retry = true;
return;
}
if (m_score_data != nullptr) {
delete m_score_data;
m_score_data = nullptr;
}
m_score_data = new ScoreData(m_score_dlg.get_score_data());
m_project_task_panel->set_star_count(m_score_data->star_count);
}
}
}
void StatusPanel::on_market_retry(wxCommandEvent &event)
{
if (obj) {
obj->get_model_mall_result_need_retry = true;
} else {
BOOST_LOG_TRIVIAL(info)<< __FUNCTION__ << "retury failed";
}
}
void StatusPanel::update_partskip_button(MachineObject *obj) {
if (!obj) return;
auto partskip_button = m_project_task_panel->get_partskip_button();
if( obj->is_support_partskip ){
partskip_button->Show();
}else{
partskip_button->Hide();
}
BOOST_LOG_TRIVIAL(info) << "part skip: is_support_partskip: "<< obj->is_support_partskip;
}
void StatusPanel::on_subtask_partskip(wxCommandEvent &event)
{
if (m_partskip_dlg == nullptr) {
m_partskip_dlg = new PartSkipDialog(this->GetParent());
}
auto dm = GUI::wxGetApp().getDeviceManager();
m_partskip_dlg->InitSchedule(dm->get_selected_machine());
BOOST_LOG_TRIVIAL(info) << "part skip: initial part skip dialog.";
if(m_partskip_dlg->ShowModal() == wxID_OK){
int cnt = m_partskip_dlg->GetAllSkippedPartsNum();
m_project_task_panel->set_part_skipped_count(cnt);
m_project_task_panel->set_part_skipped_dirty(5);
BOOST_LOG_TRIVIAL(info) << "part skip: prepare to filter printer dirty data.";
}
}
void StatusPanel::on_subtask_pause_resume(wxCommandEvent &event)
{
if (obj) {
if (obj->can_resume()) {
BOOST_LOG_TRIVIAL(info) << "monitor: resume current print task dev_id =" << obj->get_dev_id();
obj->command_task_resume();
}
else {
BOOST_LOG_TRIVIAL(info) << "monitor: pause current print task dev_id =" << obj->get_dev_id();
obj->command_task_pause();
}
}
}
void StatusPanel::on_subtask_abort(wxCommandEvent &event)
{
if (abort_dlg == nullptr) {
abort_dlg = new SecondaryCheckDialog(this->GetParent(), wxID_ANY, _L("Cancel print"));
abort_dlg->Bind(EVT_SECONDARY_CHECK_CONFIRM, [this](wxCommandEvent &e) {
if (obj) {
BOOST_LOG_TRIVIAL(info) << "monitor: stop current print task dev_id =" << obj->get_dev_id();
obj->command_task_abort();
}
});
}
abort_dlg->update_text(_L("Are you sure you want to stop this print?"));
abort_dlg->m_button_cancel->SetLabel(_L("No"));
abort_dlg->m_button_ok->SetLabel(_L("Yes"));
abort_dlg->on_show();
abort_dlg->Raise();
}
void StatusPanel::error_info_reset()
{
m_project_task_panel->error_info_reset();
}
void StatusPanel::on_print_error_clean(wxCommandEvent &event)
{
error_info_reset();
skip_print_error = obj->print_error;
char buf[32];
::sprintf(buf, "%08X", skip_print_error);
BOOST_LOG_TRIVIAL(info) << "skip_print_error: " << buf;
before_error_code = obj->print_error;
}
void StatusPanel::on_webrequest_state(wxWebRequestEvent &evt)
{
BOOST_LOG_TRIVIAL(trace) << "monitor: monitor_panel web request state = " << evt.GetState();
switch (evt.GetState()) {
case wxWebRequest::State_Completed: {
if (m_current_print_mode != PrintingTaskType::CALIBRATION ||(m_calib_mode == CalibMode::Calib_Flow_Rate && m_calib_method == CalibrationMethod::CALI_METHOD_MANUAL)) {
wxImage img(*evt.GetResponse().GetStream());
img_list.insert(std::make_pair(m_request_url, img));
wxImage resize_img = img.Scale(m_project_task_panel->get_bitmap_thumbnail()->GetSize().x, m_project_task_panel->get_bitmap_thumbnail()->GetSize().y, wxIMAGE_QUALITY_HIGH);
m_project_task_panel->set_thumbnail_img(resize_img, "");
m_project_task_panel->set_brightness_value(get_brightness_value(resize_img));
}
if (obj) {
m_project_task_panel->set_plate_index(obj->m_plate_index);
} else {
m_project_task_panel->set_plate_index(-1);
}
task_thumbnail_state = ThumbnailState::TASK_THUMBNAIL;
break;
}
case wxWebRequest::State_Failed:
case wxWebRequest::State_Cancelled:
case wxWebRequest::State_Unauthorized: {
m_project_task_panel->set_thumbnail_img(m_thumbnail_brokenimg.bmp(), m_thumbnail_brokenimg.name());
m_project_task_panel->set_plate_index(-1);
task_thumbnail_state = ThumbnailState::BROKEN_IMG;
break;
}
case wxWebRequest::State_Active:
case wxWebRequest::State_Idle: break;
default: break;
}
}
void StatusPanel::refresh_thumbnail_webrequest(wxMouseEvent& event)
{
if (!obj) return;
if (task_thumbnail_state != ThumbnailState::BROKEN_IMG) return;
if (obj->slice_info) {
m_request_url = wxString(obj->slice_info->thumbnail_url);
if (!m_request_url.IsEmpty()) {
web_request = wxWebSession::GetDefault().CreateRequest(this, m_request_url);
BOOST_LOG_TRIVIAL(trace) << "monitor: create new webrequest, state = " << web_request.GetState() << ", url = " << m_request_url;
if (web_request.GetState() == wxWebRequest::State_Idle)
web_request.Start();
BOOST_LOG_TRIVIAL(trace) << "monitor: start new webrequest, state = " << web_request.GetState() << ", url = " << m_request_url;
}
}
}
bool StatusPanel::is_task_changed(MachineObject* obj)
{
if (!obj)
return false;
if (last_subtask != obj->subtask_
|| last_profile_id != obj->profile_id_
|| last_task_id != obj->task_id_
) {
last_subtask = obj->subtask_;
last_profile_id = obj->profile_id_;
last_task_id = obj->task_id_;
request_model_info_flag = false;
m_project_task_panel->set_star_count_dirty(false);
return true;
}
return false;
}
void StatusPanel::update(MachineObject *obj)
{
if (!obj || !obj->is_info_ready())
{
m_nozzle_btn_panel->Disable();
return;
}
//m_project_task_panel->Freeze();
update_subtask(obj);
//m_project_task_panel->Thaw();
#if !BBL_RELEASE_TO_PUBLIC
auto delay1 = std::chrono::duration_cast<std::chrono::milliseconds>(obj->last_utc_time - std::chrono::system_clock::now()).count();
auto delay2 = std::chrono::duration_cast<std::chrono::milliseconds>(obj->last_push_time - std::chrono::system_clock::now()).count();
auto delay = wxString::Format(" %ld/%ld", delay1, delay2);
m_staticText_timelapse->SetLabel((obj->is_lan_mode_printer() ? "Local Mqtt" : obj->is_tunnel_mqtt ? "Tunnel Mqtt" : "Cloud Mqtt") + delay);
m_bmToggleBtn_timelapse->Enable(!obj->is_lan_mode_printer());
m_bmToggleBtn_timelapse->SetValue(obj->is_tunnel_mqtt);
#endif
#if !BBL_RELEASE_TO_PUBLIC
if (obj->HasRecentCloudMessage() && obj->HasRecentLanMessage()) m_mqtt_source->SetLabel("Cloud+Lan");
else if (obj->HasRecentCloudMessage()) m_mqtt_source->SetLabel("Cloud");
else if (obj->HasRecentLanMessage()) m_mqtt_source->SetLabel("Lan");
else m_mqtt_source->SetLabel("None");
m_mqtt_source->Show();
#endif
//m_machine_ctrl_panel->Freeze();
if (obj->is_in_printing() && !obj->can_resume()) {
show_printing_status(false, true);
} else {
show_printing_status();
}
/*STUDIO-12573*/
if (!obj->is_fdm_type()) {
m_switch_lamp->Enable(false);
}
update_temp_ctrl(obj);
update_misc_ctrl(obj);
update_ams(obj);
update_cali(obj);
update_rack(obj);
if (obj) {
//nozzle ui
//m_button_left_of_extruder->SetSelected();
// update extrusion calibration
if (m_extrusion_cali_dlg) {
m_extrusion_cali_dlg->update_machine_obj(obj);
m_extrusion_cali_dlg->update();
}
// update calibration status
if (calibration_dlg != nullptr) {
calibration_dlg->update_machine_obj(obj);
calibration_dlg->update_cali(obj);
}
std::string current_printer_type = obj->printer_type;
bool supports_safety = DevPrinterConfigUtil::support_safety_options(current_printer_type);
DevConfig* config = obj->GetConfig();
if (config->SupportFirstLayerInspect() || config->SupportAIMonitor() || obj->is_support_build_plate_marker_detect || obj->is_support_auto_recovery_step_loss) {
m_options_btn->Show();
if (print_options_dlg) {
print_options_dlg->update_machine_obj(obj);
print_options_dlg->update_options(obj);
}
} else {
m_options_btn->Hide();
}
if (obj->support_door_open_check()) {
if (supports_safety) {
m_safety_btn->Show();
if (safety_options_dlg) {
safety_options_dlg->update_machine_obj(obj);
safety_options_dlg->update_options(obj);
}
} else {
m_safety_btn->Hide();
}
} else {
m_safety_btn->Hide();
}
m_parts_btn->Show();
if (m_panel_control_title) {
m_panel_control_title->Layout();
}
if (!obj->dev_connection_type.empty()) {
auto iter_connect_type = m_print_connect_types.find(obj->get_dev_id());
if (iter_connect_type != m_print_connect_types.end()) {
if (iter_connect_type->second != obj->dev_connection_type) {
if (iter_connect_type->second == "lan" && obj->dev_connection_type == "cloud") {
m_print_connect_types[obj->get_dev_id()] = obj->dev_connection_type;
}
if (iter_connect_type->second == "cloud" && obj->dev_connection_type == "lan") {
m_print_connect_types[obj->get_dev_id()] = obj->dev_connection_type;
}
}
}
m_print_connect_types[obj->get_dev_id()] = obj->dev_connection_type;
}
update_error_message();
}
update_camera_state(obj);
//m_machine_ctrl_panel->Thaw();
}
void StatusPanel::show_recenter_dialog() {
RecenterDialog dlg(this);
if (dlg.ShowModal() == wxID_OK)
obj->command_go_home();
}
void StatusPanel::update_error_message()
{
if (!obj) return;
static int last_error = -1;
if (obj->print_error <= 0) {
error_info_reset();
} else if (obj->print_error != last_error) {
/* clear old dialog */
if (m_print_error_dlg) { delete m_print_error_dlg; }
/* show device error message*/
m_print_error_dlg = new DeviceErrorDialog(obj, this);
wxString error_msg = m_print_error_dlg->show_error_code(obj->print_error);
BOOST_LOG_TRIVIAL(info) << "print error: device error code = "<< obj->print_error;
/* show error message on task panel */
if(!error_msg.IsEmpty()) { m_project_task_panel->show_error_msg(error_msg); }
}
last_error = obj->print_error;
}
void StatusPanel::show_printing_status(bool ctrl_area, bool temp_area)
{
if (!ctrl_area) {
m_bpButton_xy->Enable(false);
m_bpButton_z_10->Enable(false);
m_bpButton_z_1->Enable(false);
m_bpButton_z_down_1->Enable(false);
m_bpButton_z_down_10->Enable(false);
m_bpButton_e_10->Enable(false);
m_bpButton_e_down_10->Enable(false);
m_bpButton_z_10->SetIcon("monitor_bed_up_disable");
m_bpButton_z_1->SetIcon("monitor_bed_up_disable");
m_bpButton_z_down_1->SetIcon("monitor_bed_down_disable");
m_bpButton_z_down_10->SetIcon("monitor_bed_down_disable");
m_bpButton_e_10->SetIcon("monitor_extruder_up_disable");
m_bpButton_e_down_10->SetIcon("monitor_extrduer_down_disable");
m_staticText_z_tip->SetForegroundColour(DISCONNECT_TEXT_COL);
m_extruder_label->SetForegroundColour(DISCONNECT_TEXT_COL);
} else {
m_bpButton_xy->Enable();
m_bpButton_z_10->Enable();
m_bpButton_z_1->Enable();
m_bpButton_z_down_1->Enable();
m_bpButton_z_down_10->Enable();
m_bpButton_e_10->Enable();
m_bpButton_e_down_10->Enable();
m_bpButton_z_10->SetIcon("monitor_bed_up");
m_bpButton_z_1->SetIcon("monitor_bed_up");
m_bpButton_z_down_1->SetIcon("monitor_bed_down");
m_bpButton_z_down_10->SetIcon("monitor_bed_down");
m_bpButton_e_10->SetIcon("monitor_extruder_up");
m_bpButton_e_down_10->SetIcon("monitor_extrduer_down");
m_staticText_z_tip->SetForegroundColour(TEXT_LIGHT_FONT_COL);
m_extruder_label->SetForegroundColour(TEXT_LIGHT_FONT_COL);
}
if (!temp_area) {
m_tempCtrl_nozzle->Enable(false);
m_tempCtrl_nozzle_deputy->Enable(false);
m_tempCtrl_bed->Enable(false);
m_tempCtrl_chamber->Enable(false);
m_switch_speed->Enable(false);
m_switch_speed->SetValue(false);
m_switch_lamp->Enable(false);
/*m_switch_nozzle_fan->Enable(false);
m_switch_printing_fan->Enable(false);
m_switch_cham_fan->Enable(false);*/
m_switch_fan->Enable(false);
} else {
m_tempCtrl_nozzle->Enable();
m_tempCtrl_nozzle_deputy->Enable();
m_tempCtrl_bed->Enable();
m_tempCtrl_chamber->Enable();
m_switch_speed->Enable();
m_switch_speed->SetValue(true);
m_switch_lamp->Enable();
/*m_switch_nozzle_fan->Enable();
m_switch_printing_fan->Enable();
m_switch_cham_fan->Enable();*/
m_switch_fan->Enable();
}
}
void StatusPanel::update_temp_ctrl(MachineObject *obj)
{
if (!obj) return;
DevBed* bed = obj->GetBed();
int bed_cur_temp = bed->GetBedTemp();
int bed_target_temp = bed->GetBedTempTarget();
m_tempCtrl_bed->SetCurrTemp((int) bed_cur_temp);
auto limit = obj->get_bed_temperature_limit();
if (obj->bed_temp_range.size() > 1) {
limit = obj->bed_temp_range[1];
}
m_tempCtrl_bed->SetMaxTemp(limit);
if (obj->nozzle_temp_range.size() >= 2) {
m_tempCtrl_nozzle->SetMinTemp(obj->nozzle_temp_range[0]);
m_tempCtrl_nozzle->SetMaxTemp(obj->nozzle_temp_range[1]);
m_tempCtrl_nozzle_deputy->SetMinTemp(obj->nozzle_temp_range[0]);
m_tempCtrl_nozzle_deputy->SetMaxTemp(obj->nozzle_temp_range[1]);
}
// update temprature if not input temp target
if (m_temp_bed_timeout > 0) {
m_temp_bed_timeout--;
} else {
if (!bed_temp_input) { m_tempCtrl_bed->SetTagTemp((int) bed_target_temp); }
}
if ((bed_target_temp - bed_cur_temp) >= TEMP_THRESHOLD_VAL) {
m_tempCtrl_bed->SetIconActive();
} else {
m_tempCtrl_bed->SetIconNormal();
}
bool to_update_layout = false;
int nozzle_num = obj->GetExtderSystem()->GetTotalExtderCount();
if (nozzle_num == 1)
{
m_tempCtrl_nozzle->SetCurrTemp(obj->GetExtderSystem()->GetNozzleTempCurrent(MAIN_EXTRUDER_ID));
m_tempCtrl_nozzle->SetCurrType(TEMP_OF_NORMAL_TYPE);
m_tempCtrl_nozzle_deputy->SetCurrType(TEMP_OF_NORMAL_TYPE);
m_tempCtrl_nozzle_deputy->SetLabel(TEMP_BLANK_STR);
m_tempCtrl_nozzle_deputy->Hide();
if (m_tempCtrl_nozzle->GetMinSize() != TEMP_CTRL_MIN_SIZE_ALIGN_ONE_ICON)
{
to_update_layout = true;
m_tempCtrl_nozzle->SetMinSize(TEMP_CTRL_MIN_SIZE_ALIGN_ONE_ICON);
}
}
else if (nozzle_num == 2)
{
m_tempCtrl_nozzle->SetCurrType(TEMP_OF_MAIN_NOZZLE_TYPE);
m_tempCtrl_nozzle->SetCurrTemp(obj->GetExtderSystem()->GetNozzleTempCurrent(MAIN_EXTRUDER_ID));
m_tempCtrl_nozzle->Show();
m_tempCtrl_nozzle_deputy->SetCurrType(TEMP_OF_DEPUTY_NOZZLE_TYPE);
m_tempCtrl_nozzle_deputy->SetCurrTemp(obj->GetExtderSystem()->GetNozzleTempCurrent(DEPUTY_EXTRUDER_ID));
m_tempCtrl_nozzle_deputy->Show();
if (m_tempCtrl_nozzle->GetMinSize() != TEMP_CTRL_MIN_SIZE_ALIGN_TWO_ICON)
{
to_update_layout = true;
m_tempCtrl_nozzle->SetMinSize(TEMP_CTRL_MIN_SIZE_ALIGN_TWO_ICON);
}
}
if (m_temp_nozzle_timeout > 0) {
m_temp_nozzle_timeout--;
} else {
if (!nozzle_temp_input) {
auto main_extder = obj->GetExtderSystem()->GetExtderById(MAIN_EXTRUDER_ID);
if (main_extder)
{
m_tempCtrl_nozzle->SetTagTemp(main_extder->GetTargetTemp());
m_tempCtrl_nozzle->SetCurrTemp((int)main_extder->GetCurrentTemp());
if (main_extder->GetTargetTemp() - main_extder->GetCurrentTemp() > TEMP_THRESHOLD_VAL)
{
m_tempCtrl_nozzle->SetIconActive();
}
else
{
m_tempCtrl_nozzle->SetIconNormal();
}
}
}
}
if (m_temp_nozzle_deputy_timeout > 0) {
m_temp_nozzle_deputy_timeout--;
}
else {
if (!nozzle_temp_input && nozzle_num >= 2) {
auto deputy_extder = obj->GetExtderSystem()->GetExtderById(DEPUTY_EXTRUDER_ID);
if (deputy_extder)
{
m_tempCtrl_nozzle_deputy->SetTagTemp(deputy_extder->GetTargetTemp());
m_tempCtrl_nozzle_deputy->SetCurrTemp((int)deputy_extder->GetCurrentTemp());
if (deputy_extder->GetTargetTemp() - deputy_extder->GetCurrentTemp() > TEMP_THRESHOLD_VAL)
{
m_tempCtrl_nozzle_deputy->SetIconActive();
}
else
{
m_tempCtrl_nozzle_deputy->SetIconNormal();
}
}
}
}
// support current temp for chamber
if (obj->get_printer_series() == PrinterSeries::SERIES_X1)
{
m_tempCtrl_chamber->SetCurrTemp(obj->chamber_temp);
}
else
{
m_tempCtrl_chamber->SetCurrTemp(TEMP_BLANK_STR);
}
// support edit chamber temp
DevConfig* config = obj->GetConfig();
if (config->SupportChamberEdit())
{
m_tempCtrl_chamber->SetReadOnly(false);
m_tempCtrl_chamber->Enable();
m_tempCtrl_chamber->SetMinTemp(config->GetChamberTempEditMin());
m_tempCtrl_chamber->SetMaxTemp(config->GetChamberTempEditMax());
m_tempCtrl_chamber->AddTemp(0); // zero is default temp
wxCursor cursor(wxCURSOR_IBEAM);
m_tempCtrl_chamber->GetTextCtrl()->SetCursor(cursor);
if (m_temp_chamber_timeout > 0)
{
m_temp_chamber_timeout--;
}
else
{
/*update temprature if not input temp target*/
if (!cham_temp_input) { m_tempCtrl_chamber->SetTagTemp(obj->chamber_temp_target); }
}
}
else
{
m_tempCtrl_chamber->SetReadOnly(true);
m_tempCtrl_chamber->SetTagTemp(TEMP_BLANK_STR);
wxCursor cursor(wxCURSOR_ARROW);
m_tempCtrl_chamber->GetTextCtrl()->SetCursor(cursor);
}
if ((obj->chamber_temp_target - obj->chamber_temp) >= TEMP_THRESHOLD_VAL) {
m_tempCtrl_chamber->SetIconActive();
}
else {
m_tempCtrl_chamber->SetIconNormal();
}
if (to_update_layout)
{
this->Layout();
}
}
void StatusPanel::update_misc_ctrl(MachineObject *obj)
{
auto get_extder_shown_state = [](bool ext_has_filament) -> ExtruderState
{
// no data to distinguish ExtruderState::UNLOAD or LOAD, use LOAD png as default
return ext_has_filament ? ExtruderState::FILLED_LOAD : ExtruderState::EMPTY_LOAD;
};
if (!obj) return;
/*extder*/
auto extder_system = obj->GetExtderSystem();
m_nozzle_num = extder_system->GetTotalExtderCount();
int select_index = m_nozzle_num - 1;
if (m_nozzle_num >= 2) {
m_extruder_book->SetSelection(m_nozzle_num);
/*style*/
m_nozzle_btn_panel->Show();
m_extruderImage[select_index]->setExtruderCount(m_nozzle_num);
if (obj->GetExtderSystem()->GetTotalExtderSize() > 1)
{
m_extruderImage[select_index]->update(get_extder_shown_state(obj->GetExtderSystem()->HasFilamentInExt(0)),
get_extder_shown_state(obj->GetExtderSystem()->HasFilamentInExt(1)));
}
/*current*/
/*update when extder position changed or the machine changed*/
if (obj->GetExtderSystem()->GetCurrentExtderId() == 0xf)
{
m_extruderImage[select_index]->setExtruderUsed("");
m_nozzle_btn_panel->updateState("");
}
else if (obj->GetExtderSystem()->GetCurrentExtderId() == MAIN_EXTRUDER_ID)
{
m_extruderImage[select_index]->setExtruderUsed("right");
m_nozzle_btn_panel->updateState("right");
}
else if (obj->GetExtderSystem()->GetCurrentExtderId() == DEPUTY_EXTRUDER_ID)
{
m_extruderImage[select_index]->setExtruderUsed("left");
m_nozzle_btn_panel->updateState("left");
}
m_nozzle_btn_panel->SetClientData(obj);
/*enable status*/
/* Can do switch while printing pause STUDIO-9789*/
if ((obj->is_in_printing() && !obj->is_in_printing_pause()) ||
obj->ams_status_main == AMS_STATUS_MAIN_FILAMENT_CHANGE ||
obj->targ_nozzle_id_from_pc != INVALID_EXTRUDER_ID)
{
m_nozzle_btn_panel->Disable();
}
else
{
m_nozzle_btn_panel->Enable();
}
} else {
m_nozzle_btn_panel->Hide();
m_extruder_book->SetSelection(m_nozzle_num);
m_extruderImage[select_index]->setExtruderCount(m_nozzle_num);
if (extder_system->GetTotalExtderSize() > 0)
{
ExtruderState shown_state = get_extder_shown_state(extder_system->HasFilamentInExt(0));
m_extruderImage[select_index]->update(shown_state);
}
}
/*switch extder*/
m_extruder_switching_status->updateBy(obj);
m_extruder_label->Show(!m_extruder_switching_status->has_content_shown());/*hide the label if there are shown infos from m_extruder_switching_status*/
/*other*/
if (obj->is_core_xy()) {
m_staticText_z_tip->SetLabel(_L("Bed"));
} else {
m_staticText_z_tip->SetLabel("Z");
}
// update extruder icon
update_extruder_status(obj);
if (obj->is_fdm_type()) {
if (!m_fan_panel->IsShown())
m_fan_panel->Show();
bool is_suppt_part_fun = true;
bool is_suppt_aux_fun = obj->GetFan()->GetSupportAuxFanData();
bool is_suppt_cham_fun = obj->GetFan()->GetSupportChamberFan();
if (m_fan_control_popup) { m_fan_control_popup->update_fan_data(obj); }
} else {
if (m_fan_panel->IsShown()) {
m_fan_panel->Hide();
}
if (m_fan_control_popup && m_fan_control_popup->IsShown())
m_fan_control_popup->Hide();
}
obj->is_series_o() ? m_switch_fan->UseTextAirCondition() : m_switch_fan->UseTextFan();
//update cham fan
/*other*/
bool light_on = obj->GetLamp()->IsChamberLightOn();
BOOST_LOG_TRIVIAL(trace) << "light: " << (light_on ? "on" : "off");
if (m_switch_lamp_timeout > 0)
m_switch_lamp_timeout--;
else {
m_switch_lamp->SetValue(light_on);
/*wxString label = light_on ? "On" : "Off";
m_switch_lamp->SetLabels(label, label);*/
}
if (speed_lvl_timeout > 0)
speed_lvl_timeout--;
else {
// update speed
this->speed_lvl = obj->GetPrintingSpeedLevel();
wxString text_speed = wxString::Format("%d%%", obj->printing_speed_mag);
m_switch_speed->SetLabels(text_speed, text_speed);
}
}
void StatusPanel::update_extruder_status(MachineObject* obj)
{
if (!obj) return;
}
void StatusPanel::update_ams(MachineObject *obj)
{
// update obj in sub dlg
if (m_ams_setting_dlg && m_ams_setting_dlg->IsShown()) {
m_ams_setting_dlg->UpdateByObj(obj);
}
if (m_filament_setting_dlg) { m_filament_setting_dlg->obj = obj; }
if (obj && (obj->last_cali_version != obj->cali_version) && (obj->is_lan_mode_printer() || obj->is_security_control_ready())) {
obj->last_cali_version = obj->cali_version;
PACalibExtruderInfo cali_info;
cali_info.nozzle_diameter = obj->GetExtderSystem()->GetNozzleDiameter(0);
cali_info.use_extruder_id = false;
cali_info.use_nozzle_volume_type = false;
CalibUtils::emit_get_PA_calib_infos(cali_info);
}
bool is_support_virtual_tray = obj->ams_support_virtual_tray;
bool is_support_filament_backup = obj->is_support_filament_backup;
if (obj && (obj->is_lan_mode_printer() || obj->is_security_control_ready())) {
obj->check_ams_filament_valid();
}
AMSModel ams_mode = AMSModel::GENERIC_AMS;
if ((obj->is_enable_np || obj->is_enable_ams_np) && obj->GetFilaSystem()->GetAmsList().size() > 0) {
ams_mode = AMSModel(obj->GetFilaSystem()->GetAmsList().begin()->second->GetAmsType());
} else if (obj->get_printer_ams_type() == "f1") {
ams_mode = AMSModel::AMS_LITE; // STUDIO-14066
}
if (!obj || !obj->is_connected()) {
last_tray_exist_bits = -1;
last_ams_exist_bits = -1;
last_tray_is_bbl_bits = -1;
last_read_done_bits = -1;
last_reading_bits = -1;
last_ams_version = -1;
BOOST_LOG_TRIVIAL(trace) << "machine object" << obj->get_dev_name() << " was disconnected, set show_ams_group is false";
m_ams_control->SetAmsModel(AMSModel::EXT_AMS, ams_mode);
show_ams_group(false);
show_filament_load_group(false);
m_ams_control->show_auto_refill(false);
} else {
m_ams_control->SetAmsModel(ams_mode, ams_mode);
m_filament_step->SetAmsModel(ams_mode, ams_mode);
show_ams_group(true);
//show_filament_load_group(true);
if (obj->GetFilaSystem()->GetAmsList().empty() || obj->ams_exist_bits == 0) {
m_ams_control->show_auto_refill(false);
} else {
m_ams_control->show_auto_refill(true);
}
}
//if (is_support_virtual_tray) m_ams_control->update_vams_kn_value(obj->vt_slot[0], obj);
if (m_filament_setting_dlg) m_filament_setting_dlg->update();
std::vector<AMSinfo> ams_info;
const auto& ams_list = obj->GetFilaSystem()->GetAmsList();
for (auto ams = ams_list.begin(); ams != ams_list.end(); ams++) {
AMSinfo info;
info.ams_id = ams->first;
if (ams->second->IsExist() && info.parse_ams_info(obj, ams->second, obj->GetFilaSystem()->IsDetectRemainEnabled(), obj->is_support_ams_humidity)) {
ams_info.push_back(info);
}
}
std::vector<AMSinfo> ext_info;
ext_info.clear();
for (auto slot : obj->vt_slot) {
AMSinfo info;
info.parse_ext_info(obj, slot);
if (ams_mode == AMSModel::AMS_LITE) info.ext_type = AMSModelOriginType::LITE_EXT;
ext_info.push_back(info);
}
// must select a current can
m_ams_control->UpdateAms(obj->get_printer_series_str(), obj->printer_type, ams_info, ext_info, *obj->GetExtderSystem(), obj->get_dev_id(), obj, false);
m_ams_control->UpdateAmsDryControl(obj);
last_tray_exist_bits = obj->tray_exist_bits;
last_ams_exist_bits = obj->ams_exist_bits;
last_tray_is_bbl_bits = obj->tray_is_bbl_bits;
last_read_done_bits = obj->tray_read_done_bits;
last_reading_bits = obj->tray_reading_bits;
last_ams_version = obj->ams_version;
std::string curr_ams_id = m_ams_control->GetCurentAms();
std::string curr_can_id = m_ams_control->GetCurrentCan(curr_ams_id);
bool is_vt_tray = false;
if (obj->GetExtderSystem()->GetCurrentAmsId() == std::to_string(VIRTUAL_TRAY_MAIN_ID)) is_vt_tray = true;
// set segment 1, 2
//if (!obj->is_enable_np) {
// if (obj->m_tray_now == std::to_string(255) || obj->m_tray_now == std::to_string(254)) {
// m_ams_control->SetAmsStep(obj->m_extder_data.extders[MAIN_NOZZLE_ID].snow.ams_id, obj->m_extder_data.extders[MAIN_NOZZLE_ID].snow.slot_id, AMSPassRoadType::AMS_ROAD_TYPE_UNLOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_NONE);
// } else {
// /*if (obj->m_tray_now != "255" && obj->is_filament_at_extruder() && !obj->m_tray_id.empty()) {
// m_ams_control->SetAmsStep(obj->m_extder_data.extders[MAIN_NOZZLE_ID].snow.ams_id, obj->m_extder_data.extders[MAIN_NOZZLE_ID].snow.slot_id,
// AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP2);
// } else if (obj->m_tray_now != "255") {
// m_ams_control->SetAmsStep(obj->m_extder_data.extders[MAIN_NOZZLE_ID].snow.ams_id, obj->m_extder_data.extders[MAIN_NOZZLE_ID].snow.slot_id,
// AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP1);
// } else {
// m_ams_control->SetAmsStep(obj->m_extder_data.extders[MAIN_NOZZLE_ID].snow.ams_id, obj->m_extder_data.extders[MAIN_NOZZLE_ID].snow.slot_id,
// AMSPassRoadType::AMS_ROAD_TYPE_UNLOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_NONE);
// }*/
// if () {
// }
// }
// m_ams_control->SetExtruder(obj->is_filament_at_extruder(), obj->m_extder_data.extders[MAIN_NOZZLE_ID].snow.ams_id, obj->m_extder_data.extders[MAIN_NOZZLE_ID].snow.slot_id);
//} else {
/*right*/
if (obj->GetExtderSystem()->GetTotalExtderCount() > 0) {
auto ext = obj->GetExtderSystem()->GetExtderById(MAIN_EXTRUDER_ID);
if (ext->HasFilamentInExt()) {
if (ext->GetSlotNow().ams_id == std::to_string(VIRTUAL_TRAY_MAIN_ID) || ext->GetSlotNow().ams_id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) {
m_ams_control->SetAmsStep(ext->GetSlotNow().ams_id, "0", AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP3);
} else {
m_ams_control->SetAmsStep(ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id, AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP2);
}
} else {
m_ams_control->SetAmsStep(ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id, AMSPassRoadType::AMS_ROAD_TYPE_UNLOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_NONE);
}
m_ams_control->SetExtruder(ext->HasFilamentInExt(), MAIN_EXTRUDER_ID, ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id);
}
/*left*/
if (obj->GetExtderSystem()->GetTotalExtderCount() > 1) {
auto ext = obj->GetExtderSystem()->GetExtderById(DEPUTY_EXTRUDER_ID);
if (ext->HasFilamentInExt()) {
if (ext->GetSlotNow().ams_id == std::to_string(VIRTUAL_TRAY_MAIN_ID) || ext->GetSlotNow().ams_id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) {
m_ams_control->SetAmsStep(ext->GetSlotNow().ams_id, "0", AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP3);
} else {
m_ams_control->SetAmsStep(ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id, AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP2);
}
} else {
m_ams_control->SetAmsStep(ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id, AMSPassRoadType::AMS_ROAD_TYPE_UNLOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_NONE);
}
m_ams_control->SetExtruder(ext->HasFilamentInExt(), DEPUTY_EXTRUDER_ID, ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id);
}
update_filament_loading_panel(obj);
const auto& amslist = obj->GetFilaSystem()->GetAmsList();
for (auto ams_it = amslist.begin(); ams_it != amslist.end(); ams_it++) {
std::string ams_id = ams_it->first;
try {
int ams_id_int = atoi(ams_id.c_str());
for (auto tray_it = ams_it->second->GetTrays().begin(); tray_it != ams_it->second->GetTrays().end(); tray_it++) {
std::string tray_id = tray_it->first;
int tray_id_int = atoi(tray_id.c_str());
// new protocol
if (ams_id_int < 128) {
if (ams_it->second->IsAmsLiteMixed()) {
// Mixed AMS-Lite (A2L / N9) RFID-reading bits occupy positions 24..27.
if ((obj->tray_reading_bits & (1 << (AMS_LITE_MIXED_TRAY_INDEX_OFFSET + tray_id_int))) != 0) {
m_ams_control->PlayRridLoading(ams_id, tray_id);
} else {
m_ams_control->StopRridLoading(ams_id, tray_id);
}
} else if ((obj->tray_reading_bits & (1 << (ams_id_int * 4 + tray_id_int))) != 0) {
m_ams_control->PlayRridLoading(ams_id, tray_id);
} else {
m_ams_control->StopRridLoading(ams_id, tray_id);
}
} else {
int check_flag = (1 << (16 + ams_id_int - 128));
if ((obj->tray_reading_bits & check_flag) != 0) {
m_ams_control->PlayRridLoading(ams_id, tray_id);
} else {
m_ams_control->StopRridLoading(ams_id, tray_id);
}
}
}
} catch (...) {}
}
update_ams_control_state(curr_ams_id, curr_can_id);
}
void StatusPanel::update_ams_control_state(std::string ams_id, std::string slot_id)
{
wxString load_error_info, unload_error_info;
if (obj->is_in_printing() && !obj->can_resume()) {
load_error_info = _L("The printer is busy with another print job.");
unload_error_info = _L("The printer is busy with another print job.");
} else if (obj->can_resume() && !devPrinterUtil::IsVirtualSlot(ams_id)) {
load_error_info = _L("When printing is paused, filament loading and unloading are only supported for external slots.");
unload_error_info = _L("When printing is paused, filament loading and unloading are only supported for external slots.");
} else {
/*switch now*/
bool in_switch_filament = false;
if (obj->is_enable_np) {
if (obj->GetExtderSystem()->IsBusyLoading()) { in_switch_filament = true; }
} else if (obj->ams_status_main == AMS_STATUS_MAIN_FILAMENT_CHANGE) {
in_switch_filament = true;
}
if (in_switch_filament) {
load_error_info = _L("Current extruder is busy changing filament.");
unload_error_info = _L("Current extruder is busy changing filament.");
}
if (ams_id.empty() || slot_id.empty()) {
load_error_info = _L("Choose an AMS slot then press \"Load\" or \"Unload\" button to automatically load or unload filament.");
unload_error_info = _L("Choose an AMS slot then press \"Load\" or \"Unload\" button to automatically load or unload filament.");
} else if (obj->GetFilaSwitch()->IsInstalled() && devPrinterUtil::IsVirtualSlot(ams_id)) {
// Orca: with a Filament Track Switch installed the external spool cannot be routed, so both actions are blocked.
load_error_info = _L("\"Load\" or \"Unload\" is not supported for external spool while using Filament Track Switch.");
unload_error_info = load_error_info;
} else if (obj->GetFilaSwitch()->IsInstalled() && !obj->GetFilaSwitch()->IsReady()) {
// Orca: an un-calibrated Filament Track Switch cannot route filament to either extruder, so block both actions.
load_error_info = _L("The Filament Track Switch has not been setup. Please setup on printer.");
unload_error_info = load_error_info;
} else if (ams_id == std::to_string(VIRTUAL_TRAY_MAIN_ID) || ams_id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) {
for (auto ext : obj->GetExtderSystem()->GetExtruders()) {
if (ext.GetSlotNow().ams_id == ams_id && ext.GetSlotNow().slot_id == slot_id)
{
load_error_info = _L("Current slot has already been loaded.");
}
}
} else {
for (auto ext : obj->GetExtderSystem()->GetExtruders()) {
// Orca: with a Filament Track Switch installed a slot is not bound to a single extruder, so skip the "already loaded" identity check.
if (obj->GetFilaSwitch()->IsInstalled()) { continue; }
if (ext.GetSlotNow().ams_id == ams_id && ext.GetSlotNow().slot_id == slot_id)
{
load_error_info = _L("Current slot has already been loaded.");
}
}
/*empty*/
auto ams_item = obj->GetFilaSystem()->GetAmsById(ams_id);
if (!ams_item)
{
load_error_info = _L("Choose an AMS slot then press \"Load\" or \"Unload\" button to automatically load or unload filament.");
}
else
{
auto tray_item = ams_item->GetTray(slot_id);
if (!tray_item)
{
load_error_info = _L("Choose an AMS slot then press \"Load\" or \"Unload\" button to automatically load or unload filament.");
}
else if (!tray_item->is_exists)
{
load_error_info = _L("The selected slot is empty.");
}
}
}
}
m_ams_control->EnableLoadFilamentBtn(load_error_info.empty(), ams_id, slot_id, load_error_info);
m_ams_control->EnableUnLoadFilamentBtn(unload_error_info.empty(), ams_id, slot_id,unload_error_info);
}
void StatusPanel::update_cali(MachineObject *obj)
{
if (!obj) return;
// disable calibration button in 2D
if (!obj->is_fdm_type()) {
m_calibration_btn->SetToolTip(_L("Printer 2D mode does not support 3D calibration"));
m_calibration_btn->SetLabel(_L("Calibration"));
m_calibration_btn->Disable();
return;
} else if (!m_calibration_btn->IsEnabled()) {
m_calibration_btn->SetToolTip(wxEmptyString);
m_calibration_btn->Enable();
}
if (obj->is_calibration_running()) {
m_calibration_btn->SetLabel(_L("Calibrating"));
if (calibration_dlg && calibration_dlg->IsShown()) {
m_calibration_btn->Disable();
} else {
m_calibration_btn->Enable();
}
} else {
// IDLE
m_calibration_btn->SetLabel(_L("Calibration"));
// disable in printing
if (obj->is_in_printing()) {
m_calibration_btn->Disable();
} else {
m_calibration_btn->Enable();
}
}
}
void StatusPanel::update_calib_bitmap() {
m_current_print_mode = PrintingTaskType::NOT_CLEAR; //printing task might be changed when updating.
if (calib_bitmap != nullptr) {
delete calib_bitmap;
calib_bitmap = nullptr;
}
}
void StatusPanel::update_basic_print_data(bool def)
{
if (def) {
if (!obj) return;
if (!obj->slice_info) return;
wxString prediction = wxString::Format("%s", get_bbl_time_dhms(obj->slice_info->prediction));
wxString weight = wxString::Format("%.2fg", obj->slice_info->weight);
m_project_task_panel->show_priting_use_info(true, prediction, weight);
}
else {
m_project_task_panel->show_priting_use_info(false, "0m", "0g");
}
}
void StatusPanel::update_model_info()
{
auto get_subtask_fn = [this](BBLModelTask* subtask) {
CallAfter([this, subtask]() {
if (obj && obj->subtask_id_ == subtask->task_id) {
obj->set_modeltask(subtask);
}
});
};
if (wxGetApp().getAgent() && obj) {
BBLSubTask* curr_task = obj->get_subtask();
if (curr_task) {
BBLModelTask* curr_model_task = obj->get_modeltask();
if (!curr_model_task && !request_model_info_flag) {
curr_model_task = new BBLModelTask();
curr_model_task->task_id = curr_task->task_id;
request_model_info_flag = true;
if (!curr_model_task->task_id.empty() && curr_model_task->task_id.compare("0") != 0) {
wxGetApp().getAgent()->get_subtask(curr_model_task, get_subtask_fn);
}
}
}
}
}
void StatusPanel::update_subtask(MachineObject *obj)
{
if (!obj) return;
if (m_current_print_mode != PRINGINT) {
if (calib_bitmap == nullptr) {
m_calib_mode = get_obj_calibration_mode(obj, m_calib_method, cali_stage);
if (m_calib_mode == CalibMode::Calib_None)
m_current_print_mode = PRINGINT;
// the printing task is calibrattion, not normal printing.
else if (m_calib_mode != CalibMode::Calib_None) {
m_current_print_mode = CALIBRATION;
auto get_bitmap = [](wxString& png_path, int width, int height) {
wxImage image(width, height);
image.LoadFile(png_path, wxBITMAP_TYPE_PNG);
image = image.Scale(width, height, wxIMAGE_QUALITY_NORMAL);
return wxBitmap(image);
};
wxString png_path = "";
int width = m_project_task_panel->get_bitmap_thumbnail()->GetSize().x;
int height = m_project_task_panel->get_bitmap_thumbnail()->GetSize().y;
if (m_calib_method == CALI_METHOD_AUTO || m_calib_method == CalibrationMethod::CALI_METHOD_NEW_AUTO) {
std::string image_name = obj->get_auto_pa_cali_thumbnail_img_str();
if (m_calib_mode == CalibMode::Calib_PA_Line) {
if (obj->is_multi_extruders()) {
int cur_ext_id = obj->GetExtderSystem()->GetCurrentExtderId();
if (cur_ext_id == 0) {
image_name += "_right";
}
else {
image_name += "_left";
}
}
png_path = (boost::format("%1%/images/%2%.png") % resources_dir() % image_name).str();
}
else if (m_calib_mode == CalibMode::Calib_Flow_Rate) {
png_path = (boost::format("%1%/images/flow_rate_calibration_auto.png") % resources_dir()).str();
}
}
else if (m_calib_method == CALI_METHOD_MANUAL) {
if (m_calib_mode== CalibMode::Calib_PA_Line) {
if (cali_stage == 0) { // Line mode
png_path = (boost::format("%1%/images/fd_calibration_manual.png") % resources_dir()).str();
}
else if (cali_stage == 1) { // Pattern mode
png_path = (boost::format("%1%/images/fd_pattern_manual_device.png") % resources_dir()).str();
}
}
}
if (png_path != "") {
calib_bitmap = new wxBitmap;
*calib_bitmap = get_bitmap(png_path, width, height);
}
}
}
if (calib_bitmap != nullptr)
m_project_task_panel->set_thumbnail_img(*calib_bitmap, "");
}
m_project_task_panel->show_layers_num(obj->is_support_layer_num);
update_model_info();
update_partskip_button(obj);
update_printer_parts_options(obj);
if (obj->is_system_printing() || obj->is_in_calibration()) {
reset_printing_values();
} else if (obj->is_in_printing() || obj->print_status == "FINISH") {
update_partskip_subtask(obj);
if (obj->is_in_prepare() || obj->print_status == "SLICING") {
m_project_task_panel->market_scoring_hide();
m_project_task_panel->get_request_failed_panel()->Hide();
m_project_task_panel->enable_partskip_button(nullptr, false);
m_project_task_panel->enable_abort_button(false);
m_project_task_panel->enable_pause_resume_button(false, "pause_disable");
wxString prepare_text;
bool show_percent = true;
if (obj->is_in_prepare()) {
prepare_text = wxString::Format(_L("Downloading..."));
}
else if (obj->print_status == "SLICING") {
if (obj->queue_number <= 0) {
prepare_text = wxString::Format(_L("Cloud Slicing..."));
} else {
prepare_text = wxString::Format(_L("In Cloud Slicing Queue, there are %s tasks ahead of you."), std::to_string(obj->queue_number));
show_percent = false;
}
} else
prepare_text = wxString::Format(_L("Downloading..."));
if (obj->gcode_file_prepare_percent >= 0 && obj->gcode_file_prepare_percent <= 100 && show_percent)
prepare_text += wxString::Format("(%d%%)", obj->gcode_file_prepare_percent);
m_project_task_panel->update_stage_value_with_machine(prepare_text, 0, obj);
m_project_task_panel->update_progress_percent(NA_STR, wxEmptyString);
m_project_task_panel->update_left_time(NA_STR);
m_project_task_panel->update_layers_num(true, wxString::Format(_L("Layer: %s"), NA_STR));
m_project_task_panel->update_subtask_name(wxString::Format("%s", GUI::from_u8(obj->subtask_name)));
if (obj->get_modeltask() && obj->get_modeltask()->design_id > 0) {
m_project_task_panel->show_profile_info(true, wxString::FromUTF8(obj->get_modeltask()->profile_name));
}
else {
m_project_task_panel->show_profile_info(false);
}
update_basic_print_data(false);
} else {
if (obj->can_resume()) {
m_project_task_panel->enable_pause_resume_button(true, "resume");
} else {
m_project_task_panel->enable_pause_resume_button(true, "pause");
}
m_project_task_panel->enable_partskip_button(obj, true);
// update printing stage
m_project_task_panel->update_left_time(obj->mc_left_time);
if (obj->subtask_) {
m_project_task_panel->update_stage_value_with_machine(obj->get_curr_stage(), obj->subtask_->task_progress, obj);
m_project_task_panel->update_progress_percent(wxString::Format("%d", obj->subtask_->task_progress), "%");
m_project_task_panel->update_layers_num(true, wxString::Format(_L("Layer: %d/%d"), obj->curr_layer, obj->total_layers));
} else {
m_project_task_panel->update_stage_value_with_machine(obj->get_curr_stage(), 0, obj);
m_project_task_panel->update_progress_percent(NA_STR, wxEmptyString);
m_project_task_panel->update_layers_num(true, wxString::Format(_L("Layer: %s"), NA_STR));
}
if (obj->is_printing_finished()) {
obj->update_model_task();
m_project_task_panel->enable_abort_button(false);
m_project_task_panel->enable_partskip_button(nullptr, false);
m_project_task_panel->enable_pause_resume_button(false, "resume_disable");
// is makeworld subtask
if (wxGetApp().has_model_mall() && obj->is_makeworld_subtask()) {
// has model mall rating result
if (obj && obj->rating_info && obj->rating_info->request_successful) {
m_project_task_panel->get_request_failed_panel()->Hide();
BOOST_LOG_TRIVIAL(info) << "model mall result request successful";
// has start count
if (!m_project_task_panel->get_star_count_dirty()) {
if (obj->rating_info->start_count > 0) {
m_project_task_panel->set_star_count(obj->rating_info->start_count);
m_project_task_panel->set_star_count_dirty(true);
BOOST_LOG_TRIVIAL(info) << "Initialize scores";
m_project_task_panel->get_market_scoring_button()->Enable(true);
m_project_task_panel->set_has_reted_text(true);
} else {
m_project_task_panel->set_star_count(0);
m_project_task_panel->set_star_count_dirty(false);
m_project_task_panel->get_market_scoring_button()->Enable(false);
m_project_task_panel->set_has_reted_text(false);
}
}
m_project_task_panel->market_scoring_show();
} else if (obj && obj->rating_info && !obj->rating_info->request_successful) {
BOOST_LOG_TRIVIAL(info) << "model mall result request failed";
if (403 != obj->rating_info->http_code) {
BOOST_LOG_TRIVIAL(info) << "Request need retry";
m_project_task_panel->get_market_retry_buttom()->Enable(!obj->get_model_mall_result_need_retry);
m_project_task_panel->get_request_failed_panel()->Show();
} else {
BOOST_LOG_TRIVIAL(info) << "Request rejected";
}
}
} else {
m_project_task_panel->market_scoring_hide();
}
} else { // model printing is not finished, hide scoring page
m_project_task_panel->enable_abort_button(true);
m_project_task_panel->market_scoring_hide();
m_project_task_panel->get_request_failed_panel()->Hide();
}
}
m_project_task_panel->update_subtask_name(wxString::Format("%s", GUI::from_u8(obj->subtask_name)));
if (obj->get_modeltask() && obj->get_modeltask()->design_id > 0) {
m_project_task_panel->show_profile_info(true, wxString::FromUTF8(obj->get_modeltask()->profile_name));
}
else {
m_project_task_panel->show_profile_info(false);
}
//update thumbnail
if (obj->is_sdcard_printing()) {
update_basic_print_data(false);
update_sdcard_subtask(obj);
} else {
update_basic_print_data(true);
update_cloud_subtask(obj);
}
} else {
reset_printing_values();
}
}
void StatusPanel::update_partskip_subtask(MachineObject *obj){
if (!obj) return;
if (!obj->subtask_) return;
auto partskip_button = m_project_task_panel->get_partskip_button();
if (partskip_button) {
int part_cnt = 0;
if(m_project_task_panel->get_part_skipped_dirty() > 0){
m_project_task_panel->set_part_skipped_dirty(m_project_task_panel->get_part_skipped_dirty() - 1);
part_cnt = m_project_task_panel->get_part_skipped_count();
BOOST_LOG_TRIVIAL(info) << "part skip: stop recv printer dirty data.";
}else{
part_cnt = obj->m_partskip_ids.size();
BOOST_LOG_TRIVIAL(info) << "part skip: recv printer normal data.";
}
if (part_cnt > 0)
partskip_button->SetLabel(wxString::Format("(%d)", part_cnt));
else
partskip_button->SetLabel("");
}
if(m_partskip_dlg && m_partskip_dlg->IsShown()) {
m_partskip_dlg->UpdatePartsStateFromPrinter(obj);
}
}
void StatusPanel::update_cloud_subtask(MachineObject *obj)
{
if (!obj) return;
if (!obj->subtask_) return;
if (is_task_changed(obj)) {
obj->set_modeltask(nullptr);
obj->free_slice_info();
reset_printing_values();
BOOST_LOG_TRIVIAL(info) << "monitor: change to sub task id = " << obj->subtask_->task_id;
if (web_request.IsOk() && web_request.GetState() == wxWebRequest::State_Active) {
BOOST_LOG_TRIVIAL(info) << "web_request: cancelled";
web_request.Cancel();
}
m_start_loading_thumbnail = true;
}
if (m_start_loading_thumbnail) {
update_calib_bitmap();
if (obj->slice_info) {
m_request_url = wxString(obj->slice_info->thumbnail_url);
load_thumbnail_from_url(m_request_url, obj);
}
}
}
bool StatusPanel::load_thumbnail_from_url(const wxString &url, MachineObject *obj)
{
if (url.IsEmpty())
return false;
wxImage img;
std::map<wxString, wxImage>::iterator it = img_list.find(url);
if (it != img_list.end()) {
if (m_current_print_mode != PrintingTaskType::CALIBRATION ||(m_calib_mode == CalibMode::Calib_Flow_Rate && m_calib_method == CalibrationMethod::CALI_METHOD_MANUAL)) {
img = it->second;
wxImage resize_img = img.Scale(m_project_task_panel->get_bitmap_thumbnail()->GetSize().x, m_project_task_panel->get_bitmap_thumbnail()->GetSize().y);
m_project_task_panel->set_thumbnail_img(resize_img, "");
m_project_task_panel->set_brightness_value(get_brightness_value(resize_img));
}
if (this->obj) {
m_project_task_panel->set_plate_index(obj->m_plate_index);
} else {
m_project_task_panel->set_plate_index(-1);
}
task_thumbnail_state = ThumbnailState::TASK_THUMBNAIL;
BOOST_LOG_TRIVIAL(trace) << "web_request: use cache image";
} else {
m_request_url = url;
web_request = wxWebSession::GetDefault().CreateRequest(this, m_request_url);
BOOST_LOG_TRIVIAL(trace) << "monitor: start request thumbnail, url = " << m_request_url;
web_request.Start();
m_start_loading_thumbnail = false;
}
return true;
}
void StatusPanel::update_sdcard_subtask(MachineObject *obj)
{
if (!obj) return;
const wxString thumbnail_url = wxString(obj->m_agent_thumbnail_url);
if (!thumbnail_url.IsEmpty()) {
if (m_request_url != thumbnail_url || !m_load_sdcard_thumbnail) {
if (web_request.IsOk() && web_request.GetState() == wxWebRequest::State_Active)
web_request.Cancel();
update_calib_bitmap();
m_request_url = thumbnail_url;
load_thumbnail_from_url(thumbnail_url, obj);
m_load_sdcard_thumbnail = true;
}
return;
}
if (!m_load_sdcard_thumbnail || !m_request_url.IsEmpty()) {
update_calib_bitmap();
if (m_current_print_mode != PrintingTaskType::CALIBRATION) {
m_project_task_panel->get_bitmap_thumbnail()->SetBitmap(m_thumbnail_sdcard.bmp());
m_project_task_panel->set_thumbnail_img(m_thumbnail_sdcard.bmp(), m_thumbnail_sdcard.name());
}
task_thumbnail_state = ThumbnailState::SDCARD_THUMBNAIL;
m_load_sdcard_thumbnail = true;
m_request_url.clear();
}
}
void StatusPanel::reset_printing_values()
{
m_project_task_panel->enable_partskip_button(nullptr, false);
m_project_task_panel->enable_pause_resume_button(false, "pause_disable");
m_project_task_panel->enable_abort_button(false);
m_project_task_panel->reset_printing_value();
m_project_task_panel->update_subtask_name(NA_STR);
m_project_task_panel->show_profile_info(false);
// m_project_task_panel->update_stage_value_with_machine(wxEmptyString, 0, obj);
m_project_task_panel->update_stage_value_with_machine(wxEmptyString, 0, obj);
//obj->get_curr_stage()
m_project_task_panel->update_progress_percent(NA_STR, wxEmptyString);
m_project_task_panel->market_scoring_hide();
m_project_task_panel->get_request_failed_panel()->Hide();
update_basic_print_data(false);
m_project_task_panel->update_left_time(NA_STR);
m_project_task_panel->update_layers_num(true, wxString::Format(_L("Layer: %s"), NA_STR));
update_calib_bitmap();
task_thumbnail_state = ThumbnailState::PLACE_HOLDER;
m_start_loading_thumbnail = false;
m_load_sdcard_thumbnail = false;
skip_print_error = 0;
this->Layout();
}
void StatusPanel::on_axis_ctrl_xy(wxCommandEvent &event)
{
if (!obj) return;
//check is at home
static std::unordered_set<int> s_x_ctrl_idxes { 1, 3, 5, 7};
static std::unordered_set<int> s_y_ctrl_idxes{ 0, 2, 4, 6 };
if (s_x_ctrl_idxes.count(event.GetInt()) != 0 && !obj->is_axis_at_home("X"))
{
BOOST_LOG_TRIVIAL(info) << "axis x is not at home";
show_recenter_dialog();
return;
}
else if (s_y_ctrl_idxes.count(event.GetInt()) != 0 && !obj->is_axis_at_home("Y"))
{
BOOST_LOG_TRIVIAL(info) << "axis y is not at home";
show_recenter_dialog();
return;
}
if (event.GetInt() == 0) { obj->command_axis_control("Y", 1.0, 10.0f, 3000); }
else if (event.GetInt() == 1) { obj->command_axis_control("X", 1.0, -10.0f, 3000); }
else if (event.GetInt() == 2) { obj->command_axis_control("Y", 1.0, -10.0f, 3000); }
else if (event.GetInt() == 3) { obj->command_axis_control("X", 1.0, 10.0f, 3000); }
else if (event.GetInt() == 4) { obj->command_axis_control("Y", 1.0, 1.0f, 3000); }
else if (event.GetInt() == 5) { obj->command_axis_control("X", 1.0, -1.0f, 3000); }
else if (event.GetInt() == 6) { obj->command_axis_control("Y", 1.0, -1.0f, 3000); }
else if (event.GetInt() == 7) { obj->command_axis_control("X", 1.0, 1.0f, 3000); }
else if (event.GetInt() == 8) {
if (obj) { obj->command_go_home(); }
}
}
bool StatusPanel::check_axis_z_at_home(MachineObject* obj)
{
if (obj) {
if (!obj->is_axis_at_home("Z")) {
BOOST_LOG_TRIVIAL(info) << "axis z is not at home";
show_recenter_dialog();
return false;
}
return true;
}
return false;
}
void StatusPanel::on_axis_ctrl_z_up_10(wxCommandEvent &event)
{
if (obj) {
obj->command_axis_control("Z", 1.0, -10.0f, 900);
if (!check_axis_z_at_home(obj))
return;
}
}
void StatusPanel::on_axis_ctrl_z_up_1(wxCommandEvent &event)
{
if (obj) {
obj->command_axis_control("Z", 1.0, -1.0f, 900);
if (!check_axis_z_at_home(obj))
return;
}
}
void StatusPanel::on_axis_ctrl_z_down_1(wxCommandEvent &event)
{
if (obj) {
obj->command_axis_control("Z", 1.0, 1.0f, 900);
if (!check_axis_z_at_home(obj))
return;
}
}
void StatusPanel::on_axis_ctrl_z_down_10(wxCommandEvent &event)
{
if (obj) {
obj->command_axis_control("Z", 1.0, 10.0f, 900);
if (!check_axis_z_at_home(obj))
return;
}
}
void StatusPanel::axis_ctrl_e_hint(bool up_down)
{
if (ctrl_e_hint_dlg == nullptr) {
/* ctrl_e_hint_dlg = new SecondaryCheckDialog(this->GetParent(), wxID_ANY, _L("Warning"), SecondaryCheckDialog::VisibleButtons::CONFIRM_AND_CANCEL, wxDefaultPosition,
ctrl_e_hint_dlg->update_text(_L("Please heat the nozzle to above 170\u2103 before loading or unloading filament."));
ctrl_e_hint_dlg->m_show_again_checkbox->Hide();
ctrl_e_hint_dlg->m_button_cancel->Hide();
ctrl_e_hint_dlg->m_staticText_release_note->SetMaxSize(wxSize(FromDIP(360), -1));
ctrl_e_hint_dlg->m_staticText_release_note->SetMinSize(wxSize(FromDIP(360), -1));
ctrl_e_hint_dlg->Fit();*/
ctrl_e_hint_dlg = new MessageDialog(this, _L("Please heat the nozzle to above 170\u2103 before loading or unloading filament."), wxString(_L("Warning")), wxOK | wxCENTER);
}
ctrl_e_hint_dlg->ShowModal();
// ctrl_e_hint_dlg->on_show();
}
void StatusPanel::on_axis_ctrl_e_up_10(wxCommandEvent &event)
{
if (obj) {
auto ext = obj->GetExtderSystem()->GetCurrentExtder();
if (ext && ext->GetCurrentTemp() >= TEMP_THRESHOLD_ALLOW_E_CTRL)
if (obj->is_enable_np) {
obj->command_extruder_control(ext->GetExtId(), -10.0f);
} else {
obj->command_axis_control("E", 1.0, -10.0f, 900);
}
else
axis_ctrl_e_hint(true);
}
}
void StatusPanel::on_axis_ctrl_e_down_10(wxCommandEvent &event)
{
if (obj) {
auto ext = obj->GetExtderSystem()->GetCurrentExtder();
if (ext && ext->GetCurrentTemp() >= TEMP_THRESHOLD_ALLOW_E_CTRL)
if (obj->is_enable_np) {
obj->command_extruder_control(ext->GetExtId(), 10.0f);
} else {
obj->command_axis_control("E", 1.0, 10.0f, 900);
}
else
axis_ctrl_e_hint(false);
}
}
void StatusPanel::on_set_bed_temp()
{
if (!obj) {return;}
wxString str = m_tempCtrl_bed->GetTextCtrl()->GetValue();
try {
long bed_temp;
if (str.ToLong(&bed_temp) && obj) {
set_hold_count(m_temp_bed_timeout);
int limit = obj->get_bed_temperature_limit();
if (obj->bed_temp_range.size() > 1) {
limit = obj->bed_temp_range[1];
}
if (bed_temp >= limit) {
BOOST_LOG_TRIVIAL(info) << "can not set over limit = " << limit << ", set temp = " << bed_temp;
bed_temp = limit;
m_tempCtrl_bed->SetTagTemp(wxString::Format("%d", bed_temp));
m_tempCtrl_bed->Warning(false);
}
obj->command_set_bed(bed_temp);
}
} catch (...) {
;
}
}
void StatusPanel::on_set_nozzle_temp(int nozzle_id)
{
if (!obj) {return;}
try {
long nozzle_temp;
if (nozzle_id == MAIN_EXTRUDER_ID) {
wxString str = m_tempCtrl_nozzle->GetTextCtrl()->GetValue();
if (str.ToLong(&nozzle_temp) && obj) {
set_hold_count(m_temp_nozzle_timeout);
if (nozzle_temp > m_tempCtrl_nozzle->get_max_temp()) {
nozzle_temp = m_tempCtrl_nozzle->get_max_temp();
m_tempCtrl_nozzle->SetTagTemp(wxString::Format("%d", nozzle_temp));
m_tempCtrl_nozzle->Warning(false);
}
if (m_tempCtrl_nozzle->GetCurrType() == TempInputType::TEMP_OF_NORMAL_TYPE) {
obj->command_set_nozzle(nozzle_temp);
} else {
obj->command_set_nozzle_new(MAIN_EXTRUDER_ID, nozzle_temp);
}
}
}
if (nozzle_id == DEPUTY_EXTRUDER_ID) {
wxString str = m_tempCtrl_nozzle_deputy->GetTextCtrl()->GetValue();
if (str.ToLong(&nozzle_temp) && obj) {
set_hold_count(m_temp_nozzle_deputy_timeout);
if (nozzle_temp > m_tempCtrl_nozzle_deputy->get_max_temp()) {
nozzle_temp = m_tempCtrl_nozzle_deputy->get_max_temp();
m_tempCtrl_nozzle_deputy->SetTagTemp(wxString::Format("%d", nozzle_temp));
m_tempCtrl_nozzle_deputy->Warning(false);
}
obj->command_set_nozzle_new(DEPUTY_EXTRUDER_ID, nozzle_temp);
}
}
} catch (...) {
;
}
}
void StatusPanel::on_set_chamber_temp()
{
if (!obj) {return;}
wxString str = m_tempCtrl_chamber->GetTextCtrl()->GetValue();
try {
long chamber_temp;
if (str.ToLong(&chamber_temp) && obj) {
set_hold_count(m_temp_chamber_timeout);
if (chamber_temp > m_tempCtrl_chamber->get_max_temp()) {
chamber_temp = m_tempCtrl_chamber->get_max_temp();
m_tempCtrl_chamber->SetTagTemp(wxString::Format("%d", chamber_temp));
m_tempCtrl_chamber->Warning(false);
}
if(obj->is_in_printing() && obj->GetFan()->GetSupportAirduct() && obj->GetFan()->is_at_cooling_mode())
{
#ifndef __APPLE__
MessageDialog champer_switch_head_dlg(this, _L("Chamber temperature cannot be changed in cooling mode while printing."), wxEmptyString, wxICON_WARNING | wxOK);
#else
wxMessageDialog champer_switch_head_dlg(this, _L("Chamber temperature cannot be changed in cooling mode while printing."), wxEmptyString, wxICON_WARNING | wxOK);
#endif
champer_switch_head_dlg.ShowModal();
return;
}
else if (!obj->GetFan()->is_at_heating_mode() && chamber_temp >= obj->GetConfig()->GetChamberTempSwitchHeat())
{
#ifndef __APPLE__
MessageDialog champer_switch_head_dlg(this, _L("If the chamber temperature exceeds 40\u2103, the system will automatically switch to heating mode. "
"Please confirm whether to switch."), wxEmptyString, wxICON_WARNING | wxOK | wxCANCEL);
#else
/*STUDIO-10386 MessageDialog here may cause block in macOS, use wxMessageDialog*/
wxMessageDialog champer_switch_head_dlg(this, _L("If the chamber temperature exceeds 40\u2103, the system will automatically switch to heating mode. "
"Please confirm whether to switch."), wxEmptyString, wxICON_WARNING | wxOK | wxCANCEL);
#endif
if (champer_switch_head_dlg.ShowModal() != wxID_OK) { return; }
}
obj->command_set_chamber(chamber_temp);
}
}
catch (...) {
;
}
}
void StatusPanel::on_ams_load(SimpleEvent &event)
{
BOOST_LOG_TRIVIAL(info) << "on_ams_load";
on_ams_load_curr();
}
void StatusPanel::update_load_with_temp()
{
if (!obj->is_filament_at_extruder()) {
m_is_load_with_temp = true;
}
else {
m_is_load_with_temp = false;
}
}
void StatusPanel::on_ams_load_curr()
{
if (obj) {
std::string curr_ams_id = m_ams_control->GetCurentAms();
std::string curr_can_id = m_ams_control->GetCurrentCan(curr_ams_id);
std::optional<int> extruder_id = std::nullopt;
if (obj->GetFilaSwitch() && obj->GetFilaSwitch()->IsInstalled()) {
if (!obj->GetFilaSwitch()->IsReady()) {
MessageDialog msg_dlg(nullptr, _L("The Filament Track Switch has not been setup. Please setup on printer."), wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
return;
}
// Filament Track Switch is calibrated: the load can go to either extruder, so ask the
// user which. Record each extruder's currently-loaded slot so the dialog can grey out a
// side that already holds this filament.
std::vector<std::pair<std::string, std::string>> extruderSlots(2, {"", ""});
if (auto ext = obj->GetExtderSystem()->GetExtderById(MAIN_EXTRUDER_ID); ext.has_value())
{
if (ext->HasFilamentInExt())
{
extruderSlots[MAIN_EXTRUDER_ID] = {ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id};
}
}
if (auto ext = obj->GetExtderSystem()->GetExtderById(DEPUTY_EXTRUDER_ID); ext.has_value())
{
if (ext->HasFilamentInExt())
{
extruderSlots[DEPUTY_EXTRUDER_ID] = {ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id};
}
}
FeedDirectionDialog dialog(nullptr, 2, obj->printer_type);
dialog.SetExtruderMapping(obj, curr_ams_id, curr_can_id, extruderSlots);
auto rtn = dialog.ShowModal();
if (rtn != wxID_OK)
{
return;
}
extruder_id = dialog.GetExtruderID();
}
update_load_with_temp();
//virtual tray
if (curr_ams_id.compare(std::to_string(VIRTUAL_TRAY_MAIN_ID)) == 0 ||
curr_ams_id.compare(std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) == 0)
{
int vt_slot_idx = 0;
if (curr_ams_id.compare(std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) == 0)
{
vt_slot_idx = 1;
}
int old_temp = -1;
int new_temp = -1;
DevAmsTray* curr_tray = &obj->vt_slot[vt_slot_idx];
if (!curr_tray) return;
try {
if (!curr_tray->nozzle_temp_max.empty() && !curr_tray->nozzle_temp_min.empty())
old_temp = (atoi(curr_tray->nozzle_temp_min.c_str()) + atoi(curr_tray->nozzle_temp_max.c_str())) / 2;
if (!curr_tray->nozzle_temp_max.empty() && !curr_tray->nozzle_temp_min.empty())
new_temp = (atoi(curr_tray->nozzle_temp_min.c_str()) + atoi(curr_tray->nozzle_temp_max.c_str())) / 2;
}
catch (...) {
;
}
if (obj->is_enable_np || obj->is_enable_ams_np) {
try {
if (!curr_ams_id.empty() && !curr_can_id.empty()) {
obj->command_ams_change_filament(true, curr_ams_id, "0", old_temp, new_temp, extruder_id);
}
} catch (...) {}
} else {
obj->command_ams_change_filament(true, "254", "0", old_temp, new_temp, extruder_id);
}
}
std::map<std::string, DevAms*>::iterator it = obj->GetFilaSystem()->GetAmsList().find(curr_ams_id);
if (it == obj->GetFilaSystem()->GetAmsList().end()) {
BOOST_LOG_TRIVIAL(trace) << "ams: find " << curr_ams_id << " failed";
return;
}
auto tray_it = it->second->GetTrays().find(curr_can_id);
if (tray_it == it->second->GetTrays().end()) {
BOOST_LOG_TRIVIAL(trace) << "ams: find " << curr_can_id << " failed";
return;
}
DevAmsTray* curr_tray = obj->get_curr_tray();
DevAmsTray* targ_tray = obj->get_ams_tray(curr_ams_id, curr_can_id);
int old_temp = -1;
int new_temp = -1;
if (curr_tray && targ_tray) {
try {
if (!curr_tray->nozzle_temp_max.empty() && !curr_tray->nozzle_temp_min.empty())
old_temp = (atoi(curr_tray->nozzle_temp_min.c_str()) + atoi(curr_tray->nozzle_temp_max.c_str())) / 2;
if (!targ_tray->nozzle_temp_max.empty() && !targ_tray->nozzle_temp_min.empty())
new_temp = (atoi(targ_tray->nozzle_temp_min.c_str()) + atoi(targ_tray->nozzle_temp_max.c_str())) / 2;
} catch (...) {
;
}
}
int tray_index = atoi(curr_ams_id.c_str()) * 4 + atoi(tray_it->second->id.c_str());
if (obj->is_enable_np) {
try {
if (!curr_ams_id.empty() && !curr_can_id.empty()) {
obj->command_ams_change_filament(true, curr_ams_id, curr_can_id, old_temp, new_temp, extruder_id);
}
}
catch (...){}
} else {
obj->command_ams_change_filament(true, curr_ams_id, curr_can_id, old_temp, new_temp, extruder_id);
}
}
}
void StatusPanel::on_ams_load_vams(wxCommandEvent& event) {
BOOST_LOG_TRIVIAL(info) << "on_ams_load_vams_tray";
m_ams_control->SwitchAms(std::to_string(VIRTUAL_TRAY_MAIN_ID));
on_ams_load_curr();
}
void StatusPanel::on_ams_switch(SimpleEvent &event)
{
if(obj){
/*right*/
if (obj->GetExtderSystem()->GetTotalExtderCount() > 0) {
auto ext = obj->GetExtderSystem()->GetExtderById(MAIN_EXTRUDER_ID);
if (ext->HasFilamentInExt()) {
if (ext->GetSlotNow().ams_id == std::to_string(VIRTUAL_TRAY_MAIN_ID) || ext->GetSlotNow().ams_id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) {
m_ams_control->SetAmsStep(ext->GetSlotNow().ams_id, "0", AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP3);
} else {
m_ams_control->SetAmsStep(ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id, AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP2);
}
} else {
m_ams_control->SetAmsStep(ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id, AMSPassRoadType::AMS_ROAD_TYPE_UNLOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_NONE);
}
m_ams_control->SetExtruder(ext->HasFilamentInExt(), MAIN_EXTRUDER_ID, ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id);
}
/*left*/
if (obj->GetExtderSystem()->GetTotalExtderCount() > 1) {
auto ext = obj->GetExtderSystem()->GetExtruders()[DEPUTY_EXTRUDER_ID];
if (ext.HasFilamentInExt()) {
if (ext.GetSlotNow().ams_id == std::to_string(VIRTUAL_TRAY_MAIN_ID) || ext.GetSlotNow().ams_id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) {
m_ams_control->SetAmsStep(ext.GetSlotNow().ams_id, "0", AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP3);
} else {
m_ams_control->SetAmsStep(ext.GetSlotNow().ams_id, ext.GetSlotNow().slot_id, AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP2);
}
} else {
m_ams_control->SetAmsStep(ext.GetSlotNow().ams_id, ext.GetSlotNow().slot_id, AMSPassRoadType::AMS_ROAD_TYPE_UNLOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_NONE);
}
m_ams_control->SetExtruder(ext.HasFilamentInExt(), DEPUTY_EXTRUDER_ID, ext.GetSlotNow().ams_id, ext.GetSlotNow().slot_id);
}
}
}
void StatusPanel::on_ams_unload(SimpleEvent &event)
{
if (obj) {
std::string curr_ams_id = m_ams_control->GetCurentAms();
std::string curr_can_id = m_ams_control->GetCurrentCan(curr_ams_id);
if (obj->is_enable_np) {
try {
for (auto ext : obj->GetExtderSystem()->GetExtruders()) {
if (ext.GetSlotNow().ams_id == curr_ams_id && ext.GetSlotNow().slot_id == curr_can_id) { obj->command_ams_change_filament(false, curr_ams_id, "255"); }
}
} catch (...) {}
} else {
obj->command_ams_change_filament(false, curr_ams_id, "255");
}
}
}
void StatusPanel::on_ams_filament_backup(SimpleEvent& event)
{
if (obj) {
AmsReplaceMaterialDialog* m_replace_material_popup = new AmsReplaceMaterialDialog(this);
m_replace_material_popup->update_machine_obj(obj);
m_replace_material_popup->ShowModal();
}
}
void StatusPanel::on_ams_setting_click(SimpleEvent &event)
{
if (obj) {
if (!m_ams_setting_dlg) {
m_ams_setting_dlg = new AMSSetting((wxWindow*)this, wxID_ANY);
}
m_ams_setting_dlg->UpdateByObj(obj);
m_ams_setting_dlg->Show();
}
}
void StatusPanel::on_filament_extrusion_cali(wxCommandEvent &event)
{
if (!m_extrusion_cali_dlg)
m_extrusion_cali_dlg = new ExtrusionCalibration((wxWindow*)this, wxID_ANY);
if (obj) {
m_extrusion_cali_dlg->obj = obj;
std::string ams_id = m_ams_control->GetCurentAms();
std::string tray_id = m_ams_control->GetCurrentCan(ams_id);
if (tray_id.empty() && ams_id.compare(std::to_string(VIRTUAL_TRAY_MAIN_ID)) != 0) {
wxString txt = _L("Please select an AMS slot before calibration");
MessageDialog msg_dlg(nullptr, txt, wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
return;
}
int ams_id_int = 0;
int tray_id_int = 0;
// set ams_filament id is is bbl filament
if (ams_id.compare(std::to_string(VIRTUAL_TRAY_MAIN_ID)) == 0) {
tray_id_int = VIRTUAL_TRAY_MAIN_ID;
m_extrusion_cali_dlg->ams_filament_id = "";
}
else {
ams_id_int = atoi(ams_id.c_str());
tray_id_int = atoi(tray_id.c_str());
auto tray = obj->GetFilaSystem()->GetAmsTray(ams_id, tray_id);
if (tray) {
if (DevFilaSystem::IsBBL_Filament(tray->tag_uid))
m_extrusion_cali_dlg->ams_filament_id = tray->setting_id;
else
m_extrusion_cali_dlg->ams_filament_id = "";
}
}
try {
m_extrusion_cali_dlg->ams_id = ams_id_int;
m_extrusion_cali_dlg->tray_id = tray_id_int;
m_extrusion_cali_dlg->SetPosition(m_staticText_control->GetScreenPosition());
m_extrusion_cali_dlg->Popup();
} catch(...) {
;
}
}
}
void StatusPanel::on_filament_edit(wxCommandEvent &event)
{
// update params
if (!m_filament_setting_dlg) m_filament_setting_dlg = new AMSMaterialsSetting((wxWindow *) this, wxID_ANY);
int current_position_x = m_ams_control->GetScreenPosition().x;
int current_position_y = m_ams_control->GetScreenPosition().y - FromDIP(40);
auto drect = wxDisplay(GetParent()).GetGeometry().GetHeight() - FromDIP(50);
current_position_y = current_position_y + m_filament_setting_dlg->GetSize().GetHeight() > drect ? drect - m_filament_setting_dlg->GetSize().GetHeight() : current_position_y;
if (obj) {
m_filament_setting_dlg->obj = obj;
// Orca: 2D mode (laser/cut) only allows viewing filament info, not editing
m_filament_setting_dlg->m_view_only = !obj->is_fdm_type();
int ams_id = event.GetInt();
int slot_id = event.GetString().IsEmpty() ? 0 : std::stoi(event.GetString().ToStdString());
try {
m_filament_setting_dlg->ams_id = ams_id;
m_filament_setting_dlg->slot_id = slot_id;
std::string sn_number;
std::string filament;
std::string temp_max;
std::string temp_min;
wxString k_val;
wxString n_val;
auto tray = obj->GetFilaSystem()->GetAmsTray(std::to_string(ams_id), std::to_string(slot_id));
if (tray)
{
k_val = wxString::Format("%.3f", tray->k);
n_val = wxString::Format("%.3f", tray->n);
wxColor color = DevAmsTray::decode_color(tray->color);
// m_filament_setting_dlg->set_color(color);
std::vector<wxColour> cols;
for (auto col : tray->cols) { cols.push_back(DevAmsTray::decode_color(col)); }
m_filament_setting_dlg->set_ctype(tray->ctype);
m_filament_setting_dlg->ams_filament_id = tray->setting_id;
if (m_filament_setting_dlg->ams_filament_id.empty())
{
m_filament_setting_dlg->set_empty_color(color);
}
else
{
m_filament_setting_dlg->set_color(color);
m_filament_setting_dlg->set_colors(cols);
}
m_filament_setting_dlg->m_is_third = !DevFilaSystem::IsBBL_Filament(tray->tag_uid);
if (!m_filament_setting_dlg->m_is_third)
{
sn_number = tray->uuid;
filament = tray->sub_brands;
temp_max = tray->nozzle_temp_max;
temp_min = tray->nozzle_temp_min;
}
}
m_filament_setting_dlg->Move(wxPoint(current_position_x, current_position_y));
m_filament_setting_dlg->Popup(filament, sn_number, temp_min, temp_max, k_val, n_val);
} catch (...) {
;
}
}
}
void StatusPanel::on_ext_spool_edit(wxCommandEvent &event)
{
// update params
if (!m_filament_setting_dlg) m_filament_setting_dlg = new AMSMaterialsSetting((wxWindow*)this, wxID_ANY);
int current_position_x = m_ams_control->GetScreenPosition().x;
int current_position_y = m_ams_control->GetScreenPosition().y - FromDIP(40);
auto drect = wxDisplay(GetParent()).GetGeometry().GetHeight() - FromDIP(50);
current_position_y = current_position_y + m_filament_setting_dlg->GetSize().GetHeight() > drect ? drect - m_filament_setting_dlg->GetSize().GetHeight() : current_position_y;
if (obj) {
m_filament_setting_dlg->obj = obj;
// Orca: 2D mode (laser/cut) only allows viewing filament info, not editing
m_filament_setting_dlg->m_view_only = !obj->is_fdm_type();
int ams_id = event.GetInt();
int slot_id = event.GetString().IsEmpty() ? 0 : std::stoi(event.GetString().ToStdString());
m_filament_setting_dlg->ams_id = ams_id;
m_filament_setting_dlg->slot_id = slot_id;
int nozzle_index = ams_id == VIRTUAL_TRAY_MAIN_ID ? 0 : 1;
try {
std::string sn_number;
std::string filament;
std::string temp_max;
std::string temp_min;
wxString k_val;
wxString n_val;
k_val = wxString::Format("%.3f", obj->vt_slot[nozzle_index].k);
n_val = wxString::Format("%.3f", obj->vt_slot[nozzle_index].n);
wxColor color = DevAmsTray::decode_color(obj->vt_slot[nozzle_index].color);
m_filament_setting_dlg->ams_filament_id = obj->vt_slot[nozzle_index].setting_id;
std::vector<wxColour> cols;
for (auto col : obj->vt_slot[nozzle_index].cols) {
cols.push_back(DevAmsTray::decode_color(col));
}
m_filament_setting_dlg->set_ctype(obj->vt_slot[nozzle_index].ctype);
if (m_filament_setting_dlg->ams_filament_id.empty()) {
m_filament_setting_dlg->set_empty_color(color);
}
else {
m_filament_setting_dlg->set_color(color);
m_filament_setting_dlg->set_colors(cols);
}
m_filament_setting_dlg->m_is_third = !DevFilaSystem::IsBBL_Filament(obj->vt_slot[nozzle_index].tag_uid);
if (!m_filament_setting_dlg->m_is_third) {
sn_number = obj->vt_slot[nozzle_index].uuid;
filament = obj->vt_slot[nozzle_index].sub_brands;
temp_max = obj->vt_slot[nozzle_index].nozzle_temp_max;
temp_min = obj->vt_slot[nozzle_index].nozzle_temp_min;
}
m_filament_setting_dlg->Move(wxPoint(current_position_x,current_position_y));
m_filament_setting_dlg->Popup(filament, sn_number, temp_min, temp_max, k_val, n_val);
}
catch (...) {
;
}
}
}
void StatusPanel::on_ams_refresh_rfid(wxCommandEvent &event)
{
if (obj) {
//std::string curr_ams_id = m_ams_control->GetCurentAms();
if (event.GetInt() < 0 || event.GetInt() > VIRTUAL_TRAY_MAIN_ID){
return;
}
std::string curr_ams_id = std::to_string(event.GetInt());
// do not support refresh rfid for VIRTUAL_TRAY_MAIN_ID
if (curr_ams_id.compare(std::to_string(VIRTUAL_TRAY_MAIN_ID)) == 0) {
return;
}
std::string curr_can_id = event.GetString().ToStdString();
std::map<std::string, DevAms *>::iterator it = obj->GetFilaSystem()->GetAmsList().find(curr_ams_id);
if (it == obj->GetFilaSystem()->GetAmsList().end()) {
BOOST_LOG_TRIVIAL(trace) << "ams: find " << curr_ams_id << " failed";
return;
}
auto slot_it = it->second->GetTrays().find(curr_can_id);
if (slot_it == it->second->GetTrays().end()) {
BOOST_LOG_TRIVIAL(trace) << "ams: find " << curr_can_id << " failed";
return;
}
auto has_filament_at_extruder = false;
auto use_new_command = false;
if (obj->is_enable_np || obj->is_enable_ams_np) {
use_new_command = true;
if (it->second->GetExtruderId() < obj->GetExtderSystem()->GetTotalExtderSize()) {
has_filament_at_extruder = obj->GetExtderSystem()->HasFilamentInExt(it->second->GetExtruderId());
}
} else {
has_filament_at_extruder = obj->is_filament_at_extruder();
}
if (has_filament_at_extruder) {
MessageDialog msg_dlg(nullptr, _L("Cannot read filament info: the filament is loaded to the tool head. Please unload the filament and try again."), wxEmptyString,
wxICON_WARNING | wxYES);
msg_dlg.ShowModal();
return;
}
try {
if (!use_new_command) {
int tray_index = atoi(curr_ams_id.c_str()) * 4 + atoi(slot_it->second->id.c_str());
obj->command_ams_refresh_rfid(-1, tray_index);
}
if (use_new_command) {
obj->command_ams_refresh_rfid(stoi(curr_ams_id), stoi(curr_can_id));
}
} catch (...) {
;
}
}
}
void StatusPanel::on_ams_selected(wxCommandEvent &event)
{
if (obj) {
std::string curr_ams_id = m_ams_control->GetCurentAms();
std::string curr_selected_ams_id = std::to_string(event.GetInt());
if (curr_ams_id.compare(std::to_string(VIRTUAL_TRAY_MAIN_ID)) == 0) {
return;
} else {
std::string curr_can_id = event.GetString().ToStdString();
std::map<std::string, DevAms *>::iterator it = obj->GetFilaSystem()->GetAmsList().find(curr_ams_id);
if (it == obj->GetFilaSystem()->GetAmsList().end()) {
BOOST_LOG_TRIVIAL(trace) << "ams: find " << curr_ams_id << " failed";
return;
}
auto tray_it = it->second->GetTrays().find(curr_can_id);
if (tray_it == it->second->GetTrays().end()) {
BOOST_LOG_TRIVIAL(trace) << "ams: find " << curr_can_id << " failed";
return;
}
try {
int tray_index = atoi(curr_ams_id.c_str()) * 4 + atoi(tray_it->second->id.c_str());
obj->command_ams_select_tray(std::to_string(tray_index));
} catch (...) {
;
}
}
}
}
void StatusPanel::on_ams_guide(wxCommandEvent& event)
{
// Orca: neutral wiki link (vendor URLs removed)
wxString ams_wiki_url = "https://www.orcaslicer.com/wiki/";
wxLaunchDefaultBrowser(ams_wiki_url);
}
void StatusPanel::on_ams_retry(wxCommandEvent& event)
{
BOOST_LOG_TRIVIAL(info) << "on_ams_retry";
if (obj) {
obj->command_ams_control("resume");
}
}
void StatusPanel::on_fan_changed(wxCommandEvent& event)
{
auto type = event.GetInt();
auto speed = atoi(event.GetString().c_str());
set_hold_count(this->m_switch_cham_fan_timeout);
}
void StatusPanel::on_cham_temp_kill_focus(wxFocusEvent& event)
{
event.Skip();
cham_temp_input = false;
}
void StatusPanel::on_cham_temp_set_focus(wxFocusEvent& event)
{
event.Skip();
cham_temp_input = true;
}
void StatusPanel::on_bed_temp_kill_focus(wxFocusEvent &event)
{
event.Skip();
bed_temp_input = false;
}
void StatusPanel::on_bed_temp_set_focus(wxFocusEvent &event)
{
event.Skip();
bed_temp_input = true;
}
void StatusPanel::on_nozzle_temp_kill_focus(wxFocusEvent &event)
{
event.Skip();
nozzle_temp_input = false;
}
void StatusPanel::on_nozzle_temp_set_focus(wxFocusEvent &event)
{
event.Skip();
nozzle_temp_input = true;
}
void StatusPanel::on_switch_speed(wxCommandEvent &event)
{
auto now = boost::posix_time::microsec_clock::universal_time();
if ((now - speed_dismiss_time).total_milliseconds() < 200) {
speed_dismiss_time = now - boost::posix_time::seconds(1);
return;
}
#if __WXOSX__
// MacOS has focus problem
PopupWindow *popUp = new PopupWindow(nullptr);
#else
PopupWindow *popUp = new PopupWindow(m_switch_speed);
#endif
#ifdef __WXMSW__
popUp->BindUnfocusEvent();
#endif
popUp->SetBackgroundColour(StateColor::darkModeColorFor(0xeeeeee));
StepCtrl *step = new StepCtrl(popUp, wxID_ANY);
wxSizer *sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(step, 1, wxEXPAND, 0);
popUp->SetSizer(sizer);
auto em = em_unit(this);
popUp->SetSize(em * 36, em * 8);
step->SetHint(_L("This only takes effect during printing"));
step->AppendItem(_L("Silent"), "");
step->AppendItem(_L("Standard"), "");
step->AppendItem(_L("Sport"), "");
step->AppendItem(_L("Ludicrous"), "");
// default speed lvl
int selected_item = 1;
if (obj) {
int speed_lvl_idx = obj->GetPrintingSpeedLevel() - 1;
if (speed_lvl_idx >= 0 && speed_lvl_idx < 4) {
selected_item = speed_lvl_idx;
}
}
step->SelectItem(selected_item);
if (!obj->is_in_printing()) {
step->Bind(wxEVT_LEFT_DOWN, [](auto& e) {
return; });
}
step->Bind(EVT_STEP_CHANGED, [this](auto &e) {
this->speed_lvl = e.GetInt() + 1;
if (obj) {
set_hold_count(this->speed_lvl_timeout);
obj->command_set_printing_speed((DevPrintingSpeedLevel)this->speed_lvl);
}
});
popUp->Bind(wxEVT_SHOW, [this, popUp](auto &e) {
if (!e.IsShown()) {
popUp->Destroy();
speed_dismiss_time = boost::posix_time::microsec_clock::universal_time();
}
});
wxPoint pos = m_switch_speed->ClientToScreen(wxPoint(0, -6));
popUp->Position(pos, {0, m_switch_speed->GetSize().y + 12});
popUp->Popup();
}
void StatusPanel::on_printing_fan_switch(wxCommandEvent &event)
{
/* if (!obj) return;
bool value = m_switch_printing_fan->GetValue();
if (value) {
obj->command_control_fan(MachineObject::FanType::BIG_COOLING_FAN, true);
m_switch_printing_fan->SetValue(true);
set_hold_count(this->m_switch_printing_fan_timeout);
} else {
obj->command_control_fan(MachineObject::FanType::BIG_COOLING_FAN, false);
m_switch_printing_fan->SetValue(false);
set_hold_count(this->m_switch_printing_fan_timeout);
}*/
}
void StatusPanel::on_nozzle_fan_switch(wxCommandEvent &event)
{
if (m_fan_control_popup) {
m_fan_control_popup->Destroy();
m_fan_control_popup = nullptr;
}
if (!obj) { return; }
if (obj->GetFan()->GetAirDuctData().modes.empty())
{
obj->GetFan()->converse_to_duct(true, obj->GetFan()->GetSupportAuxFanData(), obj->GetFan()->GetSupportChamberFan());
}
m_fan_control_popup = new FanControlPopupNew(this, obj, obj->GetFan()->GetAirDuctData());
auto pos = m_switch_fan->GetScreenPosition();
pos.y = pos.y + m_switch_fan->GetSize().y;
int display_idx = wxDisplay::GetFromWindow(this);
auto display = wxDisplay(display_idx).GetClientArea();
wxSize screenSize = wxSize(display.GetWidth(), display.GetHeight());
wxSize fan_popup_size = m_fan_control_popup->GetSize();
pos.x -= FromDIP(150);
pos.y -= FromDIP(20);
if (screenSize.y - fan_popup_size.y < FromDIP(300)) {
pos.y = (screenSize.y - fan_popup_size.y) / 2;
}
m_fan_control_popup->SetPosition(pos);
m_fan_control_popup->ShowModal();
}
void StatusPanel::on_lamp_switch(wxCommandEvent &event)
{
if (!obj) return;
bool value = m_switch_lamp->GetValue();
if (value) {
m_switch_lamp->SetValue(true);
// do not update when timeout > 0
set_hold_count(this->m_switch_lamp_timeout);
obj->GetLamp()->CtrlSetChamberLight(DevLamp::LIGHT_EFFECT_ON);
} else {
if (obj->GetLamp()->HasLampCloseRecheck()){
MessageDialog msg_dlg(nullptr, _L("Turning off the lights during the task will cause the failure of AI monitoring, like spaghetti detection. Please choose carefully."), wxEmptyString, wxICON_WARNING | wxOK | wxCANCEL);
msg_dlg.SetButtonLabel(wxID_OK, _L("Keep it On"));
msg_dlg.SetButtonLabel(wxID_CANCEL, _L("Turn it Off"));
if (msg_dlg.ShowModal() != wxID_CANCEL) {
return;
}
}
m_switch_lamp->SetValue(false);
set_hold_count(this->m_switch_lamp_timeout);
obj->GetLamp()->CtrlSetChamberLight(DevLamp::LIGHT_EFFECT_OFF);
}
}
void StatusPanel::on_switch_vcamera(wxMouseEvent &event)
{
//if (!obj) return;
//bool value = m_recording_button->get_switch_status();
//obj->command_ipcam_record(!value);
m_media_play_ctrl->ToggleStream();
show_vcamera = m_media_play_ctrl->IsStreaming();
if (m_camera_popup)
m_camera_popup->sync_vcamera_state(show_vcamera);
}
void StatusPanel::on_camera_enter(wxMouseEvent& event)
{
if (obj) {
if (m_camera_popup == nullptr)
m_camera_popup = std::make_shared<CameraPopup>(this);
m_camera_popup->check_func_supported(obj);
m_camera_popup->sync_vcamera_state(show_vcamera);
m_camera_popup->Bind(EVT_VCAMERA_SWITCH, &StatusPanel::on_switch_vcamera, this);
m_camera_popup->Bind(EVT_SDCARD_ABSENT_HINT, [this](wxCommandEvent &e) {
if (sdcard_hint_dlg == nullptr) {
sdcard_hint_dlg = new SecondaryCheckDialog(this->GetParent(), wxID_ANY, _L("Warning"), SecondaryCheckDialog::VisibleButtons::ONLY_CONFIRM); // ORCA VisibleButtons instead ButtonStyle
sdcard_hint_dlg->update_text(_L("Can't start this without storage."));
}
sdcard_hint_dlg->on_show();
});
wxWindow* ctrl = (wxWindow*)event.GetEventObject();
wxPoint pos = ctrl->ClientToScreen(wxPoint(0, 0));
wxSize sz = ctrl->GetSize();
pos.x += sz.x;
pos.y += sz.y;
m_camera_popup->SetPosition(pos);
m_camera_popup->update(m_media_play_ctrl->IsStreaming());
m_camera_popup->Popup();
}
}
void StatusBasePanel::remove_controls()
{
const std::string js_cleanup_video_element = R"(
document.body.style.overflow='hidden';
const video = document.querySelector('video');
video.setAttribute('style', 'width: 100% !important;');
video.removeAttribute('controls');
video.addEventListener('leavepictureinpicture', () => {
window.wx.postMessage('leavepictureinpicture');
});
video.addEventListener('enterpictureinpicture', () => {
window.wx.postMessage('enterpictureinpicture');
});
)";
m_custom_camera_view->RunScript(js_cleanup_video_element);
}
void StatusPanel::on_camera_leave(wxMouseEvent& event)
{
if (obj && m_camera_popup) {
m_camera_popup->Dismiss();
}
}
void StatusPanel::on_auto_leveling(wxCommandEvent &event)
{
if (obj) obj->command_auto_leveling();
}
void StatusPanel::on_xyz_abs(wxCommandEvent &event)
{
if (obj) obj->command_xyz_abs();
}
void StatusPanel::on_nozzle_selected(wxCommandEvent &event)
{
if (obj) {
/*Enable switch head while printing is paused STUDIO-9789*/
if ((obj->is_in_printing() && !obj->is_in_printing_pause()) || obj->ams_status_main == AMS_STATUS_MAIN_FILAMENT_CHANGE) {
MessageDialog dlg(nullptr, _L("The printer is busy with another print job."), _L("Error"), wxICON_WARNING | wxOK);
dlg.ShowModal();
return;
}
auto nozzle_id = event.GetInt();
if (obj->GetCtrl()->command_select_extruder(nozzle_id) == 0)
{
return;
}
}
m_nozzle_btn_panel->Enable();
}
void StatusPanel::on_show_print_options(wxCommandEvent& event)
{
if (obj) {
// Always show print options dialog for all machines
if (print_options_dlg == nullptr) {
print_options_dlg = new PrintOptionsDialog(this);
print_options_dlg->update_machine_obj(obj);
print_options_dlg->update_options(obj);
print_options_dlg->ShowModal();
}
else {
print_options_dlg->update_machine_obj(obj);
print_options_dlg->update_options(obj);
print_options_dlg->ShowModal();
}
}
}
void StatusPanel::on_show_safety_options(wxCommandEvent& event)
{
if (obj) {
std::string current_printer_type = obj->printer_type;
bool supports_safety = DevPrinterConfigUtil::support_safety_options(current_printer_type);
if (supports_safety) {
if (safety_options_dlg == nullptr) {
safety_options_dlg = new SafetyOptionsDialog(this);
safety_options_dlg->update_machine_obj(obj);
safety_options_dlg->update_options(obj);
safety_options_dlg->ShowModal();
}
else {
safety_options_dlg->update_machine_obj(obj);
safety_options_dlg->update_options(obj);
safety_options_dlg->ShowModal();
}
}
}
}
void StatusPanel::on_show_parts_options(wxCommandEvent &event)
{
if (obj) {
if (print_parts_dlg == nullptr) {
print_parts_dlg = new PrinterPartsDialog(this);
print_parts_dlg->update_machine_obj(obj);
print_parts_dlg->ShowModal();
}
else {
print_parts_dlg->update_machine_obj(obj);
print_parts_dlg->ShowModal();
}
}
}
void StatusPanel::update_printer_parts_options(MachineObject* obj_)
{
if(obj_){
if(print_parts_dlg && print_parts_dlg->IsShown()){
print_parts_dlg->update_machine_obj(obj_);
print_parts_dlg->UpdateNozzleInfo();
}
}
}
void StatusPanel::on_start_calibration(wxCommandEvent &event)
{
if (obj) {
if (calibration_dlg == nullptr) {
calibration_dlg = new CalibrationDialog();
calibration_dlg->update_machine_obj(obj);
calibration_dlg->update_cali(obj);
calibration_dlg->ShowModal();
} else {
calibration_dlg->update_machine_obj(obj);
calibration_dlg->update_cali(obj);
calibration_dlg->ShowModal();
}
}
}
bool StatusPanel::is_stage_list_info_changed(MachineObject *obj)
{
if (!obj) return true;
if (last_stage_list_info.size() != obj->stage_list_info.size()) return true;
for (int i = 0; i < last_stage_list_info.size(); i++) {
if (last_stage_list_info[i] != obj->stage_list_info[i]) return true;
}
last_stage_list_info = obj->stage_list_info;
return false;
}
void StatusPanel::set_default()
{
BOOST_LOG_TRIVIAL(trace) << "status_panel: set_default";
if (m_custom_camera_view->IsShown()) {
m_custom_camera_view->Hide();
m_media_ctrl->Show();
m_media_play_ctrl->StopWebStream();
}
obj = nullptr;
last_subtask = nullptr;
last_tray_exist_bits = -1;
speed_lvl = 1;
speed_lvl_timeout = 0;
m_switch_lamp_timeout = 0;
m_temp_nozzle_timeout = 0;
m_temp_nozzle_deputy_timeout = 0;
m_temp_bed_timeout = 0;
m_temp_chamber_timeout = 0;
m_switch_nozzle_fan_timeout = 0;
m_switch_printing_fan_timeout = 0;
m_switch_cham_fan_timeout = 0;
m_show_ams_group = false;
m_show_filament_group = false;
reset_printing_values();
m_bitmap_timelapse_img->Hide();
m_bitmap_recording_img->Hide();
m_bitmap_vcamera_img->Hide();
m_setting_button->Show();
m_tempCtrl_chamber->Show();
m_options_btn->Show();
m_safety_btn->Show();
m_parts_btn->Show();
if (m_panel_control_title) {
m_panel_control_title->Layout();
m_panel_control_title->Refresh();
}
reset_temp_misc_control();
m_extruder_switching_status->Hide();
m_ams_control->Hide();
m_ams_control_box->Hide();
m_ams_control->Reset();
m_ams_rack_switch->updateState("left");
m_ams_rack_switch->Hide();
m_panel_nozzle_rack->Hide();
m_scale_panel->Hide();
m_filament_load_box->Hide();
m_filament_step->Hide();
error_info_reset();
#ifndef __WXGTK__
// Also reached while the panel is built off screen.
if (IsShownOnScreen())
SetFocus();
#endif
}
void StatusPanel::show_status(int status)
{
if (last_status == status) return;
last_status = status;
if (((status & (int) MonitorStatus::MONITOR_DISCONNECTED) != 0)
|| ((status & (int) MonitorStatus::MONITOR_DISCONNECTED_SERVER) != 0)
|| ((status & (int)MonitorStatus::MONITOR_CONNECTING) != 0)
|| ((status & (int)MonitorStatus::MONITOR_NO_PRINTER) != 0)
) {
show_printing_status(false, false);
m_calibration_btn->Disable();
m_options_btn->Disable();
m_safety_btn->Disable();
m_parts_btn->Disable();
m_panel_monitoring_title->Disable();
} else if ((status & (int) MonitorStatus::MONITOR_NORMAL) != 0) {
show_printing_status(true, true);
m_calibration_btn->Disable();
m_options_btn->Enable();
m_safety_btn->Enable();
m_parts_btn->Enable();
m_panel_monitoring_title->Enable();
}
}
void StatusPanel::set_hold_count(int& count)
{
count = COMMAND_TIMEOUT;
}
void StatusPanel::rescale_camera_icons()
{
if (!GetParent() || IsBeingDeleted()) return;
if (!m_setting_button || !m_media_play_ctrl || !m_bitmap_vcamera_img || !m_bitmap_sdcard_img || !m_bitmap_recording_img || !m_bitmap_timelapse_img) return;
m_setting_button->msw_rescale();
m_bitmap_sdcard_state_abnormal = ScalableBitmap(this, wxGetApp().dark_mode()?"sdcard_state_abnormal_dark":"sdcard_state_abnormal", 20);
m_bitmap_sdcard_state_normal = ScalableBitmap(this, wxGetApp().dark_mode()?"sdcard_state_normal_dark":"sdcard_state_normal", 20);
m_bitmap_sdcard_state_no = ScalableBitmap(this, wxGetApp().dark_mode()?"sdcard_state_no_dark":"sdcard_state_no", 20);
m_bitmap_recording_on = ScalableBitmap(this, wxGetApp().dark_mode()?"monitor_recording_on_dark":"monitor_recording_on", 20);
m_bitmap_recording_off = ScalableBitmap(this, wxGetApp().dark_mode()?"monitor_recording_off_dark":"monitor_recording_off", 20);
m_bitmap_timelapse_on = ScalableBitmap(this, wxGetApp().dark_mode()?"monitor_timelapse_on_dark":"monitor_timelapse_on", 20);
m_bitmap_timelapse_off = ScalableBitmap(this, wxGetApp().dark_mode()?"monitor_timelapse_off_dark":"monitor_timelapse_off", 20);
m_bitmap_vcamera_on = ScalableBitmap(this, wxGetApp().dark_mode()?"monitor_vcamera_on_dark":"monitor_vcamera_on", 20);
m_bitmap_vcamera_off = ScalableBitmap(this, wxGetApp().dark_mode()?"monitor_vcamera_off_dark":"monitor_vcamera_off", 20);
if (m_media_play_ctrl->IsStreaming()) {
m_bitmap_vcamera_img->SetBitmap(m_bitmap_vcamera_on.bmp());
}
else {
m_bitmap_vcamera_img->SetBitmap(m_bitmap_vcamera_off.bmp());
}
if (!obj) return;
if (obj->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::NO_SDCARD) {
m_bitmap_sdcard_img->SetBitmap(m_bitmap_sdcard_state_no.bmp());
} else if (obj->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::HAS_SDCARD_NORMAL) {
m_bitmap_sdcard_img->SetBitmap(m_bitmap_sdcard_state_normal.bmp());
} else if (obj->GetStorage()->get_sdcard_state() == DevStorage::SdcardState::HAS_SDCARD_ABNORMAL) {
m_bitmap_sdcard_img->SetBitmap(m_bitmap_sdcard_state_abnormal.bmp());
} else {
m_bitmap_sdcard_img->SetBitmap(m_bitmap_sdcard_state_normal.bmp());
}
if (obj->is_recording()) {
m_bitmap_recording_img->SetBitmap(m_bitmap_recording_on.bmp());
} else {
m_bitmap_recording_img->SetBitmap(m_bitmap_recording_off.bmp());
}
if (obj->is_timelapse()) {
m_bitmap_timelapse_img->SetBitmap(m_bitmap_timelapse_on.bmp());
} else {
m_bitmap_timelapse_img->SetBitmap(m_bitmap_timelapse_off.bmp());
}
}
void StatusPanel::on_sys_color_changed()
{
m_project_task_panel->msw_rescale();
m_bitmap_speed.msw_rescale();
m_bitmap_speed_active.msw_rescale();
m_switch_speed->SetImages(m_bitmap_speed, m_bitmap_speed);
m_ams_control->msw_rescale();
rescale_camera_icons();
}
void StatusPanel::msw_rescale()
{
init_bitmaps();
m_project_task_panel->init_bitmaps();
m_project_task_panel->msw_rescale();
m_panel_monitoring_title->SetSize(wxSize(-1, FromDIP(PAGE_TITLE_HEIGHT)));
//m_staticText_monitoring->SetMinSize(wxSize(PAGE_TITLE_TEXT_WIDTH, PAGE_TITLE_HEIGHT));
m_bmToggleBtn_timelapse->Rescale();
m_panel_control_title->SetSize(wxSize(-1, FromDIP(PAGE_TITLE_HEIGHT)));
//m_staticText_control->SetMinSize(wxSize(-1, PAGE_TITLE_HEIGHT));
m_media_play_ctrl->msw_rescale();
m_bpButton_xy->SetBitmap(m_bitmap_axis_home);
m_bpButton_xy->SetMinSize(AXIS_MIN_SIZE);
m_bpButton_xy->SetSize(AXIS_MIN_SIZE);
m_temp_extruder_line->SetSize(wxSize(FromDIP(1), -1));
update_extruder_status(obj);
//m_bitmap_extruder_img->SetMinSize(EXTRUDER_IMAGE_SIZE);
for (Button *btn : m_buttons) { btn->Rescale(); }
init_scaled_buttons();
m_bpButton_xy->Rescale();
auto size = TEMP_CTRL_MIN_SIZE_ALIGN_ONE_ICON;
if (obj && obj->GetExtderSystem()->GetTotalExtderCount() >= 2) size = TEMP_CTRL_MIN_SIZE_ALIGN_TWO_ICON;
m_tempCtrl_nozzle->SetMinSize(size);
m_tempCtrl_nozzle->Rescale();
m_tempCtrl_nozzle_deputy->SetMinSize(size);
m_tempCtrl_nozzle_deputy->Rescale();
m_line_nozzle->SetSize(wxSize(-1, FromDIP(1)));
m_tempCtrl_bed->SetMinSize(size);
m_tempCtrl_bed->Rescale();
m_tempCtrl_chamber->SetMinSize(size);
m_tempCtrl_chamber->Rescale();
for(int i = 0; i < m_extruder_book->GetPageCount(); i++)
{
ExtruderImage* ext_img = dynamic_cast<ExtruderImage*> (m_extruder_book->GetPage(i));
if (ext_img)
{
ext_img->msw_rescale();
}
}
m_bitmap_speed.msw_rescale();
m_bitmap_speed_active.msw_rescale();
m_switch_speed->SetImages(m_bitmap_speed, m_bitmap_speed);
m_switch_speed->SetMinSize(MISC_BUTTON_2FAN_SIZE);
m_switch_speed->Rescale();
m_switch_lamp->SetImages(m_bitmap_lamp_on, m_bitmap_lamp_off);
m_switch_lamp->SetMinSize(MISC_BUTTON_2FAN_SIZE);
m_switch_lamp->Rescale();
/*m_switch_nozzle_fan->SetImages(m_bitmap_fan_on, m_bitmap_fan_off);
m_switch_nozzle_fan->Rescale();
m_switch_printing_fan->SetImages(m_bitmap_fan_on, m_bitmap_fan_off);
m_switch_printing_fan->Rescale();
m_switch_cham_fan->SetImages(m_bitmap_fan_on, m_bitmap_fan_off);
m_switch_cham_fan->Rescale();*/
m_switch_fan->SetImages(m_bitmap_fan_on, m_bitmap_fan_off);
m_switch_fan->Rescale();
if (m_fan_control_popup)
{
m_fan_control_popup->msw_rescale();
}
//m_switch_fan->SetImages(m_bitmap_fan_on, m_bitmap_fan_off);
//m_switch_fan->Rescale();
m_bpButton_z_10->Rescale();
m_bpButton_z_1->Rescale();
m_bpButton_z_down_1->Rescale();
m_bpButton_z_down_10->Rescale();
m_extruder_switching_status->msw_rescale();
m_ams_control->msw_rescale();
m_panel_nozzle_rack->Rescale();
// m_filament_step->Rescale();
m_calibration_btn->SetMinSize(wxSize(-1, FromDIP(26)));
m_calibration_btn->Rescale();
m_options_btn->SetMinSize(wxSize(-1, FromDIP(26)));
m_options_btn->Rescale();
m_safety_btn->SetMinSize(wxSize(-1, FromDIP(26)));
m_safety_btn->Rescale();
m_parts_btn->SetMinSize(wxSize(-1, FromDIP(26)));
m_parts_btn->Rescale();
rescale_camera_icons();
Layout();
Refresh();
}
void StatusPanel::update_rack(MachineObject *obj)
{
// Rack switch + live rack panel are shown only for printers whose nozzle system reports a rack
// (H2C). Every other Bambu printer keeps the switch hidden and the panel collapsed -> the AMS
// monitor page is unchanged for X1/P1/A1/H2D/H2S.
if (obj && obj->GetNozzleSystem()->GetNozzleRack()->IsSupported()) {
m_ams_rack_switch->Show();
m_panel_nozzle_rack->UpdateRackInfo(obj->GetNozzleSystem()->GetNozzleRack());
} else {
m_ams_rack_switch->Show(false);
m_panel_nozzle_rack->Show(false);
}
}
void StatusPanel::update_filament_loading_panel(MachineObject* obj)
{
if (!obj) {
show_filament_load_group(false);
return;
}
bool ams_loading_state = false;
auto ams_status_sub = obj->ams_status_sub;
// Skip busy-loading detection during a cold pull.
if (obj->is_enable_np && obj->ams_status_main != AMS_STATUS_MAIN_COLD_PULL) {
ams_loading_state = obj->GetExtderSystem()->IsBusyLoading();
} else if (obj->ams_status_main == AMS_STATUS_MAIN_FILAMENT_CHANGE) {
ams_loading_state = true;
}
if (ams_loading_state) {
update_load_with_temp();
const std::string& cur_ams_id = obj->GetExtderSystem()->GetCurrentAmsId();
const std::string& cur_tray_id = obj->GetExtderSystem()->GetCurrentSlotId();
if (!cur_ams_id.empty() && !cur_tray_id.empty()) {
m_filament_step->updateID(std::atoi(cur_ams_id.c_str()), std::atoi(cur_tray_id.c_str()));
}
auto loading_ext = obj->GetExtderSystem()->GetLoadingExtder();
auto tar = loading_ext ? loading_ext->GetSlotTarget() : DevAmsSlotInfo();
bool busy_for_vt_loading = (tar.ams_id == std::to_string(VIRTUAL_TRAY_MAIN_ID) || tar.ams_id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) && !obj->is_target_slot_unload();
if (busy_for_vt_loading) {
// wait to heat hotend
if (ams_status_sub == 0x02) {
m_filament_step->SetFilamentStep(FilamentStep::STEP_HEAT_NOZZLE, FilamentStepType::STEP_TYPE_VT_LOAD);
} else if (ams_status_sub == 0x05) {
m_filament_step->SetFilamentStep(FilamentStep::STEP_PUSH_NEW_FILAMENT, FilamentStepType::STEP_TYPE_VT_LOAD);
} else if (ams_status_sub == 0x06) {
m_filament_step->SetFilamentStep(FilamentStep::STEP_CONFIRM_EXTRUDED, FilamentStepType::STEP_TYPE_VT_LOAD);
} else if (ams_status_sub == 0x07) {
m_filament_step->SetFilamentStep(FilamentStep::STEP_PURGE_OLD_FILAMENT, FilamentStepType::STEP_TYPE_VT_LOAD);
} else {
m_filament_step->SetFilamentStep(FilamentStep::STEP_IDLE, FilamentStepType::STEP_TYPE_VT_LOAD);
ams_loading_state = false;
}
} else {
// wait to heat hotend
if (ams_status_sub == 0x02) {
if (!obj->is_target_slot_unload()) {
m_filament_step->SetFilamentStep(FilamentStep::STEP_HEAT_NOZZLE, FilamentStepType::STEP_TYPE_LOAD);
} else {
m_filament_step->SetFilamentStep(FilamentStep::STEP_HEAT_NOZZLE, FilamentStepType::STEP_TYPE_UNLOAD);
}
} else if (ams_status_sub == 0x03) {
if (!obj->is_target_slot_unload()) {
m_filament_step->SetFilamentStep(FilamentStep::STEP_CUT_FILAMENT, FilamentStepType::STEP_TYPE_LOAD);
} else {
m_filament_step->SetFilamentStep(FilamentStep::STEP_CUT_FILAMENT, FilamentStepType::STEP_TYPE_UNLOAD);
}
} else if (ams_status_sub == 0x04) {
if (!obj->is_target_slot_unload()) {
m_filament_step->SetFilamentStep(FilamentStep::STEP_PULL_CURR_FILAMENT, FilamentStepType::STEP_TYPE_LOAD);
} else {
m_filament_step->SetFilamentStep(FilamentStep::STEP_PULL_CURR_FILAMENT, FilamentStepType::STEP_TYPE_UNLOAD);
}
} else if (ams_status_sub == 0x05) {
if (!obj->is_target_slot_unload()) {
if (m_is_load_with_temp) {
m_filament_step->SetFilamentStep(FilamentStep::STEP_CUT_FILAMENT, FilamentStepType::STEP_TYPE_LOAD);
} else {
m_filament_step->SetFilamentStep(FilamentStep::STEP_PUSH_NEW_FILAMENT, FilamentStepType::STEP_TYPE_LOAD);
}
} else {
m_filament_step->SetFilamentStep(FilamentStep::STEP_PUSH_NEW_FILAMENT, FilamentStepType::STEP_TYPE_UNLOAD);
}
} else if (ams_status_sub == 0x06) {
if (!obj->is_target_slot_unload()) {
m_filament_step->SetFilamentStep(FilamentStep::STEP_PUSH_NEW_FILAMENT, FilamentStepType::STEP_TYPE_LOAD);
} else {
m_filament_step->SetFilamentStep(FilamentStep::STEP_PUSH_NEW_FILAMENT, FilamentStepType::STEP_TYPE_UNLOAD);
}
} else if (ams_status_sub == 0x07) {
if (!obj->is_target_slot_unload()) {
if (m_is_load_with_temp) {
m_filament_step->SetFilamentStep(FilamentStep::STEP_PULL_CURR_FILAMENT, FilamentStepType::STEP_TYPE_LOAD);
} else {
m_filament_step->SetFilamentStep(FilamentStep::STEP_PURGE_OLD_FILAMENT, FilamentStepType::STEP_TYPE_LOAD);
}
} else {
m_filament_step->SetFilamentStep(FilamentStep::STEP_PURGE_OLD_FILAMENT, FilamentStepType::STEP_TYPE_UNLOAD);
}
} else if (ams_status_sub == 0x08) {
if (!obj->is_target_slot_unload()) {
m_filament_step->SetFilamentStep(FilamentStep::STEP_CHECK_POSITION, FilamentStepType::STEP_TYPE_LOAD);
} else {
m_filament_step->SetFilamentStep(FilamentStep::STEP_CHECK_POSITION, FilamentStepType::STEP_TYPE_UNLOAD);
}
} else if (ams_status_sub == 0x09) {
//just wait
} else if (ams_status_sub == 0x0B) {
if (!obj->is_target_slot_unload()) {
m_filament_step->SetFilamentStep(FilamentStep::STEP_CHECK_POSITION, FilamentStepType::STEP_TYPE_LOAD);
} else {
m_filament_step->SetFilamentStep(FilamentStep::STEP_CHECK_POSITION, FilamentStepType::STEP_TYPE_UNLOAD);
}
} else {
m_filament_step->SetFilamentStep(FilamentStep::STEP_IDLE, FilamentStepType::STEP_TYPE_UNLOAD);
ams_loading_state = false;
}
}
} else if (obj->ams_status_main == AMS_STATUS_MAIN_ASSIST) {
m_filament_step->SetFilamentStep(FilamentStep::STEP_IDLE, FilamentStepType::STEP_TYPE_LOAD);
ams_loading_state = false;
} else {
m_filament_step->SetFilamentStep(FilamentStep::STEP_IDLE, FilamentStepType::STEP_TYPE_LOAD);
ams_loading_state = false;
}
// Orca: show the Stop button when the printer supports aborting a filament change (flag3 bit-13 or printer config)
m_fila_change_abort->Show(ams_loading_state &&
(obj->is_support_fila_change_abort || DevPrinterConfigUtil::support_ams_fila_change_abort(obj->printer_type)));
show_filament_load_group(ams_loading_state);
}
ScoreDialog::ScoreDialog(wxWindow *parent, int design_id, std::string model_id, int profile_id, int rating_id, bool success_printed, int star_count)
: DPIDialog(parent, wxID_ANY, _L("Rate the Print Profile"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX | wxRESIZE_BORDER)
, m_design_id(design_id)
, m_model_id(model_id)
, m_profile_id(profile_id)
, m_star_count(star_count)
, m_rating_id(rating_id)
, m_success_printed(success_printed)
, m_upload_status_code(StatusCode::CODE_NUMBER)
{
m_tocken.reset(new int(0));
wxBoxSizer *m_main_sizer = get_main_sizer();
this->SetSizer(m_main_sizer);
Fit();
Layout();
wxGetApp().UpdateDlgDarkUI(this);
}
ScoreDialog::ScoreDialog(wxWindow *parent, ScoreData *score_data)
: DPIDialog(parent, wxID_ANY, _L("Rate the Print Profile"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX | wxRESIZE_BORDER)
, m_design_id(score_data->design_id)
, m_rating_id(score_data->rating_id)
, m_model_id(score_data->model_id)
, m_profile_id(score_data->profile_id)
, m_star_count(score_data->star_count)
, m_success_printed(score_data->success_printed)
, m_upload_status_code(StatusCode::CODE_NUMBER)
{
m_tocken.reset(new int(0));
wxBoxSizer *m_main_sizer = get_main_sizer(score_data->local_to_url_image, score_data->comment_text);
m_image_url_paths = score_data->image_url_paths;
this->SetSizer(m_main_sizer);
Fit();
Layout();
wxGetApp().UpdateDlgDarkUI(this);
}
ScoreDialog::~ScoreDialog() {}
void ScoreDialog::on_dpi_changed(const wxRect &suggested_rect) {}
void ScoreDialog::OnBitmapClicked(wxMouseEvent &event)
{
wxStaticBitmap *clickedBitmap = dynamic_cast<wxStaticBitmap *>(event.GetEventObject());
if (m_image.find(clickedBitmap) != m_image.end()) {
if (!m_image[clickedBitmap].is_selected) {
for (auto panel : m_image[clickedBitmap].image_broad) {
panel->Show();
}
m_image[clickedBitmap].is_selected = true;
m_selected_image_list.insert(clickedBitmap);
} else {
for (auto panel : m_image[clickedBitmap].image_broad) {
panel->Hide();
}
m_image[clickedBitmap].is_selected = false;
m_selected_image_list.erase(clickedBitmap);
m_selected_image_list.erase(clickedBitmap);
}
}
if (m_selected_image_list.empty())
m_delete_photo->Hide();
else
m_delete_photo->Show();
Fit();
Layout();
}
std::set <std::pair<wxStaticBitmap * ,wxString>> ScoreDialog::add_need_upload_imgs()
{
std::set<std::pair<wxStaticBitmap *, wxString>> need_upload_images;
for (auto bitmap : m_image) {
if (!bitmap.second.is_uploaded) {
wxString &local_image_path = bitmap.second.local_image_url;
if (!local_image_path.empty()) { need_upload_images.insert(std::make_pair(bitmap.first, local_image_path)); }
}
}
return need_upload_images;
}
std::pair<wxStaticBitmap *, ScoreDialog::ImageMsg> ScoreDialog::create_local_thumbnail(wxString &local_path)
{
std::pair<wxStaticBitmap *, ImageMsg> bitmap_to_image_msg;
if (local_path.empty()) return bitmap_to_image_msg;
ImageMsg cur_image_msg;
cur_image_msg.local_image_url = local_path;
cur_image_msg.img_url_paths = "";
cur_image_msg.is_uploaded = false;
wxStaticBitmap *imageCtrl = new wxStaticBitmap(this, wxID_ANY, wxBitmap(wxImage(local_path, wxBITMAP_TYPE_ANY).Rescale(FromDIP(80), FromDIP(60))), wxDefaultPosition,
wxDefaultSize, 0);
imageCtrl->Bind(wxEVT_LEFT_DOWN, &ScoreDialog::OnBitmapClicked, this);
m_image_sizer->Add(create_broad_sizer(imageCtrl, cur_image_msg), 0, wxALL, 5);
bitmap_to_image_msg.first = imageCtrl;
bitmap_to_image_msg.second = cur_image_msg;
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": local picture is download";
return bitmap_to_image_msg;
}
std::pair<wxStaticBitmap *, ScoreDialog::ImageMsg> ScoreDialog::create_oss_thumbnail(std::string &oss_path)
{
std::pair<wxStaticBitmap *, ImageMsg> bitmap_to_image_msg;
if (oss_path.empty()) return bitmap_to_image_msg;
ImageMsg cur_image_msg;
cur_image_msg.local_image_url = "";
cur_image_msg.img_url_paths = oss_path;
cur_image_msg.is_uploaded = true;
wxImage image(Slic3r::resources_dir() + "/images/oss_picture_loading.png", wxBITMAP_TYPE_ANY);
wxStaticBitmap *imageCtrl = new wxStaticBitmap(this, wxID_ANY, wxBitmap(image.Rescale(FromDIP(80), FromDIP(60))), wxDefaultPosition, wxDefaultSize, 0);
imageCtrl->Bind(wxEVT_LEFT_DOWN, &ScoreDialog::OnBitmapClicked, this);
Slic3r::Http http = Slic3r::Http::get(oss_path);
std::string suffix = oss_path.substr(oss_path.find_last_of(".") + 1);
http.header("accept", "image/" + suffix) //"image/" + suffix
.header("Accept-Encoding", "gzip")
.on_complete([this, imageCtrl, time = std::weak_ptr<int>(m_tocken)](std::string body, unsigned int status) {
if (time.expired()) return;
wxMemoryInputStream stream(body.data(), body.size());
wxImage success_image;
if (success_image.LoadFile(stream, wxBITMAP_TYPE_ANY)) {
CallAfter([this, success_image, imageCtrl]() { update_static_bitmap(imageCtrl, success_image); });
} else {
CallAfter([this, imageCtrl]() { update_static_bitmap(imageCtrl, fail_image); });
}
})
.on_error([this, imageCtrl, &oss_path](std::string body, std::string error, unsigned status) {
BOOST_LOG_TRIVIAL(info) << "load oss picture failed, oss path: " << oss_path << " status:" << status << " error:" << error;
CallAfter([this, imageCtrl]() { update_static_bitmap(imageCtrl, fail_image); });
}).perform();
m_image_sizer->Add(create_broad_sizer(imageCtrl, cur_image_msg), 0, wxALL, 5);
bitmap_to_image_msg.first = imageCtrl;
bitmap_to_image_msg.second = cur_image_msg;
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": oss picture is download";
return bitmap_to_image_msg;
}
void ScoreDialog::update_static_bitmap(wxStaticBitmap* static_bitmap, wxImage image)
{
static_bitmap->SetBitmap(wxBitmap(image.Rescale(FromDIP(80), FromDIP(60))));
Layout();
Fit();
//Refresh();
}
wxBoxSizer *ScoreDialog::create_broad_sizer(wxStaticBitmap *bitmap, ImageMsg& cur_image_msg)
{
// tb: top and bottom lr: left and right
auto m_image_tb_broad = new wxBoxSizer(wxVERTICAL);
auto line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL);
line_top->SetBackgroundColour(wxColour(0xA6, 0xa9, 0xAA));
m_image_tb_broad->Add(line_top, 0, wxEXPAND, 0);
cur_image_msg.image_broad.push_back(line_top);
line_top->Hide();
auto m_image_lr_broad = new wxBoxSizer(wxHORIZONTAL);
auto line_left = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(1, -1), wxTAB_TRAVERSAL);
line_left->SetBackgroundColour(wxColour(0xA6, 0xa9, 0xAA));
m_image_lr_broad->Add(line_left, 0, wxEXPAND, 0);
cur_image_msg.image_broad.push_back(line_left);
line_left->Hide();
m_image_lr_broad->Add(bitmap, 0, wxALL, 5);
auto line_right = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(1, -1), wxTAB_TRAVERSAL);
line_right->SetBackgroundColour(wxColour(0xA6, 0xa9, 0xAA));
m_image_lr_broad->Add(line_right, 0, wxEXPAND, 0);
m_image_tb_broad->Add(m_image_lr_broad, 0, wxEXPAND, 0);
cur_image_msg.image_broad.push_back(line_right);
line_right->Hide();
auto line_bottom = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL);
line_bottom->SetBackgroundColour(wxColour(0xA6, 0xa9, 0xAA));
m_image_tb_broad->Add(line_bottom, 0, wxEXPAND, 0);
cur_image_msg.image_broad.push_back(line_bottom);
line_bottom->Hide();
cur_image_msg.is_selected = false;
cur_image_msg.image_tb_broad = m_image_tb_broad;
return m_image_tb_broad;
}
void ScoreDialog::init() {
SetBackgroundColour(*wxWHITE);
SetMinSize(wxSize(FromDIP(540), FromDIP(380)));
fail_image = wxImage(Slic3r::resources_dir() + "/images/oss_picture_load_failed.png", wxBITMAP_TYPE_ANY);
}
wxBoxSizer *ScoreDialog::get_score_sizer() {
wxBoxSizer *score_sizer = new wxBoxSizer(wxHORIZONTAL);
wxStaticText *static_score_text = new wxStaticText(this, wxID_ANY, _L("Rate"), wxDefaultPosition, wxDefaultSize, 0);
static_score_text->Wrap(-1);
score_sizer->Add(static_score_text, 1, wxEXPAND | wxLEFT, FromDIP(24));
score_sizer->Add(0, 0, 1, wxEXPAND, 0);
return score_sizer;
}
wxBoxSizer *ScoreDialog::get_star_sizer()
{
wxBoxSizer *static_score_star_sizer = new wxBoxSizer(wxHORIZONTAL);
static_score_star_sizer->AddSpacer(FromDIP(20));
m_score_star.resize(5);
for (int i = 0; i < m_score_star.size(); ++i) {
if (!m_success_printed && m_star_count > 3) {
m_star_count = 3;
warning_text->Show();
Layout();
Fit();
}
if (i < m_star_count) {
m_score_star[i] = new ScalableButton(this, wxID_ANY, "score_star_light", wxEmptyString, wxSize(FromDIP(26), FromDIP(26)), wxDefaultPosition,
wxBU_EXACTFIT | wxNO_BORDER, true, 26);
} else
m_score_star[i] = new ScalableButton(this, wxID_ANY, "score_star_dark", wxEmptyString, wxSize(FromDIP(26), FromDIP(26)), wxDefaultPosition,
wxBU_EXACTFIT | wxNO_BORDER, true, 26);
m_score_star[i]->SetMinSize(wxSize(FromDIP(26), FromDIP(26)));
m_score_star[i]->SetMaxSize(wxSize(FromDIP(26), FromDIP(26)));
m_score_star[i]->Bind(wxEVT_LEFT_DOWN, [this, i](auto &e) {
if (!m_success_printed && i >= 3) {
warning_text->Show();
Layout();
Fit();
return;
} else {
warning_text->Hide();
Layout();
Fit();
}
for (int j = 0; j < m_score_star.size(); ++j) {
ScalableBitmap light_star = ScalableBitmap(nullptr, "score_star_light", 26);
m_score_star[j]->SetBitmap(light_star.bmp());
if (m_score_star[j] == m_score_star[i]) {
m_star_count = j + 1;
break;
}
}
for (int k = m_star_count; k < m_score_star.size(); ++k) {
ScalableBitmap dark_star = ScalableBitmap(nullptr, "score_star_dark", 26);
m_score_star[k]->SetBitmap(dark_star.bmp());
}
});
static_score_star_sizer->Add(m_score_star[i], 1, wxEXPAND | wxLEFT, FromDIP(5));
}
return static_score_star_sizer;
}
wxBoxSizer* ScoreDialog::get_comment_text_sizer() {
wxBoxSizer* m_comment_sizer = new wxBoxSizer(wxHORIZONTAL);
wxStaticText *static_comment_text = new wxStaticText(this, wxID_ANY, _L("Comment"), wxDefaultPosition, wxDefaultSize, 0);
static_comment_text->Wrap(-1);
m_comment_sizer->Add(static_comment_text, 1, wxEXPAND | wxLEFT, FromDIP(24));
m_comment_sizer->Add(0, 0, 1, wxEXPAND, 0);
return m_comment_sizer;
}
void ScoreDialog::create_comment_text(const wxString& comment) {
m_comment_text = new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxSize(FromDIP(492), FromDIP(104)), wxTE_MULTILINE);
m_comment_text->SetBackgroundColour(wxColor(*wxWHITE));
if (!comment.empty()) {
m_comment_text->SetValue(comment);
}
m_comment_text->SetHint(_L("Rate this print"));
m_comment_text->SetBackgroundColour(*wxWHITE);
//m_comment_text->SetForegroundColour(wxColor("#BBBBBB"));
m_comment_text->SetMinSize(wxSize(FromDIP(492), FromDIP(104)));
m_comment_text->Bind(wxEVT_SET_FOCUS, [this](auto &event) {
if (wxGetApp().dark_mode()) {
m_comment_text->SetForegroundColour(wxColor(*wxWHITE));
} else
m_comment_text->SetForegroundColour(wxColor(*wxBLACK));
m_comment_text->Refresh();
event.Skip();
});
}
wxBoxSizer *ScoreDialog::get_photo_btn_sizer() {
wxBoxSizer * m_photo_sizer = new wxBoxSizer(wxHORIZONTAL);
ScalableBitmap little_photo = wxGetApp().dark_mode() ? ScalableBitmap(this, "single_little_photo_dark", 20) : ScalableBitmap(this, "single_little_photo", 20);
wxStaticBitmap *little_photo_img = new wxStaticBitmap(this, wxID_ANY, little_photo.bmp(), wxDefaultPosition, wxSize(FromDIP(20), FromDIP(20)), 0);
m_photo_sizer->Add(little_photo_img, 0, wxEXPAND | wxLEFT, FromDIP(24));
m_add_photo = new Label(this, _L("Add Photo"));
m_add_photo->SetBackgroundColour(*wxWHITE);
//m_add_photo->SetForegroundColour(wxColor("#898989"));
m_add_photo->SetSize(wxSize(-1, FromDIP(20)));
m_photo_sizer->Add(m_add_photo, 0, wxEXPAND | wxLEFT, FromDIP(12));
m_delete_photo = new Label(this, _L("Delete Photo"));
m_delete_photo->SetBackgroundColour(*wxWHITE);
//m_delete_photo->SetForegroundColour(wxColor("#898989"));
m_delete_photo->SetSize(wxSize(-1, FromDIP(20)));
m_photo_sizer->Add(m_delete_photo, 0, wxEXPAND | wxLEFT, FromDIP(12));
m_delete_photo->Hide();
m_photo_sizer->Add(0, 0, 1, wxEXPAND, 0);
m_add_photo->Bind(wxEVT_LEFT_DOWN, [this](auto &e) {
// add photo logic
wxFileDialog openFileDialog(this, _L("Select Images"), "", "", _L("Image files (*.png;*.jpg;*jpeg)|*.png;*.jpg;*.jpeg"), wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);
if (openFileDialog.ShowModal() == wxID_CANCEL) return;
wxArrayString filePaths;
openFileDialog.GetPaths(filePaths);
//wxArrayString filePaths_reduction;
std::vector<std::pair<wxString, std::string>> local_path;
for (int i = 0; i < filePaths.GetCount(); i++) { //It's ugly, but useful
bool is_repeat = false;
for (auto image : m_image) {
if (filePaths[i] == image.second.local_image_url) {
is_repeat = true;
continue;
}
}
if (!is_repeat) {
local_path.push_back(std::make_pair(filePaths[i], ""));
if (local_path.size() + m_image.size() > m_photo_nums) {
break;
}
}
}
load_photo(local_path);
m_image_sizer->Layout();
this->Fit();
this->Layout();
});
m_delete_photo->Bind(wxEVT_LEFT_DOWN, [this](auto &e) {
for (auto it = m_selected_image_list.begin(); it != m_selected_image_list.end();) {
auto bitmap = *it;
m_image_sizer->Detach(m_image[bitmap].image_tb_broad);
m_image[bitmap].image_tb_broad->DeleteWindows();
m_image.erase(bitmap);
it = m_selected_image_list.erase(it);
}
m_image_url_paths.clear();
for (const auto& bitmap : m_image) {
if (bitmap.second.is_uploaded) {
if (!bitmap.second.img_url_paths.empty()) {
m_image_url_paths.push_back(bitmap.second.img_url_paths);
}
}
}
m_delete_photo->Hide();
Layout();
Fit();
});
return m_photo_sizer;
}
wxBoxSizer *ScoreDialog::get_button_sizer()
{
wxBoxSizer *bSizer_button = new wxBoxSizer(wxHORIZONTAL);
bSizer_button->Add(0, 0, 1, wxEXPAND, 0);
m_button_ok = new Button(this, _L("Submit"));
m_button_ok->SetStyle(ButtonStyle::Confirm, ButtonType::Choice);
bSizer_button->Add(m_button_ok, 0, wxRIGHT, FromDIP(ButtonProps::ChoiceButtonGap()));
m_button_ok->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) {
m_upload_status_code = StatusCode::UPLOAD_PROGRESS;
if (m_star_count == 0) {
MessageDialog dlg(this, _L("Please click on the star first."), wxString(SLIC3R_APP_FULL_NAME) + " - " + _L("Info"), wxOK);
dlg.ShowModal();
return;
}
std::set<std::pair<wxStaticBitmap *, wxString>> need_upload_images = add_need_upload_imgs();
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": get need upload picture count: " << need_upload_images.size();
std::string comment = into_u8(m_comment_text->GetValue());
unsigned int http_code;
std::string http_error;
wxString error_info;
if (!need_upload_images.empty()) {
std::string config;
int ret = wxGetApp().getAgent()->get_oss_config(config, wxGetApp().app_config->get_country_code(), http_code, http_error);
if (ret == -1) {
error_info += into_u8(_L("Get oss config failed.")) + "\n\thttp code: " + std::to_string(http_code) + "\n\thttp error: " + http_error;
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": get oss config filed and http_error: " << http_error;
m_upload_status_code = StatusCode::UPLOAD_EXIST_ISSUE;
}
if (m_upload_status_code == StatusCode::UPLOAD_PROGRESS) {
int need_upload_nums = need_upload_images.size();
int upload_nums = 0;
int upload_failed_nums = 0;
ProgressDialog *progress_dialog = new ProgressDialog(_L("Upload Pictures"), _L("Number of images successfully uploaded") + ": " + std::to_string(upload_nums) + "/" + std::to_string(need_upload_nums), need_upload_nums, this);
for (std::set<std::pair<wxStaticBitmap *, wxString>>::iterator it = need_upload_images.begin(); it != need_upload_images.end();) {
std::pair<wxStaticBitmap *, wxString> need_upload = *it;
std::string need_upload_uf8 = into_u8(need_upload.second);
//Local path when incoming, cloud path when outgoing
ret = wxGetApp().getAgent()->put_rating_picture_oss(config, need_upload_uf8, m_model_id, m_profile_id, http_code, http_error);
std::unordered_map<wxStaticBitmap *, ImageMsg>::iterator iter;
switch (ret) {
case 0:
upload_nums++;
iter = m_image.find(need_upload.first);
if (m_image.end() != iter) {
iter->second.img_url_paths = need_upload_uf8;
iter->second.is_uploaded = true;
m_image_url_paths.push_back(need_upload_uf8);
}
it++;
progress_dialog->Update(upload_nums, _L("Number of images successfully uploaded") + ": " + std::to_string(upload_nums) + "/" + std::to_string(need_upload_nums));
progress_dialog->Fit();
BOOST_LOG_TRIVIAL(info) << "put_rating_picture_oss: model_id [" << m_model_id << "] profile_id [" << m_profile_id << "] http_code [" << http_code
<< "] http_error [" << http_error << "] config [" << config << "] image_path [" << need_upload.second << "]";
break;
case -1:
error_info += need_upload.second + _L(" upload failed").ToUTF8().data() + "\n\thttp code:" + std::to_string(http_code) + "\n\thttp_error:" + http_error + "\n";
m_upload_status_code = StatusCode::UPLOAD_IMG_FAILED;
++it;
break;
case BAMBU_NETWORK_ERR_PARSE_CONFIG_FAILED:
error_info += need_upload.second + _L(" upload config prase failed\n").ToUTF8().data() + "\n";
m_upload_status_code = StatusCode::UPLOAD_IMG_FAILED;
++it;
break;
case BAMBU_NETWORK_ERR_NO_CORRESPONDING_BUCKET:
error_info += need_upload.second + _L(" No corresponding storage bucket\n").ToUTF8().data() + "\n";
m_upload_status_code = StatusCode::UPLOAD_IMG_FAILED;
++it;
break;
case BAMBU_NETWORK_ERR_OPEN_FILE_FAILED:
error_info += need_upload.second + _L(" cannot be opened\n").ToUTF8().data() + "\n";
m_upload_status_code = StatusCode::UPLOAD_IMG_FAILED;
++it;
break;
}
}
progress_dialog->Hide();
if (progress_dialog) {
delete progress_dialog;
progress_dialog = nullptr;
}
if (m_upload_status_code == StatusCode::UPLOAD_IMG_FAILED) {
std::string upload_failed_images = into_u8(_L("The following issues occurred during the process of uploading images. Do you want to ignore them?\n\n"));
MessageDialog dlg_info(this, upload_failed_images + error_info, wxString(_L("info")), wxOK | wxNO | wxCENTER);
if (dlg_info.ShowModal() == wxID_OK) {
m_upload_status_code = StatusCode::UPLOAD_PROGRESS;
}
}
}
}
if (m_upload_status_code == StatusCode::UPLOAD_PROGRESS) {
int ret = wxGetApp().getAgent()->put_model_mall_rating(m_rating_id, m_star_count, comment, m_image_url_paths, http_code, http_error);
MessageDialog *dlg_info;
switch (ret) {
case 0: EndModal(wxID_OK); break;
case BAMBU_NETWORK_ERR_GET_RATING_ID_FAILED:
dlg_info = new MessageDialog(this, _L("Synchronizing the printing results. Please retry a few seconds later."), wxString(_L("info")), wxOK | wxCENTER);
dlg_info->ShowModal();
delete dlg_info;
break;
default: // Upload failed and obtaining instance_id failed
if (ret == -1)
error_info += _L("Upload failed\n").ToUTF8().data();
else
error_info += _L("Obtaining instance_id failed\n").ToUTF8().data();
if (!error_info.empty()) { BOOST_LOG_TRIVIAL(info) << error_info; }
dlg_info = new MessageDialog(this,
_L("Your comment result cannot be uploaded due to the following reasons:\n\n error code: ") +
std::to_string(http_code) + "\n " + _L("error message: ") + http_error +
_L("\n\nWould you like to redirect to the webpage to give a rating?"),
wxString(_L("info")), wxOK | wxNO | wxCENTER);
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": upload rating picture failed and http error" << http_error;
if (dlg_info->ShowModal() == wxID_OK) {
market_model_scoring_page(m_design_id);
EndModal(wxID_OK);
}
delete dlg_info;
break;
}
} else if (m_upload_status_code == StatusCode::UPLOAD_IMG_FAILED) {
MessageDialog *dlg_info = new MessageDialog(this,
_L("Some of your images failed to upload. Would you like to redirect to the webpage to give a rating?"),
wxString(_L("info")), wxOK | wxNO | wxCENTER);
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": upload rating picture failed or get oss config failed";
if (dlg_info->ShowModal() == wxID_OK) {
market_model_scoring_page(m_design_id);
EndModal(wxID_OK);
}
delete dlg_info;
if (!error_info.empty()) { BOOST_LOG_TRIVIAL(info) << error_info; }
}
});
m_button_cancel = new Button(this, _L("Cancel"));
m_button_cancel->SetStyle(ButtonStyle::Regular, ButtonType::Choice);
bSizer_button->Add(m_button_cancel, 0, wxRIGHT, FromDIP(ButtonProps::ChoiceButtonGap()));
m_button_cancel->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) { EndModal(wxID_CANCEL); });
return bSizer_button;
}
void ScoreDialog::load_photo(const std::vector<std::pair<wxString, std::string>> &filePaths)
{
for (size_t i = 0; i < filePaths.size(); ++i) {
if (m_image.size() < m_photo_nums) {
std::pair<wxString, std::string> local_to_url_path = filePaths[i];
wxString filePath = local_to_url_path.first;
ImageMsg cur_image_msg;
if (filePath.empty()) { // local img path is empty, oss url path is exist
std::string oss_url_path = local_to_url_path.second;
//to do: load oss image, create wxStaticBitmap
if (!oss_url_path.empty()) {
m_image.insert(create_oss_thumbnail(oss_url_path));
}
continue;
} else {
m_image.insert(create_local_thumbnail(filePath));
}
} else {
MessageDialog *dlg_info_up_to_8 = new MessageDialog(this, _L("You can select up to 16 images."), wxString(_L("info")), wxOK | wxCENTER);
dlg_info_up_to_8->ShowModal();
break;
}
}
}
wxBoxSizer *ScoreDialog::get_main_sizer(const std::vector<std::pair<wxString, std::string>> &images, const wxString &comment)
{
init();
wxBoxSizer *m_main_sizer = new wxBoxSizer(wxVERTICAL);
// top line
auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL);
m_line_top->SetBackgroundColour(wxColour(0xA6, 0xa9, 0xAA));
m_main_sizer->Add(m_line_top, 0, wxEXPAND, 0);
m_main_sizer->Add(0, 0, 0, wxTOP, FromDIP(32));
warning_text = new wxStaticText(this, wxID_ANY, _L("At least one successful print record of this print profile is required \nto give a positive rating (4 or 5 stars)."));
warning_text->SetForegroundColour(*wxRED);
warning_text->SetFont(::Label::Body_13);
wxBoxSizer *score_sizer = get_score_sizer();
m_main_sizer->Add(score_sizer, 0, wxEXPAND, FromDIP(20));
m_main_sizer->Add(0, 0, 0, wxBOTTOM, FromDIP(8));
wxBoxSizer *static_score_star_sizer = get_star_sizer();
m_main_sizer->Add(static_score_star_sizer, 1, wxEXPAND | wxBOTTOM, FromDIP(20));
m_main_sizer->Add(warning_text, 0, wxEXPAND | wxLEFT, FromDIP(24));
m_main_sizer->Add(0, 0, 0, wxBOTTOM, FromDIP(8));
warning_text->Hide();
wxBoxSizer *m_comment_sizer = get_comment_text_sizer();
m_main_sizer->Add(m_comment_sizer, 0, wxEXPAND, FromDIP(20));
m_main_sizer->Add(0, 0, 0, wxBOTTOM, FromDIP(8));
create_comment_text(comment);
m_main_sizer->Add(m_comment_text, 0, wxLEFT, FromDIP(24));
wxBoxSizer *m_photo_sizer = get_photo_btn_sizer();
m_main_sizer->Add(m_photo_sizer, 0, wxEXPAND | wxTOP, FromDIP(8));
m_image_sizer = new wxGridSizer(5, FromDIP(5), FromDIP(5));
if (!images.empty()) {
load_photo(images);
}
m_main_sizer->Add(m_image_sizer, 0, wxEXPAND | wxLEFT, FromDIP(24));
m_main_sizer->Add(0, 0, 1, wxEXPAND, 0);
wxBoxSizer *bSizer_button = get_button_sizer();
m_main_sizer->Add(bSizer_button, 0, wxEXPAND | wxBOTTOM, FromDIP(24));
return m_main_sizer;
}
ScoreData ScoreDialog::get_score_data() {
ScoreData score_data;
score_data.rating_id = m_rating_id;
score_data.design_id = m_design_id;
score_data.model_id = m_model_id;
score_data.profile_id = m_profile_id;
score_data.star_count = m_star_count;
score_data.success_printed = m_success_printed;
score_data.comment_text = m_comment_text->GetValue();
score_data.image_url_paths = m_image_url_paths;
for (auto img : m_image) { score_data.local_to_url_image.push_back(std::make_pair(img.second.local_image_url, img.second.img_url_paths)); }
return score_data;
}
void ScoreDialog::set_comment(std::string comment)
{
if (m_comment_text) {
m_comment_text->SetValue(wxString::FromUTF8(comment));
}
}
void ScoreDialog::set_cloud_bitmap(std::vector<std::string> cloud_bitmaps)
{
m_image_url_paths = cloud_bitmaps;
for (std::string &url : cloud_bitmaps) {
if (std::string::npos == url.find(m_model_id)) continue;
m_image.insert(create_oss_thumbnail(url));
}
Layout();
Fit();
}
} // namespace GUI
} // namespace Slic3r