Files
OrcaSlicer/src/slic3r/GUI/SendToPrinter.hpp
yw4z 0bee82cee5 Hyperlink class (#9947)
### FIXES
• 3mf file version check dialog opens bambu releases page instead Orca

### CODE COMPARISON

<img width="112" height="36" alt="Screenshot-20251128125737" src="https://github.com/user-attachments/assets/73718a18-8159-43d5-bb80-0eb90d59a8f6" />

**wxHyperlinkCtrl**
• System decides what colors to use. so blue color is visible even with colors set
• No need to use SetCursor()
```
auto wiki_url = "https://github.com/OrcaSlicer/OrcaSlicer/wiki/Built-in-placeholders-variables";
wxHyperlinkCtrl* wiki = new wxHyperlinkCtrl(this, wxID_ANY, _L("Wiki Guide"), wiki_url);
wiki->SetToolTip(wiki_url); // required to showing navigation point to user
wiki->SetFont(Label::Body_14); // not works properly
wiki->SetVisitedColour(wxColour("#009687")); // not works properly
wiki->SetHoverColour(  wxColour("#26A69A")); // not works properly
wiki->SetNormalColour( wxColour("#009687")); // not works properly
```

<img width="132" height="39" alt="Screenshot-20251128125847" src="https://github.com/user-attachments/assets/f6818dc0-5078-498a-bf09-1fd36e81ebe5" />

**wxStaticText**
• Works reliably on colors and fonts
• All event has to defined manually
```
wxStaticText* wiki = new wxStaticText(this, wxID_ANY, _L("Wiki Guide"));
auto wiki_url = "https://github.com/OrcaSlicer/OrcaSlicer/wiki/Built-in-placeholders-variables";
wiki->SetToolTip(wiki_url); // required to showing navigation point to user
wiki->SetForegroundColour(wxColour("#009687"));
wiki->SetCursor(wxCURSOR_HAND);
wxFont font = Label::Body_14;
font.SetUnderlined(true);
wiki->SetFont(font);
wiki->Bind(wxEVT_LEFT_DOWN   ,[this, wiki_url](wxMouseEvent e) {wxLaunchDefaultBrowser(wiki_url);});
wiki->Bind(wxEVT_ENTER_WINDOW,[this, wiki    ](wxMouseEvent e) {SetForegroundColour(wxColour("#26A69A"));});
wiki->Bind(wxEVT_LEAVE_WINDOW,[this, wiki    ](wxMouseEvent e) {SetForegroundColour(wxColour("#009687"));});
```

<img width="132" height="39" alt="Screenshot-20251128125847" src="https://github.com/user-attachments/assets/f6818dc0-5078-498a-bf09-1fd36e81ebe5" />

**HyperLink**
• Fully automated and single line solution
• Colors can be controllable from one place
• Works reliably on colors and fonts
• Reduces duplicate code
```
HyperLink* wiki = new HyperLink(this, _L("Wiki Guide"), "https://github.com/OrcaSlicer/OrcaSlicer/wiki/Built-in-placeholders-variables");
wiki->SetFont(Label::Body_14) // OPTIONAL default is Label::Body_14;
```


### CHANGES
• Unifies all hyperlinks with same style and makes them controllable from one place
• Replaces all wxHyperlink with simple custom class. Problem with wxHyperlink it mostly rendered as blue even color set
• Reduces duplicate code
• Adds wiki links for calibration dialogs
• Probably will add "Wiki Guide" to more dialogs overtime

<img width="349" height="238" alt="Screenshot-20251127212007" src="https://github.com/user-attachments/assets/69da2732-ea35-44de-8ebc-97a01f86328f" />

<img width="355" height="459" alt="Screenshot-20251127212021" src="https://github.com/user-attachments/assets/c0df40f8-c15d-47fa-b31a-cf8d8b337472" />

<img width="442" height="382" alt="Screenshot-20251127212046" src="https://github.com/user-attachments/assets/5d94242b-6364-4b0a-8b2f-a1f482199bd1" />

<img width="225" height="241" alt="Screenshot-20250824171339" src="https://github.com/user-attachments/assets/39ca6af3-6f8a-42ee-bf1d-c13d0f54bb63" />

<img width="442" height="639" alt="Screenshot-20251127212403" src="https://github.com/user-attachments/assets/c1c580f8-3e1b-42f0-aa8e-bac41c2ff76b" />

<img width="476" height="286" alt="Screenshot-20251127212515" src="https://github.com/user-attachments/assets/28b130ce-c7c0-4ada-9842-ff7154c00c21" />

<img width="1460" height="245" alt="Screenshot-20251127212541" src="https://github.com/user-attachments/assets/3fca2649-9cd3-4aea-9153-b2f508fdfefe" />

<img width="401" height="291" alt="Screenshot-20251127213243" src="https://github.com/user-attachments/assets/82b4ec1f-6074-4018-9efa-a1b6b819ae28" />
2026-01-03 23:06:57 +08:00

241 lines
10 KiB
C++

#ifndef slic3r_GUI_SendToSDcard_hpp_
#define slic3r_GUI_SendToSDcard_hpp_
#include <wx/wx.h>
#include <wx/intl.h>
#include <wx/collpane.h>
#include <wx/dataview.h>
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/dataview.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/string.h>
#include <wx/sizer.h>
#include <wx/stattext.h>
#include <wx/hyperlink.h>
#include <wx/button.h>
#include <wx/dialog.h>
#include <wx/popupwin.h>
#include <wx/spinctrl.h>
#include <wx/artprov.h>
#include <wx/wrapsizer.h>
#include <wx/srchctrl.h>
#include "SelectMachine.hpp"
#include "GUI_Utils.hpp"
#include "wxExtensions.hpp"
#include "DeviceManager.hpp"
#include "Plater.hpp"
#include "BBLStatusBar.hpp"
#include "BBLStatusBarSend.hpp"
#include "Widgets/Label.hpp"
#include "Widgets/Button.hpp"
#include "Widgets/CheckBox.hpp"
#include "Widgets/ComboBox.hpp"
#include "Widgets/ScrolledWindow.hpp"
#include <wx/simplebook.h>
#include <wx/hashmap.h>
#include "Widgets/AnimaController.hpp"
#include "Widgets/RadioBox.hpp"
namespace Slic3r {
class FileTransferTunnel;
class FileTransferJob;
namespace GUI {
class SendToPrinterDialog : public DPIDialog
{
private:
void init_bind();
void init_timer();
int m_print_plate_idx;
int m_current_filament_id;
int m_print_error_code = 0;
int timeout_count = 0;
int m_connect_try_times = 0;
bool m_is_in_sending_mode{ false };
bool m_is_rename_mode{ false };
bool enable_prepare_mode{ true };
bool m_need_adaptation_screen{ false };
bool m_export_3mf_cancel{ false };
bool m_is_canceled{ false };
bool m_tcp_try_connect{true};
bool m_tutk_try_connect{false};
bool m_ftp_try_connect{false};
std::string m_print_error_msg;
std::string m_print_error_extra;
std::string m_print_info;
std::string m_printer_last_select;
std::string m_device_select;
wxString m_current_project_name;
TextInput* m_rename_input{ nullptr };
wxSimplebook* m_rename_switch_panel{ nullptr };
Plater* m_plater{ nullptr };
wxStaticBitmap* m_staticbitmap{ nullptr };
ThumbnailPanel* m_thumbnailPanel{ nullptr };
ComboBox* m_comboBox_printer{ nullptr };
ComboBox* m_comboBox_bed{ nullptr };
Button* m_rename_button{ nullptr };
Button* m_button_refresh{ nullptr };
Button* m_button_ensure{ nullptr };
wxPanel* m_scrollable_region;
wxPanel* m_line_schedule{ nullptr };
wxPanel* m_panel_sending{ nullptr };
wxPanel* m_panel_prepare{ nullptr };
wxPanel* m_panel_finish{ nullptr };
wxPanel* m_line_top{ nullptr };
wxPanel* m_panel_image{ nullptr };
wxPanel* m_rename_normal_panel{ nullptr };
wxPanel* m_line_materia{ nullptr };
wxBoxSizer* m_storage_sizer{ nullptr };
wxPanel* m_storage_panel{ nullptr };
wxPanel * m_connecting_panel{nullptr};
wxSimplebook* m_simplebook{ nullptr };
wxStaticText* m_statictext_finish{ nullptr };
wxStaticText* m_stext_sending{ nullptr };
wxStaticText* m_staticText_bed_title{ nullptr };
wxStaticText* m_statictext_printer_msg{ nullptr };
wxStaticText * m_connecting_printer_msg{nullptr};
wxStaticText* m_stext_printer_title{ nullptr };
wxStaticText* m_rename_text{ nullptr };
wxStaticText* m_stext_time{ nullptr };
wxStaticText* m_stext_weight{ nullptr };
Label* m_st_txt_error_code{ nullptr };
Label* m_st_txt_error_desc{ nullptr };
Label* m_st_txt_extra_info{ nullptr };
HyperLink* m_link_network_state{ nullptr };
StateColor btn_bg_enable;
wxBoxSizer* rename_sizer_v{ nullptr };
wxBoxSizer* rename_sizer_h{ nullptr };
wxBoxSizer* sizer_thumbnail;
wxBoxSizer* m_sizer_scrollable_region;
wxBoxSizer* m_sizer_main;
wxStaticText* m_file_name;
PrintDialogStatus m_print_status{ PrintStatusInit };
AnimaIcon * m_animaicon{nullptr};
std::vector<wxString> m_bedtype_list;
std::map<std::string, ::CheckBox*> m_checkbox_list;
std::vector<MachineObject*> m_list;
wxColour m_colour_def_color{ wxColour(255, 255, 255) };
wxColour m_colour_bold_color{ wxColour(38, 46, 48) };
wxTimer* m_refresh_timer{ nullptr };
std::unique_ptr<wxTimer> m_task_timer{ nullptr };
std::unique_ptr<wxTimer> m_url_timer{nullptr};
std::shared_ptr<BBLStatusBarSend> m_status_bar;
std::unique_ptr<Worker> m_worker;
wxScrolledWindow *m_sw_print_failed_info{nullptr};
std::shared_ptr<int> m_token = std::make_shared<int>(0);
std::vector<RadioBox *> m_storage_radioBox;
std::string m_selected_storage;
bool m_if_has_sdcard;
bool m_waiting_support{ false };
bool m_waiting_enable{ false };
std::vector<std::string> m_ability_list;
public:
enum {
SUCCESS = 0,
CONTINUE = 1,
ERROR_JSON = 2,
ERROR_PIPE = 3,
ERROR_CANCEL = 4,
ERROR_RES_BUSY = 5,
ERROR_TIME_OUT = 6,
FILE_NO_EXIST = 10,
FILE_NAME_INVALID = 11,
FILE_SIZE_ERR = 12,
FILE_OPEN_ERR = 13,
FILE_READ_WRITE_ERR = 14,
FILE_CHECK_ERR = 15,
FILE_TYPE_ERR = 16,
STORAGE_UNAVAILABLE = 17,
API_VERSION_UNSUPPORT = 18,
FILE_EXIST = 19,
STORAGE_SPACE_NOT_ENOUGH = 20,
FILE_CREATE_ERR = 21,
FILE_WRITE_ERR = 22,
MD5_COMPARE_ERR = 23,
FILE_RENAME_ERR = 24,
SEND_ERR = 25,
};
private:
enum ConnectionStatus { NOT_START, CONNECTING, CONNECTED, CONNECTION_FAILED, DISCONNECTED };
ConnectionStatus m_connection_status{ConnectionStatus::NOT_START};
std::unique_ptr<FileTransferTunnel> m_filetransfer_tunnel;
std::unique_ptr<FileTransferJob> m_filetransfer_mediability_job;
std::unique_ptr<FileTransferJob> m_filetransfer_uploadfile_job;
wxDateTime m_last_refresh_time;
public:
SendToPrinterDialog(Plater *plater = nullptr);
~SendToPrinterDialog();
bool Show(bool show);
bool is_timeout();
void on_rename_click(wxCommandEvent& event);
void on_rename_enter();
void stripWhiteSpace(std::string& str);
void prepare_mode();
void sending_mode();
void reset_timeout();
void update_user_printer();
void update_show_status();
bool is_blocking_printing(MachineObject* obj_);
void prepare(int print_plate_idx);
void check_focus(wxWindow* window);
void check_fcous_state(wxWindow* window);
void update_priner_status_msg(wxString msg, bool is_warning = false);
void update_print_status_msg(wxString msg, bool is_warning = false, bool is_printer = true);
void update_printer_combobox(wxCommandEvent& event);
void on_cancel(wxCloseEvent& event);
void on_ok(wxCommandEvent& event);
void clear_ip_address_config(wxCommandEvent& e);
void on_refresh(wxCommandEvent& event);
void on_print_job_cancel(wxCommandEvent& evt);
void set_default();
void on_timer(wxTimerEvent& event);
void on_selection_changed(wxCommandEvent& event);
void Enable_Refresh_Button(bool en);
void show_status(PrintDialogStatus status, std::vector<wxString> params = std::vector<wxString>());
void Enable_Send_Button(bool en);
void on_dpi_changed(const wxRect& suggested_rect) override;
void update_user_machine_list();
void show_print_failed_info(bool show, int code = 0, wxString description = wxEmptyString, wxString extra = wxEmptyString);
void update_print_error_info(int code, std::string msg, std::string extra);
void on_change_color_mode() { wxGetApp().UpdateDlgDarkUI(this); }
void update_storage_list(const std::vector<std::string>& storages);
std::string get_storage_selected();
wxString format_text(wxString& m_msg);
std::vector<std::string> sort_string(std::vector<std::string> strArray);
void GetConnection();
private:
void ResetConnectMethod();
void ResetTunnelAndJob();
void OnConnection(bool is_success, int error_code, std::string error_msg);
void CreateMediaAbilityJob();
void CreateUploadFileJob(const std::string &path, const std::string &name);
void ChangeConnectMethod();
void UploadFileProgressCallback(int progress);
void UploadFileRessultCallback(int res, int resp_ec, std::string json_res, std::vector<std::byte> bin_res);
void Reset();
};
wxDECLARE_EVENT(EVT_CLEAR_IPADDRESS, wxCommandEvent);
}
}
#endif