mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-05 14:51:06 +00:00
269 lines
10 KiB
C++
269 lines
10 KiB
C++
#include "OrcaFilesPanel.h"
|
|
|
|
#include "DeviceManager.hpp"
|
|
#include "GUI_App.hpp"
|
|
#include "GUI.hpp"
|
|
#include "I18N.hpp"
|
|
#include "ImageGrid.h"
|
|
#include "MsgDialog.hpp"
|
|
#include "Widgets/Button.hpp"
|
|
#include "Widgets/Label.hpp"
|
|
#include "Widgets/StaticBox.hpp"
|
|
#include "Widgets/StateColor.hpp"
|
|
#include "slic3r/Utils/NetworkAgent.hpp"
|
|
#include "slic3r/Utils/bambu_networking.hpp"
|
|
|
|
#include <boost/make_shared.hpp>
|
|
#include <wx/colour.h>
|
|
#include <wx/sizer.h>
|
|
#include <utility>
|
|
|
|
namespace Slic3r {
|
|
namespace GUI {
|
|
|
|
OrcaFilesPanel::OrcaFilesPanel(wxWindow* parent)
|
|
: wxPanel(parent, wxID_ANY)
|
|
, m_bmp_loading(this, "media_loading", 0)
|
|
, m_bmp_failed(this, "media_failed", 0)
|
|
, m_bmp_empty(this, "media_empty", 0)
|
|
{
|
|
const wxColour light_background("#EEEEEE");
|
|
SetBackgroundColour(wxGetApp().dark_mode() ? StateColor::darkModeColorFor(light_background) : light_background);
|
|
|
|
auto* sizer = new wxBoxSizer(wxVERTICAL);
|
|
auto* toolbar = new wxBoxSizer(wxHORIZONTAL);
|
|
toolbar->SetMinSize({-1, 75 * em_unit(this) / 10});
|
|
|
|
m_root_label = new Label(this, _L("gcodes"));
|
|
m_root_label->SetFont(Label::Head_16);
|
|
toolbar->Add(m_root_label, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 24);
|
|
|
|
m_time_panel = new ::StaticBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
|
|
m_time_panel->SetCornerRadius(0);
|
|
m_button_year = new ::Button(m_time_panel, _L("Year"), "", wxBORDER_NONE);
|
|
m_button_month = new ::Button(m_time_panel, _L("Month"), "", wxBORDER_NONE);
|
|
m_button_all = new ::Button(m_time_panel, _L("All Files"), "", wxBORDER_NONE);
|
|
m_button_year->SetToolTip(_L("Group files by year, recent first."));
|
|
m_button_month->SetToolTip(_L("Group files by month, recent first."));
|
|
m_button_all->SetToolTip(_L("Show all files, recent first."));
|
|
for (auto* button : {m_button_year, m_button_month, m_button_all}) {
|
|
button->SetBackgroundColor(StateColor(
|
|
std::make_pair(0xEEEEEE, static_cast<int>(StateColor::Checked)),
|
|
std::make_pair(*wxLIGHT_GREY, static_cast<int>(StateColor::Hovered)),
|
|
std::make_pair(*wxWHITE, static_cast<int>(StateColor::Normal))));
|
|
button->SetTextColor(StateColor(
|
|
std::make_pair(0x3B4446, static_cast<int>(StateColor::Checked)),
|
|
std::make_pair(*wxLIGHT_GREY, static_cast<int>(StateColor::Hovered)),
|
|
std::make_pair(0xABACAC, static_cast<int>(StateColor::Normal))));
|
|
button->SetCanFocus(false);
|
|
}
|
|
auto* time_sizer = new wxBoxSizer(wxHORIZONTAL);
|
|
time_sizer->Add(m_button_year, 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 24);
|
|
time_sizer->Add(m_button_month, 0, wxALIGN_CENTER_VERTICAL);
|
|
time_sizer->Add(m_button_all, 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 24);
|
|
m_time_panel->SetSizer(time_sizer);
|
|
toolbar->AddStretchSpacer(1);
|
|
toolbar->Add(m_time_panel, 0, wxALIGN_CENTER_VERTICAL);
|
|
toolbar->AddStretchSpacer(1);
|
|
|
|
m_button_refresh = new ::Button(this, _L("Refresh"));
|
|
m_button_refresh->SetToolTip(_L("Reload file list from printer."));
|
|
m_button_refresh->SetFont(Label::Body_12);
|
|
m_button_refresh->SetCornerRadius(12);
|
|
m_button_refresh->SetPaddingSize({10, 6});
|
|
m_button_refresh->SetCanFocus(false);
|
|
m_button_refresh->SetBorderWidth(0);
|
|
toolbar->Add(m_button_refresh, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 24);
|
|
sizer->Add(toolbar, 0, wxEXPAND);
|
|
|
|
m_image_grid = new ImageGrid(this);
|
|
// Theme this grid instance without changing the shared Bambu defaults.
|
|
m_image_grid->SetBackgroundColour(GetBackgroundColour());
|
|
m_image_grid->SetSelecting(false);
|
|
m_image_grid->ShowDownload(false);
|
|
m_image_grid->SetStatus(m_bmp_failed, _L("Please confirm if the printer is connected."));
|
|
sizer->Add(m_image_grid, 1, wxEXPAND);
|
|
SetSizer(sizer);
|
|
applyThemeColors();
|
|
updateGroupButtons(m_group_mode);
|
|
|
|
auto group_clicked = [this](wxCommandEvent& event) {
|
|
const FileGridGroup mode = event.GetEventObject() == m_button_year ? FileGridGroup::Year :
|
|
event.GetEventObject() == m_button_month ? FileGridGroup::Month : FileGridGroup::All;
|
|
m_image_grid->SetGroupMode(static_cast<int>(mode));
|
|
updateGroupButtons(mode);
|
|
};
|
|
m_button_year->Bind(wxEVT_COMMAND_BUTTON_CLICKED, group_clicked);
|
|
m_button_month->Bind(wxEVT_COMMAND_BUTTON_CLICKED, group_clicked);
|
|
m_button_all->Bind(wxEVT_COMMAND_BUTTON_CLICKED, group_clicked);
|
|
|
|
m_button_refresh->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](wxCommandEvent& event) {
|
|
event.Skip();
|
|
if (m_model)
|
|
m_model->Refresh();
|
|
});
|
|
|
|
m_image_grid->Bind(EVT_ITEM_ACTION, [this](wxCommandEvent& event) {
|
|
const int action = event.GetInt();
|
|
if (!m_model || m_device_id.empty())
|
|
return;
|
|
|
|
const size_t index = static_cast<size_t>(event.GetExtraLong());
|
|
if (index >= m_model->GetCount())
|
|
return;
|
|
const FileGridCard& card = m_model->GetFile(index);
|
|
if (card.id.empty())
|
|
return;
|
|
const std::string path = card.id;
|
|
const std::string name = card.name;
|
|
|
|
if (action == 0) {
|
|
MessageDialog dlg(this,
|
|
wxString::Format(_L("Do you want to delete the file '%s' from printer?"), from_u8(name)),
|
|
_L("Delete file"), wxYES_NO | wxICON_WARNING);
|
|
if (dlg.ShowModal() != wxID_YES)
|
|
return;
|
|
|
|
m_model->DeleteFile(path, [this](bool ok) {
|
|
if (ok)
|
|
return;
|
|
MessageDialog(this, _L("Failed to delete the file from printer."), _L("Delete file"),
|
|
wxOK | wxICON_ERROR).ShowModal();
|
|
});
|
|
} else if (action == 1) {
|
|
// Print is .gcode-only for now; .gcode.3mf support to be added later.
|
|
MessageDialog dlg(this,
|
|
wxString::Format(_L("Do you want to print the file '%s' from printer?"), from_u8(name)),
|
|
_L("Print file"), wxYES_NO | wxICON_WARNING);
|
|
if (dlg.ShowModal() != wxID_YES)
|
|
return;
|
|
|
|
NetworkAgent* agent = wxGetApp().getAgent();
|
|
if (!agent)
|
|
return;
|
|
|
|
PrintParams params;
|
|
params.dev_id = m_device_id;
|
|
params.dst_file = path;
|
|
params.connection_type = "lan";
|
|
if (agent->start_sdcard_print(params, {}, {}) != BAMBU_NETWORK_SUCCESS)
|
|
MessageDialog(this, _L("Failed to start the print job."), _L("Print file"),
|
|
wxOK | wxICON_ERROR).ShowModal();
|
|
}
|
|
});
|
|
}
|
|
|
|
OrcaFilesPanel::~OrcaFilesPanel()
|
|
{
|
|
if (m_model)
|
|
m_model->SetStatusHandler({});
|
|
if (m_model)
|
|
m_model->SetGroupModeHandler({});
|
|
m_image_grid->SetModel(nullptr);
|
|
m_model.reset();
|
|
}
|
|
|
|
void OrcaFilesPanel::UpdateByObj(MachineObject* obj)
|
|
{
|
|
const std::string device_id = obj ? obj->get_dev_id() : std::string();
|
|
if (device_id == m_device_id)
|
|
return;
|
|
|
|
m_device_id = device_id;
|
|
if (m_model)
|
|
m_model->SetStatusHandler({});
|
|
if (m_model)
|
|
m_model->SetGroupModeHandler({});
|
|
m_image_grid->SetModel(nullptr);
|
|
m_model.reset();
|
|
|
|
if (m_device_id.empty()) {
|
|
m_button_refresh->Enable(false);
|
|
m_image_grid->SetStatus(m_bmp_failed, _L("Please confirm if the printer is connected."));
|
|
return;
|
|
}
|
|
|
|
m_model = boost::make_shared<RemoteFileGridModel>(m_device_id);
|
|
m_model->SetStatusHandler([this](RemoteFileGridModel::Status status) { updateStatus(status); });
|
|
m_model->SetGroupModeHandler([this](FileGridGroup mode) { updateGroupButtons(mode); });
|
|
m_model->SetGroupMode(m_group_mode);
|
|
m_image_grid->SetModel(m_model);
|
|
m_image_grid->SetFileType(static_cast<int>(FileGridType::Model), {});
|
|
m_button_refresh->Enable(true);
|
|
m_model->Refresh();
|
|
}
|
|
|
|
void OrcaFilesPanel::updateStatus(RemoteFileGridModel::Status status)
|
|
{
|
|
switch (status) {
|
|
case RemoteFileGridModel::Status::Loading:
|
|
m_image_grid->SetStatus(m_bmp_loading, _L("Loading file list..."));
|
|
break;
|
|
case RemoteFileGridModel::Status::Ready:
|
|
break;
|
|
case RemoteFileGridModel::Status::Empty:
|
|
m_image_grid->SetStatus(m_bmp_empty, _L("No files"));
|
|
break;
|
|
case RemoteFileGridModel::Status::Failed:
|
|
m_image_grid->SetStatus(m_bmp_failed, _L("Load failed"));
|
|
break;
|
|
}
|
|
}
|
|
|
|
void OrcaFilesPanel::Rescale()
|
|
{
|
|
m_bmp_loading.msw_rescale();
|
|
m_bmp_failed.msw_rescale();
|
|
m_bmp_empty.msw_rescale();
|
|
|
|
auto* toolbar = GetSizer()->GetItem(static_cast<size_t>(0))->GetSizer();
|
|
toolbar->SetMinSize({-1, 75 * em_unit(this) / 10});
|
|
m_root_label->SetFont(Label::Head_16);
|
|
m_button_refresh->Rescale();
|
|
m_button_year->Rescale();
|
|
m_button_month->Rescale();
|
|
m_button_all->Rescale();
|
|
m_image_grid->Rescale();
|
|
}
|
|
|
|
void OrcaFilesPanel::on_sys_color_changed()
|
|
{
|
|
applyThemeColors();
|
|
Layout();
|
|
Refresh();
|
|
}
|
|
|
|
void OrcaFilesPanel::applyThemeColors()
|
|
{
|
|
const bool dark = wxGetApp().dark_mode();
|
|
const wxColour light_background("#EEEEEE");
|
|
const wxColour light_text("#262E30");
|
|
const wxColour light_teal("#009688");
|
|
const wxColour background = dark ? StateColor::darkModeColorFor(light_background) : light_background;
|
|
|
|
SetBackgroundColour(background);
|
|
m_root_label->SetBackgroundColour(background);
|
|
m_root_label->SetForegroundColour(dark ? StateColor::darkModeColorFor(light_text) : light_text);
|
|
m_time_panel->SetBackgroundColour(background);
|
|
m_button_refresh->SetBackgroundColorNormal(dark ? StateColor::darkModeColorFor(light_teal) : light_teal);
|
|
m_button_refresh->SetTextColorNormal(*wxWHITE);
|
|
m_image_grid->SetBackgroundColour(background);
|
|
m_image_grid->Refresh();
|
|
m_button_year->Refresh();
|
|
m_button_month->Refresh();
|
|
m_button_all->Refresh();
|
|
}
|
|
|
|
void OrcaFilesPanel::updateGroupButtons(FileGridGroup mode)
|
|
{
|
|
m_group_mode = mode;
|
|
::Button* buttons[] = {m_button_all, m_button_month, m_button_year};
|
|
const int selected = static_cast<int>(mode);
|
|
for (int i = 0; i < 3; ++i) {
|
|
buttons[i]->SetValue(i == selected);
|
|
buttons[i]->SetFont(i == selected ? Label::Head_14 : Label::Body_14);
|
|
}
|
|
}
|
|
|
|
}}
|