Add project info editor (#3754)

* Add button to add model info

* Initial impl of project info editor

* Add sidebar item to edit project info

* Add license selector

* Fix use of deprecated apis

* Fix license combox dark mode

* Add back button on project info editor screen

---------

Co-authored-by: SoftFever <softfeverever@gmail.com>
This commit is contained in:
Noisyfox 2024-01-21 22:13:37 +08:00 committed by GitHub
parent ead78a98f9
commit 122c5cedd8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 292 additions and 189 deletions

View file

@ -33,17 +33,29 @@ wxDEFINE_EVENT(EVT_AUXILIARY_IMPORT, wxCommandEvent);
wxDEFINE_EVENT(EVT_AUXILIARY_UPDATE_COVER, wxCommandEvent);
wxDEFINE_EVENT(EVT_AUXILIARY_UPDATE_DELETE, wxCommandEvent);
wxDEFINE_EVENT(EVT_AUXILIARY_UPDATE_RENAME, wxCommandEvent);
wxDEFINE_EVENT(EVT_AUXILIARY_DONE, wxCommandEvent);
const std::vector<std::string> license_list = {
"BSD License",
"Apache License",
"GPL License",
"LGPL License",
"MIT License",
"CC License"
"",
"CC0",
"BY",
"BY-SA",
"BY-ND",
"BY-NC",
"BY-NC-SA",
"BY-NC-ND",
};
static std::shared_ptr<ModelInfo> ensure_model_info()
{
auto& model = wxGetApp().plater()->model();
if (model.model_info == nullptr) {
model.model_info = std::make_shared<ModelInfo>();
}
return model.model_info;
}
AuFile::AuFile(wxWindow *parent, fs::path file_path, wxString file_name, AuxiliaryFolderType type, wxWindowID id, const wxPoint &pos, const wxSize &size, long style)
{
m_type = type;
@ -344,7 +356,7 @@ void AuFile::on_input_enter(wxCommandEvent &evt)
}
auto existing = false;
auto dir = m_file_path.branch_path();
auto dir = m_file_path.parent_path();
auto new_fullname = new_file_name + m_file_path.extension().string();
@ -454,14 +466,12 @@ void AuFile::on_mouse_left_up(wxMouseEvent &evt)
void AuFile::on_set_cover()
{
if (wxGetApp().plater()->model().model_info == nullptr) { wxGetApp().plater()->model().model_info = std::make_shared<ModelInfo>(); }
fs::path path(into_path(m_file_name));
wxGetApp().plater()->model().model_info->cover_file = path.string();
ensure_model_info()->cover_file = path.string();
//wxGetApp().plater()->model().model_info->cover_file = m_file_name.ToStdString();
auto full_path = m_file_path.branch_path();
auto full_root_path = full_path.branch_path();
auto full_path = m_file_path.parent_path();
auto full_root_path = full_path.parent_path();
auto full_root_path_str = encode_path(full_root_path.string().c_str());
auto dir = wxString::Format("%s/.thumbnails", full_root_path_str);
@ -505,8 +515,8 @@ void AuFile::on_set_delete()
auto is_fine = fs::remove(bfs_path);
if (m_cover) {
auto full_path = m_file_path.branch_path();
auto full_root_path = full_path.branch_path();
auto full_path = m_file_path.parent_path();
auto full_root_path = full_path.parent_path();
auto full_root_path_str = encode_path(full_root_path.string().c_str());
auto dir = wxString::Format("%s/.thumbnails", full_root_path_str);
fs::path dir_path(dir.ToStdWstring());
@ -520,8 +530,11 @@ void AuFile::on_set_delete()
if (fs::exists(fs::path(middle_img_path))) { fs::remove(fs::path(middle_img_path)); }
}
if (wxGetApp().plater()->model().model_info == nullptr) { wxGetApp().plater()->model().model_info = std::make_shared<ModelInfo>(); }
if (wxGetApp().plater()->model().model_info->cover_file == m_file_name) { wxGetApp().plater()->model().model_info->cover_file = ""; }
if (wxGetApp().plater()->model().model_info != nullptr) {
if (wxGetApp().plater()->model().model_info->cover_file == m_file_name) {
wxGetApp().plater()->model().model_info->cover_file = "";
}
}
if (is_fine) {
auto evt = wxCommandEvent(EVT_AUXILIARY_UPDATE_DELETE);
@ -669,6 +682,7 @@ void AuFolderPanel::update(std::vector<fs::path> paths)
}
m_gsizer_content->Layout();
Layout();
Refresh();
}
void AuFolderPanel::msw_rescale()
@ -820,9 +834,22 @@ void AuxiliaryPanel::init_bitmap()
void AuxiliaryPanel::init_tabpanel()
{
auto m_side_tools = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(220), FromDIP(18)));
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Disabled),
std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed),
std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
auto back_btn = new Button(this, _L("Back"), "assemble_return", wxBORDER_NONE | wxBU_LEFT | wxBU_EXACTFIT);
back_btn->SetSize(wxSize(FromDIP(220), FromDIP(18)));
back_btn->SetBackgroundColor(btn_bg_green);
back_btn->SetCornerRadius(0);
back_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, [this](wxEvent& e) {
auto event = wxCommandEvent(EVT_AUXILIARY_DONE);
event.SetEventObject(m_parent);
wxPostEvent(m_parent, event);
});
wxBoxSizer *sizer_side_tools = new wxBoxSizer(wxVERTICAL);
sizer_side_tools->Add(m_side_tools, 1, wxEXPAND, 0);
sizer_side_tools->Add(back_btn, 1, wxEXPAND, 0);
m_tabpanel = new Tabbook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, sizer_side_tools, wxNB_LEFT | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME);
m_tabpanel->SetBackgroundColour(wxColour("#FEFFFF"));
m_tabpanel->Bind(wxEVT_BOOKCTRL_PAGE_CHANGED, [this](wxBookCtrlEvent &e) { ; });
@ -872,20 +899,7 @@ bool AuxiliaryPanel::Show(bool show) { return wxPanel::Show(show); }
void AuxiliaryPanel::init_auxiliary()
{
Model &model = wxGetApp().plater()->model();
m_root_dir = encode_path(model.get_auxiliary_file_temp_path().c_str());
if (wxDirExists(m_root_dir)) {
fs::path path_to_del(m_root_dir.ToStdWstring());
try {
fs::remove_all(path_to_del);
} catch (...) {
BOOST_LOG_TRIVIAL(error) << "Failed removing the auxiliary directory " << m_root_dir.c_str();
}
}
fs::path top_dir_path(m_root_dir.ToStdWstring());
fs::create_directory(top_dir_path);
for (auto folder : s_default_folders) create_folder(folder);
Reload(encode_path(model.get_auxiliary_file_temp_path().c_str()), {});
}
void AuxiliaryPanel::on_import_file(wxCommandEvent &event)
@ -947,7 +961,7 @@ void AuxiliaryPanel::on_import_file(wxCommandEvent &event)
boost::system::error_code ec;
if (!fs::copy_file(src_bfs_path, fs::path(dir_path.ToStdWstring()), fs::copy_option::overwrite_if_exists, ec)) continue;
if (!fs::copy_file(src_bfs_path, fs::path(dir_path.ToStdWstring()), fs::copy_options::overwrite_existing, ec)) continue;
Slic3r::put_other_changes();
// add in file list
@ -987,76 +1001,22 @@ std::string AuxiliaryPanel::replaceSpace(std::string s, std::string ts, std::str
return s;
}
void AuxiliaryPanel::Reload(wxString aux_path)
void AuxiliaryPanel::Reload(wxString aux_path, std::map<std::string, std::vector<json>> paths)
{
fs::path new_aux_path(aux_path.ToStdWstring());
try {
fs::remove_all(fs::path(m_root_dir.ToStdWstring()));
} catch (...) {
BOOST_LOG_TRIVIAL(error) << "Failed removing the auxiliary directory " << m_root_dir.c_str();
}
m_root_dir = aux_path;
m_paths_list.clear();
// Check new path. If not exist, create a new one.
if (!fs::exists(new_aux_path)) {
fs::create_directory(new_aux_path);
// Create default folders if they are not loaded
for (auto folder : s_default_folders) {
wxString folder_path = aux_path + "/" + folder;
if (fs::exists(folder_path.ToStdWstring())) continue;
fs::create_directory(folder_path.ToStdWstring());
for (const auto & path : paths) {
m_paths_list[path.first] = std::vector<fs::path>{};
for (const auto & j : path.second) {
m_paths_list[path.first].push_back(j["_filepath"]);
}
update_all_panel();
m_designer_panel->update_info();
return;
}
// Load from new path
std::vector<fs::path> dir_cache;
fs::directory_iterator iter_end;
for (fs::directory_iterator iter(new_aux_path); iter != iter_end; iter++) {
wxString path = iter->path().generic_wstring();
dir_cache.push_back(iter->path());
}
for (auto dir : dir_cache) {
for (fs::directory_iterator iter(dir); iter != iter_end; iter++) {
if (fs::is_directory(iter->path())) continue;
wxString file_path = iter->path().generic_wstring();
//auto file_path_str = encode_path(file_path.c_str());
for (auto folder : s_default_folders) {
auto idx = file_path.find(folder.ToStdString());
if (idx != std::string::npos) {
auto iter = m_paths_list.find(folder.ToStdString());
auto file_path_str = fs::path(file_path.ToStdWstring());
if (iter != m_paths_list.end()) {
m_paths_list[folder.ToStdString()].push_back(file_path_str);
break;
} else {
m_paths_list[folder.ToStdString()] = std::vector<fs::path>{file_path_str};
break;
}
}
}
}
}
// Create default folders if they are not loaded
wxDataViewItemArray default_items;
for (auto folder : s_default_folders) {
wxString folder_path = aux_path + "/" + folder;
if (fs::exists(folder_path.ToStdWstring())) continue;
fs::create_directory(folder_path.ToStdWstring());
}
update_all_panel();
update_all_cover();
m_designer_panel->update_info();
m_tabpanel->SetSelection(0);
}
void AuxiliaryPanel::update_all_panel()
@ -1121,22 +1081,21 @@ void AuxiliaryPanel::update_all_cover()
m_imput_model_name->GetTextCtrl()->SetSize(wxSize(FromDIP(450), -1));
m_sizer_model_name->Add(m_imput_model_name, 0, wxALIGN_CENTER, 0);
/*
wxBoxSizer *m_sizer_license = new wxBoxSizer(wxHORIZONTAL);
auto m_text_license = new wxStaticText(this, wxID_ANY, _L("License"), wxDefaultPosition, wxSize(120, -1), 0);
auto m_text_license = new wxStaticText(this, wxID_ANY, _L("License"), wxDefaultPosition, wxSize(180, -1), 0);
m_text_license->Wrap(-1);
m_sizer_license->Add(m_text_license, 0, wxALIGN_CENTER, 0);
m_combo_license = new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(450, -1), 0, NULL, wxCB_READONLY);
m_combo_license = new ComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(450), -1), 0, NULL, wxCB_READONLY);
m_sizer_license->Add(m_combo_license, 0, wxALIGN_CENTER, 0);
*/
m_sizer_body->Add( 0, 0, 0, wxTOP, FromDIP(50) );
m_sizer_body->Add(m_sizer_designer, 0, wxLEFT, FromDIP(50));
m_sizer_body->Add( 0, 0, 0, wxTOP, FromDIP(20));
m_sizer_body->Add(m_sizer_model_name, 0, wxLEFT, FromDIP(50));
//m_sizer_body->Add(0, 0, 0, wxTOP, FromDIP(20));
//m_sizer_body->Add(m_sizer_license, 0, wxLEFT, FromDIP(50));
//init_license_list();
m_sizer_body->Add(0, 0, 0, wxTOP, FromDIP(20));
m_sizer_body->Add(m_sizer_license, 0, wxLEFT, FromDIP(50));
init_license_list();
SetSizer(m_sizer_body);
Layout();
@ -1144,52 +1103,35 @@ void AuxiliaryPanel::update_all_cover()
m_input_designer->Bind(wxEVT_TEXT, &DesignerPanel::on_input_enter_designer, this);
m_imput_model_name->Bind(wxEVT_TEXT, &DesignerPanel::on_input_enter_model, this);
//m_combo_license->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler(DesignerPanel::on_select_license), NULL, this);
m_combo_license->Bind(wxEVT_COMMAND_COMBOBOX_SELECTED, &DesignerPanel::on_select_license, this);
}
DesignerPanel::~DesignerPanel()
{
//m_combo_license->Disconnect(wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler(DesignerPanel::on_select_license), NULL, this);
}
void DesignerPanel::init_license_list()
{
/*
wxArrayString text_licese;
for (int i = 0; i < license_list.size(); i++) {
text_licese.Add(license_list[i]);
}
m_combo_license->Set(text_licese);
*/
}
void DesignerPanel::on_select_license(wxCommandEvent&evt)
{
int selected = evt.GetInt();
if (selected >= 0 && selected < license_list.size()) {
if (wxGetApp().plater()->model().model_info == nullptr) {
wxGetApp().plater()->model().model_info = std::make_shared<ModelInfo>();
}
if (wxGetApp().plater()->model().model_info != nullptr) {
wxGetApp().plater()->model().model_info->license = license_list[selected];
}
ensure_model_info()->license = license_list[selected];
}
}
bool DesignerPanel::Show(bool show)
{
if ( wxGetApp().plater()->model().design_info != nullptr) {
wxString text = wxString::FromUTF8(wxGetApp().plater()->model().design_info->Designer);
m_input_designer->GetTextCtrl()->SetValue(text);
}
if (wxGetApp().plater()->model().model_info != nullptr) {
wxString text = wxString::FromUTF8(wxGetApp().plater()->model().model_info->model_name);
m_imput_model_name->GetTextCtrl()->SetValue(text);
}
return wxPanel::Show(show);
}
bool DesignerPanel::Show(bool show)
{
if (show) update_info();
return wxPanel::Show(show);
}
void DesignerPanel::on_input_enter_designer(wxCommandEvent &evt)
{
@ -1200,9 +1142,7 @@ void DesignerPanel::on_input_enter_designer(wxCommandEvent &evt)
void DesignerPanel::on_input_enter_model(wxCommandEvent &evt)
{
auto text = evt.GetString();
if (wxGetApp().plater()->model().model_info) {
wxGetApp().plater()->model().model_info->model_name = std::string(text.ToUTF8().data());
}
ensure_model_info()->model_name = std::string(text.ToUTF8().data());
}
void DesignerPanel::update_info()
@ -1215,10 +1155,13 @@ void DesignerPanel::update_info()
}
if (wxGetApp().plater()->model().model_info != nullptr) {
wxString text = wxString::FromUTF8(wxGetApp().plater()->model().model_info->model_name);
m_imput_model_name->GetTextCtrl()->SetValue(text);
m_imput_model_name->GetTextCtrl()->SetValue(wxString::FromUTF8(wxGetApp().plater()->model().model_info->model_name));
if (!m_combo_license->SetStringSelection(wxString::FromUTF8(wxGetApp().plater()->model().model_info->license))) {
m_combo_license->SetSelection(0);
}
} else {
m_imput_model_name->GetTextCtrl()->SetValue(wxEmptyString);
m_imput_model_name->GetTextCtrl()->SetValue(wxEmptyString);
m_combo_license->SetSelection(0);
}
}
@ -1226,6 +1169,7 @@ void DesignerPanel::msw_rescale()
{
m_input_designer->GetTextCtrl()->SetSize(wxSize(FromDIP(450), -1));
m_imput_model_name->GetTextCtrl()->SetSize(wxSize(FromDIP(450), -1));
m_combo_license->SetSize(wxSize(FromDIP(450), -1));
}
}} // namespace Slic3r::GUI

View file

@ -181,7 +181,7 @@ public:
::TextInput* m_input_designer {nullptr};
::TextInput* m_imput_model_name {nullptr};
//wxComboBox* m_combo_license {nullptr};
ComboBox* m_combo_license {nullptr};
bool Show(bool show) override;
void init_license_list();
void on_input_enter_designer(wxCommandEvent &evt);
@ -232,7 +232,7 @@ public:
void create_folder(wxString name = wxEmptyString);
std::string replaceSpace(std::string s, std::string ts, std::string ns);
void on_import_file(wxCommandEvent &event);
void Reload(wxString aux_path);
void Reload(wxString aux_path, std::map<std::string, std::vector<json>> paths);
void update_all_panel();
void update_all_cover();
@ -242,6 +242,7 @@ wxDECLARE_EVENT(EVT_AUXILIARY_IMPORT, wxCommandEvent);
wxDECLARE_EVENT(EVT_AUXILIARY_UPDATE_COVER, wxCommandEvent);
wxDECLARE_EVENT(EVT_AUXILIARY_UPDATE_DELETE, wxCommandEvent);
wxDECLARE_EVENT(EVT_AUXILIARY_UPDATE_RENAME, wxCommandEvent);
wxDECLARE_EVENT(EVT_AUXILIARY_DONE, wxCommandEvent);
}} // namespace Slic3r::GUI
#endif

View file

@ -2656,7 +2656,7 @@ bool GUI_App::on_init_inner()
sidebar().obj_list()->init();
//sidebar().aux_list()->init_auxiliary();
//mainframe->m_auxiliary->init_auxiliary();
mainframe->m_project->init_auxiliary();
// update_mode(); // !!! do that later
SetTopWindow(mainframe);

View file

@ -62,6 +62,11 @@ ProjectPanel::ProjectPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos,
Bind(EVT_PROJECT_RELOAD, &ProjectPanel::on_reload, this);
m_auxiliary = new AuxiliaryPanel(this);
m_auxiliary->Hide();
main_sizer->Add(m_auxiliary, wxSizerFlags().Expand().Proportion(1));
Bind(EVT_AUXILIARY_DONE, [this](wxCommandEvent& e) { update_model_data();});
SetSizer(main_sizer);
Layout();
Fit();
@ -91,38 +96,39 @@ void ProjectPanel::on_reload(wxCommandEvent& evt)
std::string model_author;
std::string cover_file;
std::string description;
std::map<std::string, std::vector<json>> files;
std::string p_name;
std::string p_author;
std::string p_description;
std::string p_cover_file;
std::map<std::string, std::vector<json>> files;
Model model = wxGetApp().plater()->model();
license = model.model_info->license;
model_name = model.model_info->model_name;
cover_file = model.model_info->cover_file;
description = model.model_info->description;
update_type = model.model_info->origin;
auto model_info = model.model_info;
if (model_info != nullptr) {
license = model_info->license;
model_name = model_info->model_name;
cover_file = model_info->cover_file;
description = model_info->description;
update_type = model_info->origin;
try {
if (!model_info->copyright.empty()) {
json copy_right = json::parse(model_info->copyright);
try {
if (!model.model_info->copyright.empty()) {
json copy_right = json::parse(model.model_info->copyright);
if (copy_right.is_array()) {
for (auto it = copy_right.begin(); it != copy_right.end(); it++) {
if ((*it).contains("author")) {
model_author = (*it)["author"].get<std::string>();
if (copy_right.is_array()) {
for (auto it = copy_right.begin(); it != copy_right.end(); it++) {
if ((*it).contains("author")) {
model_author = (*it)["author"].get<std::string>();
}
}
}
}
} catch (...) {
;
}
}
catch (...) {
;
}
if (model_author.empty() && model.design_info != nullptr)
model_author = model.design_info->Designer;
@ -134,12 +140,44 @@ void ProjectPanel::on_reload(wxCommandEvent& evt)
p_author = model.profile_info->ProfileUserName;
}
//file info
// file info
std::string file_path = encode_path(wxGetApp().plater()->model().get_auxiliary_file_temp_path().c_str());
if (!file_path.empty()) {
files = Reload(file_path);
wxGetApp().CallAfter([this, file_path, files] { m_auxiliary->Reload(file_path, files); });
} else {
clear_model_info();
return;
}
else {
bool has_content = false;
for (const string& v : {
update_type,
license,
model_name,
model_author,
cover_file,
description,
p_name,
p_author,
p_description,
p_cover_file,
}) {
if (!v.empty()) {
has_content = true;
break;
}
}
if (!has_content) {
for (const auto & file : files) {
if (!file.second.empty()) {
has_content = true;
break;
}
}
}
if (!has_content) {
// Nothing to show, just return
clear_model_info();
return;
}
@ -180,6 +218,7 @@ void ProjectPanel::on_reload(wxCommandEvent& evt)
void ProjectPanel::msw_rescale()
{
m_auxiliary->msw_rescale();
}
void ProjectPanel::on_size(wxSizeEvent &event)
@ -215,6 +254,9 @@ void ProjectPanel::OnScriptMessage(wxWebViewEvent& evt)
else if (strCmd == "request_3mf_info") {
m_web_init_completed = true;
}
else if (strCmd == "edit_project_info") {
show_info_editor(true);
}
else if (strCmd == "debug_info") {
//wxString msg = j["msg"];
//OutputDebugString(wxString::Format("Model_Web: msg = %s \r\n", msg));
@ -227,14 +269,24 @@ void ProjectPanel::OnScriptMessage(wxWebViewEvent& evt)
}
}
void ProjectPanel::show_info_editor(bool show)
{
m_browser->Show(!show);
m_auxiliary->Show(show);
Layout();
}
void ProjectPanel::update_model_data()
{
Model model = wxGetApp().plater()->model();
show_info_editor(false);
clear_model_info();
m_auxiliary->init_auxiliary();
//basics info
if (model.model_info == nullptr)
return;
//if (model.model_info == nullptr)
// return;
auto event = wxCommandEvent(EVT_PROJECT_RELOAD);
event.SetEventObject(this);
@ -258,7 +310,6 @@ std::map<std::string, std::vector<json>> ProjectPanel::Reload(wxString aux_path)
{
std::vector<fs::path> dir_cache;
fs::directory_iterator iter_end;
wxString m_root_dir;
std::map<std::string, std::vector<json>> m_paths_list;
const static std::array<wxString, 5> s_default_folders = {
@ -276,24 +327,16 @@ std::map<std::string, std::vector<json>> ProjectPanel::Reload(wxString aux_path)
fs::path new_aux_path(aux_path.ToStdWstring());
try {
fs::remove_all(fs::path(m_root_dir.ToStdWstring()));
}
catch (...) {
BOOST_LOG_TRIVIAL(error) << "Failed removing the auxiliary directory" << m_root_dir.c_str();
}
m_root_dir = aux_path;
// Check new path. If not exist, create a new one.
if (!fs::exists(new_aux_path)) {
fs::create_directory(new_aux_path);
// Create default folders if they are not loaded
for (auto folder : s_default_folders) {
wxString folder_path = aux_path + "/" + folder;
if (fs::exists(folder_path.ToStdWstring())) continue;
fs::create_directory(folder_path.ToStdWstring());
}
return m_paths_list;
}
// Create default folders if they are not loaded
for (auto folder : s_default_folders) {
wxString folder_path = aux_path + "/" + folder;
if (fs::exists(folder_path.ToStdWstring())) continue;
fs::create_directory(folder_path.ToStdWstring());
}
// Load from new path
@ -320,7 +363,8 @@ std::map<std::string, std::vector<json>> ProjectPanel::Reload(wxString aux_path)
wxString file_name = encode_path(file_path.c_str());
wxStat(file_name, &strucStat);
wxFileOffset filelen = strucStat.st_size;
pfile_obj["_filepath"] = file_path;
pfile_obj["filename"] = wxGetApp().url_encode(file_path_obj.filename().string().c_str());
pfile_obj["size"] = formatBytes((unsigned long)filelen);

View file

@ -32,6 +32,7 @@
#include "Event.hpp"
#include "libslic3r/ProjectTask.hpp"
#include "wxExtensions.hpp"
#include "Auxiliary.hpp"
#define AUFILE_GREY700 wxColour(107, 107, 107)
#define AUFILE_GREY500 wxColour(158, 158, 158)
@ -63,9 +64,12 @@ private:
bool m_reload_already = {false};
wxWebView* m_browser = {nullptr};
AuxiliaryPanel* m_auxiliary{nullptr};
wxString m_project_home_url;
wxString m_root_dir;
static inline int m_sequence_id = 8000;
void show_info_editor(bool show);
public:
@ -81,6 +85,7 @@ public:
void msw_rescale();
void update_model_data();
void clear_model_info();
void init_auxiliary() { m_auxiliary->init_auxiliary(); }
bool Show(bool show);
void OnScriptMessage(wxWebViewEvent& evt);