Files
OrcaSlicer/src/slic3r/GUI/StatusPanel.hpp
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

852 lines
31 KiB
C++

#ifndef slic3r_StatusPanel_hpp_
#define slic3r_StatusPanel_hpp_
#include "libslic3r/ProjectTask.hpp"
#include "DeviceManager.hpp"
#include "MonitorPage.hpp"
#include "SliceInfoPanel.hpp"
#include "CameraPopup.hpp"
#include "GUI.hpp"
#include "ThermalPreconditioningDialog.hpp"
#include <wx/panel.h>
#include <wx/bitmap.h>
#include <wx/image.h>
#include <wx/sizer.h>
#include <wx/gbsizer.h>
#include <wx/webrequest.h>
#include <memory>
#include "MediaPlayCtrl.h"
#include "WebMediaController.hpp"
#include "AMSSetting.hpp"
#include "Calibration.hpp"
#include "CalibrationWizardPage.hpp"
#include "PrintOptionsDialog.hpp"
#include "SafetyOptionsDialog.hpp"
#include "AMSMaterialsSetting.hpp"
#include "ExtrusionCalibration.hpp"
#include "ReleaseNote.hpp"
#include "Widgets/SwitchButton.hpp"
#include "Widgets/AxisCtrlButton.hpp"
#include "Widgets/TextInput.hpp"
#include "Widgets/TempInput.hpp"
#include "Widgets/StaticLine.hpp"
#include "Widgets/ProgressBar.hpp"
#include "Widgets/ImageSwitchButton.hpp"
#include "Widgets/AMSControl.hpp"
#include "Widgets/FilamentLoad.hpp"
#include "Widgets/FanControl.hpp"
#include "HMS.hpp"
#include "PartSkipDialog.hpp"
#include "DeviceErrorDialog.hpp"
#include "StagedBuild.hpp"
class StepIndicator;
#define COMMAND_TIMEOUT 5
namespace Slic3r {
class DevExtderSystem;
namespace GUI {
// Previous definitions
class MessageDialog;
class wgtDeviceNozzleRack;
enum CameraRecordingStatus {
RECORDING_NONE,
RECORDING_OFF_NORMAL,
RECORDING_OFF_HOVER,
RECORDING_ON_NORMAL,
RECORDING_ON_HOVER,
};
enum CameraTimelapseStatus {
TIMELAPSE_NONE,
TIMELAPSE_OFF_NORMAL,
TIMELAPSE_OFF_HOVER,
TIMELAPSE_ON_NORMAL,
TIMELAPSE_ON_HOVER,
};
enum PrintingTaskType {
PRINGINT,
CALIBRATION,
NOT_CLEAR
};
enum ExtruderState {
FILLED_LOAD,
FILLED_UNLOAD,
EMPTY_LOAD,
EMPTY_UNLOAD
};
struct ScoreData
{
int rating_id;
int design_id;
std::string model_id;
int profile_id;
int star_count;
bool success_printed;
wxString comment_text;
std::vector<std::string> image_url_paths;
std::set<wxString> need_upload_images;
std::vector<std::pair<wxString, std::string>> local_to_url_image;
};
typedef std::function<void(BBLModelTask* subtask)> OnGetSubTaskFn;
class ExtruderImage : public wxWindow
{
ScalableBitmap *m_pipe_filled_load;
ScalableBitmap *m_pipe_filled_unload;
ScalableBitmap *m_pipe_empty_load;
ScalableBitmap *m_pipe_empty_unload;
ScalableBitmap *m_pipe_filled_load_unselected;
ScalableBitmap *m_pipe_filled_unload_unselected;
ScalableBitmap *m_pipe_empty_load_unselected;
ScalableBitmap *m_pipe_empty_unload_unselected;
ScalableBitmap *m_left_extruder_active_filled;
ScalableBitmap *m_left_extruder_active_empty;
ScalableBitmap *m_left_extruder_unactive_filled;
ScalableBitmap *m_left_extruder_unactive_empty;
ScalableBitmap *m_right_extruder_active_filled;
ScalableBitmap *m_right_extruder_active_empty;
ScalableBitmap *m_right_extruder_unactive_filled;
ScalableBitmap *m_right_extruder_unactive_empty;
ScalableBitmap *m_extruder_single_nozzle_empty_load;
ScalableBitmap *m_extruder_single_nozzle_empty_unload;
ScalableBitmap *m_extruder_single_nozzle_filled_load;
ScalableBitmap *m_extruder_single_nozzle_filled_unload;
ExtruderState m_left_ext_state = {ExtruderState::EMPTY_LOAD};
ExtruderState m_right_ext_state = {ExtruderState::EMPTY_LOAD};
ExtruderState m_single_ext_state = {ExtruderState::EMPTY_LOAD};
public:
void update(int nozzle_num, int nozzle_id);
void update(ExtruderState single_state);
void update(ExtruderState right_state, ExtruderState left_state);
void msw_rescale();
void setExtruderCount(int nozzle_num);
void setExtruderUsed(std::string loc);
void paintEvent(wxPaintEvent &evt);
void render(wxDC &dc);
bool m_show_state = {false};
int m_nozzle_num = 1;
int current_nozzle_idx = 0;
std::string current_nozzle_loc = "";
wxColour m_colour;
string m_file_name;
bool m_ams_loading{false};
void doRender(wxDC &dc);
ExtruderImage(wxWindow *parent, wxWindowID id, int nozzle_num, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize);
~ExtruderImage();
};
class ExtruderSwithingStatus : public wxPanel
{
public:
ExtruderSwithingStatus(wxWindow *parent);
~ExtruderSwithingStatus() = default;
public:
void updateBy(MachineObject *obj);
bool has_content_shown() const;
void msw_rescale();
private:
void updateBy(const DevExtderSystem* ext_system);
void showQuitBtn(bool show);
void showRetryBtn(bool show);
void on_quit(wxCommandEvent &event);
void on_retry(wxCommandEvent &event);
private:
MachineObject *m_obj = nullptr;
Label *m_switching_status_label = nullptr;
Button *m_button_quit = nullptr;
Button *m_button_retry = nullptr;
/*the last control time*/
time_t m_last_ctrl_time = 0;
};
class ScoreDialog : public GUI::DPIDialog
{
public:
ScoreDialog(wxWindow *parent, int design_id, std::string model_id, int profile_id, int rating_id, bool success_printed, int star_count = 0);
ScoreDialog(wxWindow *parent, ScoreData *score_data);
~ScoreDialog();
int get_rating_id() { return m_rating_id; }
ScoreData get_score_data();
void set_comment(std::string comment);
void set_cloud_bitmap(std::vector<std::string> cloud_bitmaps);
protected:
enum StatusCode {
UPLOAD_PROGRESS = 0,
UPLOAD_EXIST_ISSUE,
UPLOAD_IMG_FAILED,
CODE_NUMBER
};
std::shared_ptr<int> m_tocken;
const int m_photo_nums = 16;
int m_rating_id;
int m_design_id;
std::string m_model_id;
int m_profile_id;
int m_star_count;
bool m_success_printed;
std::vector<std::string> m_image_url_paths;
StatusCode m_upload_status_code;
struct ImageMsg
{
wxString local_image_url; //local image path
std::string img_url_paths; // oss url path
vector<wxPanel *> image_broad;
bool is_selected;
bool is_uploaded; // load
wxBoxSizer * image_tb_broad = nullptr;
};
std::vector<ScalableButton *> m_score_star;
wxTextCtrl * m_comment_text = nullptr;
Button * m_button_ok = nullptr;
Button * m_button_cancel = nullptr;
Label * m_add_photo = nullptr;
Label * m_delete_photo = nullptr;
wxGridSizer * m_image_sizer = nullptr;
wxStaticText * warning_text = nullptr;
std::unordered_map<wxStaticBitmap *, ImageMsg> m_image;
std::unordered_set<wxStaticBitmap *> m_selected_image_list;
void init();
void update_static_bitmap(wxStaticBitmap *static_bitmap, wxImage image);
void create_comment_text(const wxString &comment = "");
void load_photo(const std::vector<std::pair<wxString, std::string>> &filePaths);
void on_dpi_changed(const wxRect &suggested_rect) override;
void OnBitmapClicked(wxMouseEvent &event);
wxBoxSizer * create_broad_sizer(wxStaticBitmap *bitmap, ImageMsg &cur_image_msg);
wxBoxSizer * get_score_sizer();
wxBoxSizer * get_star_sizer();
wxBoxSizer * get_comment_text_sizer();
wxBoxSizer * get_photo_btn_sizer();
wxBoxSizer * get_button_sizer();
wxBoxSizer * get_main_sizer(const std::vector<std::pair<wxString, std::string>> &images = std::vector<std::pair<wxString, std::string>>(), const wxString &comment = "");
std::set<std::pair<wxStaticBitmap *, wxString>> add_need_upload_imgs();
std::pair<wxStaticBitmap *, ImageMsg> create_local_thumbnail(wxString &local_path);
std::pair<wxStaticBitmap *, ImageMsg> create_oss_thumbnail(std::string &oss_path);
};
class PrintingTaskPanel : public wxPanel
{
public:
PrintingTaskPanel(wxWindow* parent, PrintingTaskType type);
~PrintingTaskPanel();
void create_panel(wxWindow* parent);
private:
MachineObject* m_obj{nullptr};
ScalableBitmap m_thumbnail_placeholder;
std::string m_thumbnail_bmp_display_name;
wxBitmap m_thumbnail_bmp_display;
ScalableBitmap m_bitmap_use_time;
ScalableBitmap m_bitmap_use_weight;
ScalableBitmap m_bitmap_background;
wxPanel * m_panel_printing_title;
wxPanel* m_staticline;
wxPanel* m_panel_error_txt;
wxBoxSizer* m_printing_sizer;
wxStaticText * m_staticText_printing;
wxStaticText* m_staticText_subtask_value;
wxStaticText* m_staticText_consumption_of_time;
wxStaticText* m_staticText_consumption_of_weight;
wxStaticText* m_printing_stage_value;
ScalableButton* m_question_button;
wxStaticText* m_staticText_profile_value;
wxStaticText* m_staticText_progress_percent;
wxStaticText* m_staticText_progress_percent_icon;
wxStaticText* m_staticText_progress_left;
// Orca: show print end time
wxStaticText * m_staticText_progress_end;
wxStaticText* m_staticText_layers;
wxStaticText * m_has_rated_prompt;
wxStaticText * m_request_failed_info;
wxStaticBitmap* m_bitmap_thumbnail;
int m_plate_index { -1 };
wxStaticBitmap* m_bitmap_static_use_time;
wxStaticBitmap* m_bitmap_static_use_weight;
ScalableButton* m_button_pause_resume;
ScalableButton* m_button_abort;
Button* m_button_partskip;
Button* m_button_market_scoring;
Button* m_button_clean;
Button * m_button_market_retry;
wxPanel * m_score_subtask_info;
wxPanel * m_score_staticline;
wxPanel * m_request_failed_panel;
wxPanel *m_printing_stage_underline;
wxPanel *m_printing_stage_panel;
// score page
int m_star_count;
std::vector<ScalableButton *> m_score_star;
bool m_star_count_dirty = false;
// partskip button
int m_part_skipped_count{ 0 };
int m_part_skipped_dirty{ 0 };
ProgressBar* m_gauge_progress;
Label* m_error_text;
PrintingTaskType m_type;
int m_brightness_value{ -1 };
public:
void init_bitmaps();
void init_scaled_buttons();
void error_info_reset();
void show_error_msg(wxString msg);
void reset_printing_value();
void msw_rescale();
public:
void enable_partskip_button(MachineObject* obj, bool enable);
void enable_pause_resume_button(bool enable, std::string type);
void enable_abort_button(bool enable);
void update_subtask_name(wxString name);
void update_stage_value(wxString stage, int val);
void update_stage_value_with_machine(wxString stage, int val, MachineObject* obj = nullptr);
void on_stage_clicked(wxMouseEvent& event);
// Public interface to update remaining time text in the thermal dialog
void update_thermal_remaining_time(MachineObject* obj);
void update_progress_percent(wxString percent, wxString icon);
void update_left_time(wxString time);
void update_left_time(int mc_left_time);
void show_layers_num(bool show) { m_staticText_layers->Show(show); }
void update_layers_num(bool show, wxString num = wxEmptyString);
void show_priting_use_info(bool show, wxString time = wxEmptyString, wxString weight = wxEmptyString);
void show_profile_info(bool show, wxString profile = wxEmptyString);
void set_thumbnail_img(const wxBitmap& bmp, const std::string& bmp_name);
void set_brightness_value(int value) { m_brightness_value = value; }
void set_plate_index(int plate_idx = -1);
void market_scoring_show();
void market_scoring_hide();
public:
ScalableButton* get_abort_button() {return m_button_abort;};
ScalableButton* get_pause_resume_button() {return m_button_pause_resume;};
Button* get_partskip_button() { return m_button_partskip; };
Button* get_market_scoring_button() {return m_button_market_scoring;};
Button * get_market_retry_buttom() { return m_button_market_retry; };
Button* get_clean_button() {return m_button_clean;};
wxStaticBitmap* get_bitmap_thumbnail() {return m_bitmap_thumbnail;};
wxPanel * get_request_failed_panel() { return m_request_failed_panel; }
int get_star_count() { return m_star_count; }
void set_star_count(int star_count);
std::vector<ScalableButton *> &get_score_star() { return m_score_star; }
bool get_star_count_dirty() { return m_star_count_dirty; }
void set_star_count_dirty(bool dirty) { m_star_count_dirty = dirty; }
int get_part_skipped_count() { return m_part_skipped_count; }
void set_part_skipped_count(int count) { m_part_skipped_count = count; }
int get_part_skipped_dirty() { return m_part_skipped_dirty; }
void set_part_skipped_dirty(int dirty) { m_part_skipped_dirty = dirty; }
void set_has_reted_text(bool has_rated);
void paint(wxPaintEvent&);
};
class StatusBasePanel : public wxScrolledWindow, public StagedBuild
{
protected:
wxBitmap m_item_placeholder;
ScalableBitmap m_thumbnail_placeholder;
ScalableBitmap m_thumbnail_brokenimg;
ScalableBitmap m_thumbnail_sdcard;
wxBitmap m_bitmap_item_prediction;
wxBitmap m_bitmap_item_cost;
wxBitmap m_bitmap_item_print;
ScalableBitmap m_bitmap_speed;
ScalableBitmap m_bitmap_speed_active;
ScalableBitmap m_bitmap_axis_home;
ScalableBitmap m_bitmap_lamp_on;
ScalableBitmap m_bitmap_lamp_off;
ScalableBitmap m_bitmap_fan_on;
ScalableBitmap m_bitmap_fan_off;
ScalableBitmap m_bitmap_use_time;
ScalableBitmap m_bitmap_use_weight;
wxBitmap m_bitmap_extruder_empty_load;
wxBitmap m_bitmap_extruder_filled_load;
wxBitmap m_bitmap_extruder_empty_unload;
wxBitmap m_bitmap_extruder_filled_unload;
wxBitmap m_bitmap_extruder_now;
CameraRecordingStatus m_state_recording{CameraRecordingStatus::RECORDING_NONE};
CameraTimelapseStatus m_state_timelapse{CameraTimelapseStatus::TIMELAPSE_NONE};
CameraItem *m_setting_button;
wxBitmap m_bitmap_camera;
ScalableBitmap m_bitmap_sdcard_state_normal;
ScalableBitmap m_bitmap_sdcard_state_abnormal;
ScalableBitmap m_bitmap_sdcard_state_no;
ScalableBitmap m_bitmap_recording_on;
ScalableBitmap m_bitmap_recording_off;
ScalableBitmap m_bitmap_timelapse_on;
ScalableBitmap m_bitmap_timelapse_off;
ScalableBitmap m_bitmap_vcamera_on;
ScalableBitmap m_bitmap_vcamera_off;
ScalableBitmap m_bitmap_switch_camera;
/* title panel */
wxPanel * media_ctrl_panel;
wxPanel * m_panel_monitoring_title;
wxPanel * m_panel_printing_title;
wxPanel * m_panel_control_title;
wxStaticText* m_staticText_consumption_of_time;
wxStaticText * m_staticText_consumption_of_weight;
Label * m_staticText_monitoring;
wxStaticText * m_staticText_timelapse;
SwitchButton * m_bmToggleBtn_timelapse;
wxStaticText *m_mqtt_source;
wxStaticBitmap *m_bitmap_camera_img;
wxStaticBitmap *m_bitmap_recording_img;
wxStaticBitmap *m_bitmap_timelapse_img;
wxStaticBitmap* m_bitmap_vcamera_img;
wxStaticBitmap *m_bitmap_sdcard_img;
wxStaticBitmap *m_bitmap_static_use_time;
wxStaticBitmap *m_bitmap_static_use_weight;
// wxStaticBitmap* m_camera_switch_button;
wxMediaCtrl3 * m_media_ctrl;
MediaPlayCtrl * m_media_play_ctrl{nullptr};
Label * m_staticText_printing;
wxStaticBitmap *m_bitmap_thumbnail;
wxStaticText * m_staticText_subtask_value;
wxStaticText * m_printing_stage_value;
wxStaticText * m_staticText_profile_value;
ProgressBar* m_gauge_progress;
wxStaticText * m_staticText_progress_percent;
wxStaticText * m_staticText_progress_percent_icon;
wxStaticText * m_staticText_progress_left;
wxStaticText * m_staticText_layers;
Button * m_button_report;
Button * m_button_partskip;
ScalableButton *m_button_pause_resume;
ScalableButton *m_button_abort;
Button * m_button_clean;
wxWebView * m_custom_camera_view{nullptr};
std::unique_ptr<WebMediaController> m_web_media_controller;
wxSimplebook* m_extruder_book;
std::vector<ExtruderImage *> m_extruderImage;
SwitchBoard * m_nozzle_btn_panel;
wxStaticText * m_text_tasklist_caption;
Label * m_staticText_control;
ImageSwitchButton *m_switch_lamp;
int m_switch_lamp_timeout{0};
ImageSwitchButton *m_switch_speed;
/* TempInput */
wxBoxSizer * m_misc_ctrl_sizer;
StaticBox* m_fan_panel;
StaticLine * m_line_nozzle;
TempInput* m_tempCtrl_nozzle;
int m_temp_nozzle_timeout{ 0 };
TempInput* m_tempCtrl_nozzle_deputy;
int m_temp_nozzle_deputy_timeout{ 0 };
TempInput * m_tempCtrl_bed;
int m_temp_bed_timeout {0};
TempInput * m_tempCtrl_chamber;
int m_temp_chamber_timeout {0};
FanSwitchButton *m_switch_nozzle_fan;
int m_switch_nozzle_fan_timeout{0};
FanSwitchButton *m_switch_printing_fan;
int m_switch_printing_fan_timeout{0};
FanSwitchButton *m_switch_cham_fan;
FanSwitchButton *m_switch_fan;
int m_switch_cham_fan_timeout{0};
wxPanel* m_switch_block_fan;
int m_nozzle_num{ 0 };
int m_current_nozzle_id{ 0 };
float m_fixed_aspect_ratio{1.8};
AxisCtrlButton *m_bpButton_xy;
//wxStaticText * m_staticText_xy;
Button * m_bpButton_z_10;
Button * m_bpButton_z_1;
Button * m_bpButton_z_down_1;
Button * m_bpButton_z_down_10;
//Button * m_button_unload;
wxStaticText * m_staticText_z_tip;
Label * m_extruder_label;
Button * m_bpButton_e_10;
Button * m_bpButton_e_down_10;
ExtruderSwithingStatus *m_extruder_switching_status;
wxPanel * m_temp_temp_line;
wxPanel * m_temp_extruder_line;
wxBoxSizer* m_ams_list;
wxStaticText * m_ams_debug;
bool m_show_ams_group{false};
bool m_show_filament_group{ false };
/* AMS control box <-> live nozzle-rack panel toggle (rack printers only) */
SwitchBoard* m_ams_rack_switch{ nullptr };
AMSControl* m_ams_control;
StaticBox* m_ams_control_box;
wxStaticBitmap *m_ams_extruder_img;
wxStaticBitmap* m_bitmap_extruder_img;
wgtDeviceNozzleRack* m_panel_nozzle_rack{ nullptr };
wxPanel * m_panel_separator_right;
wxPanel * m_panel_separotor_bottom;
wxGridBagSizer *m_tasklist_info_sizer{nullptr};
wxBoxSizer * m_printing_sizer;
wxBoxSizer * m_tasklist_sizer;
wxBoxSizer * m_tasklist_caption_sizer;
wxPanel* m_panel_error_txt;
wxPanel* m_staticline;
Label * m_error_text;
wxStaticText* m_staticText_calibration_caption;
wxStaticText* m_staticText_calibration_caption_top;
wxStaticText* m_calibration_text;
Button* m_parts_btn;
Button* m_options_btn;
Button* m_safety_btn;
Button* m_calibration_btn;
StepIndicator* m_calibration_flow;
wxPanel * m_machine_ctrl_panel;
wxPanel * m_scale_panel;
wxStaticBitmap* m_img_filament_loading;
PrintingTaskPanel * m_project_task_panel;
FilamentLoad* m_filament_step;
wxStaticBitmap *m_filament_load_img;
Button *m_button_retry {nullptr};
Button *m_fila_change_abort {nullptr}; // Orca: filament-change Stop button
StaticBox* m_filament_load_box;
// Virtual event handlers, override them in your derived class
virtual void on_subtask_partskip(wxCommandEvent &event) { event.Skip(); }
virtual void on_subtask_pause_resume(wxCommandEvent &event) { event.Skip(); }
virtual void on_subtask_abort(wxCommandEvent &event) { event.Skip(); }
virtual void on_lamp_switch(wxCommandEvent &event) { event.Skip(); }
virtual void on_bed_temp_kill_focus(wxFocusEvent &event) { event.Skip(); }
virtual void on_bed_temp_set_focus(wxFocusEvent &event) { event.Skip(); }
virtual void on_nozzle_temp_kill_focus(wxFocusEvent &event) { event.Skip(); }
virtual void on_nozzle_temp_set_focus(wxFocusEvent &event) { event.Skip(); }
virtual void on_nozzle_fan_switch(wxCommandEvent &event) { event.Skip(); }
virtual void on_printing_fan_switch(wxCommandEvent &event) { event.Skip(); }
virtual void on_axis_ctrl_z_up_10(wxCommandEvent &event) { event.Skip(); }
virtual void on_axis_ctrl_z_up_1(wxCommandEvent &event) { event.Skip(); }
virtual void on_axis_ctrl_z_down_1(wxCommandEvent &event) { event.Skip(); }
virtual void on_axis_ctrl_z_down_10(wxCommandEvent &event) { event.Skip(); }
virtual void on_axis_ctrl_e_up_10(wxCommandEvent &event) { event.Skip(); }
virtual void on_axis_ctrl_e_down_10(wxCommandEvent &event) { event.Skip(); }
virtual void on_nozzle_selected(wxCommandEvent &event) { event.Skip(); }
void remove_controls();
void on_webview_navigating(wxWebViewEvent& evt);
public:
StatusBasePanel(wxWindow * parent,
wxWindowID id = wxID_ANY,
const wxPoint & pos = wxDefaultPosition,
const wxSize & size = wxDefaultSize,
long style = wxTAB_TRAVERSAL,
const wxString &name = wxEmptyString);
~StatusBasePanel();
MachineObject* obj{nullptr};
void init_bitmaps();
wxBoxSizer *create_monitoring_page();
wxBoxSizer *create_machine_control_page(wxWindow *parent);
wxBoxSizer *create_temp_axis_group(wxWindow *parent);
wxBoxSizer *create_temp_control(wxWindow *parent);
wxBoxSizer *create_misc_control(wxWindow *parent);
wxBoxSizer *create_axis_control(wxWindow *parent);
wxPanel *create_bed_control(wxWindow *parent);
wxBoxSizer *create_extruder_control(wxWindow *parent);
void reset_temp_misc_control();
int before_error_code = 0;
int skip_print_error = 0;
wxBoxSizer *create_ams_group(wxWindow *parent);
wxBoxSizer *create_settings_group(wxWindow *parent);
wxBoxSizer* create_filament_group(wxWindow* parent);
void expand_filament_loading(wxMouseEvent &e);
void show_ams_group(bool show = true);
void show_filament_load_group(bool show = true);
MediaPlayCtrl* get_media_play_ctrl() {return m_media_play_ctrl;};
void jump_to_Rack();
private:
void on_ams_rack_switch(wxCommandEvent& event);
};
class StatusPanel : public StatusBasePanel
{
private:
friend class MonitorPanel;
void wire_controls();
bool load_thumbnail_from_url(const wxString &url, MachineObject *obj);
protected:
std::shared_ptr<SliceInfoPopup> m_slice_info_popup;
std::shared_ptr<ImageTransientPopup> m_image_popup;
std::shared_ptr<CameraPopup> m_camera_popup;
std::set<int> rated_model_id;
AMSSetting *m_ams_setting_dlg{nullptr};
PrinterPartsDialog* print_parts_dlg { nullptr };
PrintOptionsDialog* print_options_dlg { nullptr };
SafetyOptionsDialog* safety_options_dlg { nullptr };
CalibrationDialog* calibration_dlg {nullptr};
AMSMaterialsSetting *m_filament_setting_dlg{nullptr};
DeviceErrorDialog* m_print_error_dlg = nullptr;
SecondaryCheckDialog* abort_dlg = nullptr;
SecondaryCheckDialog* con_load_dlg = nullptr;
MessageDialog * ctrl_e_hint_dlg = nullptr;
SecondaryCheckDialog* sdcard_hint_dlg = nullptr;
FanControlPopupNew* m_fan_control_popup{nullptr};
ExtrusionCalibration *m_extrusion_cali_dlg{nullptr};
PartSkipDialog *m_partskip_dlg{nullptr};
wxString m_request_url;
bool m_start_loading_thumbnail = false;
bool m_load_sdcard_thumbnail = false;
int m_last_sdcard = -1;
int m_last_recording = -1;
int m_last_timelapse = -1;
int m_last_extrusion = -1;
int m_last_vcamera = -1;
int m_model_mall_request_count = 0;
bool m_is_load_with_temp = false;
json m_rating_result;
wxWebRequest web_request;
bool bed_temp_input = false;
bool nozzle_temp_input = false;
bool cham_temp_input = false;
bool request_model_info_flag = false;
int speed_lvl = 1; // 0 - 3
int speed_lvl_timeout {0};
boost::posix_time::ptime speed_dismiss_time;
bool m_show_mode_changed = false;
std::map<wxString, wxImage> img_list; // key: url, value: wxBitmap png Image
std::map<std::string, std::string> m_print_connect_types;
std::vector<Button *> m_buttons;
int last_status;
ScoreData *m_score_data = nullptr;
wxBitmap* calib_bitmap = nullptr;
CalibMode m_calib_mode;
CalibrationMethod m_calib_method;
int cali_stage;
PrintingTaskType m_current_print_mode = PrintingTaskType::NOT_CLEAR;
void init_scaled_buttons();
void create_tasklist_info();
void show_task_list_info(bool show = true);
void update_tasklist_info();
void on_market_scoring(wxCommandEvent &event);
void on_market_retry(wxCommandEvent &event);
void on_subtask_partskip(wxCommandEvent &event);
void on_subtask_pause_resume(wxCommandEvent &event);
void on_subtask_abort(wxCommandEvent &event);
void on_print_error_clean(wxCommandEvent &event);
void error_info_reset();
void show_recenter_dialog();
/* axis control */
bool check_axis_z_at_home(MachineObject* obj);
void on_axis_ctrl_xy(wxCommandEvent &event);
void on_axis_ctrl_z_up_10(wxCommandEvent &event);
void on_axis_ctrl_z_up_1(wxCommandEvent &event);
void on_axis_ctrl_z_down_1(wxCommandEvent &event);
void on_axis_ctrl_z_down_10(wxCommandEvent &event);
void on_axis_ctrl_e_up_10(wxCommandEvent &event);
void on_axis_ctrl_e_down_10(wxCommandEvent &event);
void axis_ctrl_e_hint(bool up_down);
void on_nozzle_selected(wxCommandEvent &event);
/* temp control */
void on_bed_temp_kill_focus(wxFocusEvent &event);
void on_bed_temp_set_focus(wxFocusEvent &event);
void on_set_bed_temp();
void on_nozzle_temp_kill_focus(wxFocusEvent &event);
void on_nozzle_temp_set_focus(wxFocusEvent &event);
void on_set_nozzle_temp(int nozzle_id);
void on_set_chamber_temp();
/* extruder apis */
void on_ams_load(SimpleEvent &event);
void update_load_with_temp();
void on_ams_load_curr();
void on_ams_load_vams(wxCommandEvent& event);
void on_ams_switch(SimpleEvent &event);
void on_ams_unload(SimpleEvent &event);
void on_ams_filament_backup(SimpleEvent& event);
void on_ams_setting_click(SimpleEvent& event);
void on_filament_edit(wxCommandEvent &event);
void on_ext_spool_edit(wxCommandEvent &event);
void on_filament_extrusion_cali(wxCommandEvent &event);
void on_ams_refresh_rfid(wxCommandEvent &event);
void on_ams_selected(wxCommandEvent &event);
void on_ams_guide(wxCommandEvent &event);
void on_ams_retry(wxCommandEvent &event);
void on_fan_changed(wxCommandEvent& event);
void on_cham_temp_kill_focus(wxFocusEvent& event);
void on_cham_temp_set_focus(wxFocusEvent& event);
void on_switch_speed(wxCommandEvent& event);
void on_lamp_switch(wxCommandEvent &event);
void on_printing_fan_switch(wxCommandEvent &event);
void on_nozzle_fan_switch(wxCommandEvent &event);
void on_thumbnail_enter(wxMouseEvent &event);
void on_thumbnail_leave(wxMouseEvent &event);
void refresh_thumbnail_webrequest(wxMouseEvent& event);
void on_switch_vcamera(wxMouseEvent &event);
void on_camera_enter(wxMouseEvent &event);
void on_camera_leave(wxMouseEvent& event);
void on_auto_leveling(wxCommandEvent &event);
void on_xyz_abs(wxCommandEvent &event);
void on_show_parts_options(wxCommandEvent& event);
/* print options */
void on_show_print_options(wxCommandEvent &event);
/* safety options */
void on_show_safety_options(wxCommandEvent &event);
/* calibration */
void on_start_calibration(wxCommandEvent &event);
/* update apis */
void update(MachineObject* obj);
void show_printing_status(bool ctrl_area = true, bool temp_area = true);
void update_left_time(int mc_left_time);
void update_basic_print_data(bool def = false);
void update_model_info();
void update_subtask(MachineObject* obj);
void update_partskip_subtask(MachineObject *obj);
void update_cloud_subtask(MachineObject *obj);
void update_sdcard_subtask(MachineObject *obj);
void update_temp_ctrl(MachineObject *obj);
void update_misc_ctrl(MachineObject *obj);
void update_ams(MachineObject* obj);
void update_rack(MachineObject* obj);
void update_filament_loading_panel(MachineObject* obj);
void update_extruder_status(MachineObject* obj);
void update_ams_control_state(std::string ams_id, std::string slot_id);
void update_cali(MachineObject* obj);
void update_calib_bitmap();
void reset_printing_values();
void on_webrequest_state(wxWebRequestEvent &evt);
bool is_task_changed(MachineObject* obj);
/* camera */
void update_camera_state(MachineObject* obj);
bool show_vcamera = false;
// partskip button
void update_partskip_button(MachineObject* obj);
// printer parts options
void update_printer_parts_options(MachineObject* obj);
public:
void update_error_message();
public:
StatusPanel(wxWindow * parent,
wxWindowID id = wxID_ANY,
const wxPoint & pos = wxDefaultPosition,
const wxSize & size = wxDefaultSize,
long style = wxTAB_TRAVERSAL,
const wxString &name = wxEmptyString);
~StatusPanel();
enum ThumbnailState {
PLACE_HOLDER = 0,
BROKEN_IMG = 1,
TASK_THUMBNAIL = 2,
SDCARD_THUMBNAIL = 3,
STATE_COUNT = 4
};
BBLSubTask * last_subtask{nullptr};
std::string last_profile_id;
std::string last_task_id;
long last_tray_exist_bits { -1 };
long last_ams_exist_bits { -1 };
long last_tray_is_bbl_bits{ -1 };
long last_read_done_bits{ -1 };
long last_reading_bits { -1 };
long last_ams_version { -1 };
std::optional<int> last_cali_version;
enum ThumbnailState task_thumbnail_state {ThumbnailState::PLACE_HOLDER};
std::vector<int> last_stage_list_info;
bool is_stage_list_info_changed(MachineObject* obj);
void set_default();
void show_status(int status);
void set_hold_count(int& count);
void rescale_camera_icons();
void on_sys_color_changed();
void msw_rescale();
};
}
}
#endif