mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 20:21:12 -06:00 
			
		
		
		
	
		
			
				
	
	
		
			1224 lines
		
	
	
	
		
			44 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1224 lines
		
	
	
	
		
			44 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "Tab.hpp"
 | |
| #include "Auxiliary.hpp"
 | |
| #include "libslic3r/Utils.hpp"
 | |
| #include "libslic3r/Model.hpp"
 | |
| #include "libslic3r/Format/bbs_3mf.hpp"
 | |
| 
 | |
| #include <wx/app.h>
 | |
| #include <wx/button.h>
 | |
| #include <wx/scrolwin.h>
 | |
| #include <wx/sizer.h>
 | |
| 
 | |
| #include <wx/bmpcbox.h>
 | |
| #include <wx/bmpbuttn.h>
 | |
| #include <wx/treectrl.h>
 | |
| #include <wx/imaglist.h>
 | |
| #include <wx/settings.h>
 | |
| #include <wx/filedlg.h>
 | |
| #include <wx/wupdlock.h>
 | |
| #include <wx/dataview.h>
 | |
| #include <wx/tokenzr.h>
 | |
| #include <wx/arrstr.h>
 | |
| #include <wx/tglbtn.h>
 | |
| 
 | |
| #include "wxExtensions.hpp"
 | |
| #include "GUI_App.hpp"
 | |
| #include "GUI_ObjectList.hpp"
 | |
| #include "MainFrame.hpp"
 | |
| #include "Widgets/Label.hpp"
 | |
| 
 | |
| namespace Slic3r { namespace GUI {
 | |
| 
 | |
| 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);
 | |
| 
 | |
| 
 | |
| const std::vector<std::string> license_list = {
 | |
|     "BSD License",
 | |
|     "Apache License",
 | |
|     "GPL License",
 | |
|     "LGPL License",
 | |
|     "MIT License",
 | |
|     "CC License"
 | |
| };
 | |
| 
 | |
| 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;
 | |
|     m_file_path = file_path;
 | |
|     m_file_name = file_name;
 | |
| 
 | |
|     wxSize panel_size = m_type == MODEL_PICTURE ? AUFILE_PICTURES_PANEL_SIZE : AUFILE_PANEL_SIZE;
 | |
|     wxPanel::Create(parent, id, pos, panel_size, style);
 | |
|     SetBackgroundColour(AUFILE_GREY300);
 | |
|     wxBoxSizer *sizer_body = new wxBoxSizer(wxVERTICAL);
 | |
| 
 | |
|    SetSize(panel_size);
 | |
| 
 | |
|     if (m_type == MODEL_PICTURE) {
 | |
|         if (m_file_path.empty()) { return; }
 | |
|         auto image = new wxImage(encode_path(m_file_path.string().c_str()));
 | |
| 
 | |
|         //constrain
 | |
|         auto size = wxSize(0, 0);
 | |
|         float proportion = float(image->GetSize().x) / float(image->GetSize().y);
 | |
|         if (proportion >= 1) { 
 | |
|             size.x = AUFILE_PICTURES_SIZE.x;
 | |
|             size.y = AUFILE_PICTURES_SIZE.x / proportion;
 | |
|         } else {
 | |
|             size.y = AUFILE_PICTURES_SIZE.y;
 | |
|             size.x = AUFILE_PICTURES_SIZE.y * proportion;
 | |
|         }
 | |
| 
 | |
|         image->Rescale(size.x, size.y);
 | |
|         m_file_bitmap.bmp() = wxBitmap(*image);
 | |
|     } else {
 | |
|         m_bitmap_excel = ScalableBitmap(this, "placeholder_excel", 168);
 | |
|         m_bitmap_pdf   = ScalableBitmap(this, "placeholder_pdf", 168);
 | |
|         m_bitmap_txt   = ScalableBitmap(this, "placeholder_txt", 168);
 | |
| 
 | |
|         if (m_type == OTHERS) {m_file_bitmap = m_bitmap_txt;}
 | |
|         if (m_type == BILL_OF_MATERIALS) {
 | |
|             if (m_file_path.extension() == ".xls" || m_file_path.extension() == ".xlsx") {
 | |
|                 m_file_bitmap = m_bitmap_excel;
 | |
|             }
 | |
| 
 | |
|             if (m_file_path.extension() == ".pdf") { m_file_bitmap = m_bitmap_pdf; }
 | |
|             
 | |
|         }
 | |
|         if (m_type == ASSEMBLY_GUIDE) {m_file_bitmap = m_bitmap_pdf;}
 | |
|     }
 | |
|     
 | |
|     m_add_file = _L("Add File");
 | |
|     cover_text_left  = _L("Set as cover");
 | |
|     cover_text_right = _L("Rename");
 | |
|     cover_text_cover = _L("Cover");
 | |
| 
 | |
|     m_file_cover     = ScalableBitmap(this, "auxiliary_cover", 40);
 | |
|     m_file_edit_mask = ScalableBitmap(this, "auxiliary_edit_mask", 30);
 | |
|     m_file_delete    = ScalableBitmap(this, "auxiliary_delete", 20);
 | |
|     
 | |
| 
 | |
|     auto m_text_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(panel_size.x, AUFILE_TEXT_HEIGHT), wxTAB_TRAVERSAL);
 | |
|     m_text_panel->SetBackgroundColour(AUFILE_GREY300);
 | |
| 
 | |
|     wxBoxSizer *m_text_sizer = new wxBoxSizer(wxHORIZONTAL);
 | |
|     m_text_name              = new wxStaticText(m_text_panel, wxID_ANY, m_file_name, wxDefaultPosition, wxSize(panel_size.x, -1), wxST_ELLIPSIZE_END);
 | |
|     m_text_name->Wrap(panel_size.x - FromDIP(10));
 | |
|     m_text_name->SetFont(::Label::Body_14);
 | |
| 
 | |
|     m_input_name = new ::TextInput(m_text_panel, wxEmptyString, wxEmptyString, wxEmptyString, wxDefaultPosition, wxSize(panel_size.x - FromDIP(28), FromDIP(32)), wxTE_PROCESS_ENTER);
 | |
|     m_input_name->GetTextCtrl()->SetFont(::Label::Body_13);
 | |
|     m_input_name->SetFont(::Label::Body_14);
 | |
|     m_input_name->Hide();
 | |
| 
 | |
|     m_file_exit_rename = new wxStaticBitmap(m_text_panel, wxID_ANY, create_scaled_bitmap("auxiliary_delete", this, 20), wxDefaultPosition, wxSize(FromDIP(20), FromDIP(20)), 0);
 | |
| 
 | |
|     m_file_exit_rename->Bind(wxEVT_LEFT_UP, [this](auto& e) {
 | |
|         exit_rename_mode();
 | |
|     });
 | |
| 
 | |
|     m_text_sizer->Add(0, 0, 1, wxEXPAND, 0);
 | |
|     m_text_sizer->Add(m_text_name, 0, wxALIGN_CENTER, 0);
 | |
|     m_text_sizer->Add(m_input_name, 0, wxALIGN_CENTER, 0);
 | |
|     m_text_sizer->Add( 0, 0, 1, wxEXPAND, 0 );
 | |
|     m_text_sizer->Add(m_file_exit_rename, 0, wxALIGN_CENTER, 0);
 | |
|     m_file_exit_rename->Hide();
 | |
| 
 | |
|     m_text_panel->SetSizer(m_text_sizer);
 | |
|     m_text_panel->Layout();
 | |
|     sizer_body->Add(0, 0, 0, wxTOP, panel_size.y - AUFILE_TEXT_HEIGHT);
 | |
|     sizer_body->Add(m_text_panel, 0, wxALIGN_CENTER, 0);
 | |
| 
 | |
|     SetSizer(sizer_body);
 | |
|     Layout();
 | |
|     Fit();
 | |
| 
 | |
|     Bind(wxEVT_PAINT, &AuFile::OnPaint, this);
 | |
|     Bind(wxEVT_ERASE_BACKGROUND, &AuFile::OnEraseBackground, this);
 | |
|     Bind(wxEVT_ENTER_WINDOW, &AuFile::on_mouse_enter, this);
 | |
|     Bind(wxEVT_LEAVE_WINDOW, &AuFile::on_mouse_leave, this);
 | |
|     Bind(wxEVT_LEFT_UP, &AuFile::on_mouse_left_up, this);
 | |
|     Bind(wxEVT_LEFT_DCLICK, &AuFile::on_dclick, this);
 | |
|     m_input_name->Bind(wxEVT_TEXT_ENTER, &AuFile::on_input_enter, this);
 | |
| }
 | |
| 
 | |
| void AuFile::enter_rename_mode()
 | |
| {
 | |
|     m_input_name->Show();
 | |
|     m_file_exit_rename->Show();
 | |
|     m_text_name->Hide();
 | |
|     auto name = m_file_name.SubString(0, (m_file_name.Find(".") - 1));
 | |
|     m_input_name->GetTextCtrl()->SetLabelText(name);
 | |
|     Layout();
 | |
| }
 | |
| 
 | |
| void AuFile::exit_rename_mode()
 | |
| {
 | |
|     m_input_name->Hide();
 | |
|     m_file_exit_rename->Hide();
 | |
|     m_text_name->Show();
 | |
|     Layout();
 | |
| }
 | |
| 
 | |
| void AuFile::OnPaint(wxPaintEvent &event)
 | |
| {
 | |
|     wxPaintDC dc(this);
 | |
| #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);
 | |
|         PaintBackground(dc2);
 | |
|         PaintForeground(dc2);
 | |
|     }
 | |
| 
 | |
|     memdc.SelectObject(wxNullBitmap);
 | |
|     dc.DrawBitmap(bmp, 0, 0);
 | |
| #else
 | |
|     PaintBackground(dc);
 | |
|     PaintForeground(dc);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void AuFile::PaintBackground(wxDC &dc)
 | |
| {
 | |
|     wxColour backgroundColour = GetBackgroundColour();
 | |
|     if (!backgroundColour.Ok()) backgroundColour = AUFILE_GREY300;
 | |
|     dc.SetBrush(wxBrush(backgroundColour));
 | |
|     dc.SetPen(wxPen(backgroundColour, 1));
 | |
|     wxRect windowRect(wxPoint(0, 0), GetClientSize());
 | |
| 
 | |
|     //CalcUnscrolledPosition(windowRect.x, windowRect.y, &windowRect.x, &windowRect.y);
 | |
|     dc.DrawRectangle(windowRect);
 | |
| 
 | |
| 
 | |
|     wxSize size = m_type == MODEL_PICTURE ? AUFILE_PICTURES_SIZE : AUFILE_SIZE;
 | |
| 
 | |
|     if (m_type == AddFileButton)
 | |
|     {
 | |
|         auto pen_width = FromDIP(2);
 | |
|         dc.SetPen(wxPen(AUFILE_GREY500, pen_width));
 | |
|         dc.SetBrush(AUFILE_GREY200);
 | |
|         dc.DrawRoundedRectangle(pen_width / 2, pen_width / 2, size.x - pen_width / 2, size.y - pen_width / 2, AUFILE_ROUNDING);
 | |
| 
 | |
|         auto line_length = FromDIP(50);
 | |
|         dc.DrawLine(wxPoint((size.x - line_length) / 2, size.y / 2), wxPoint((size.x + line_length) / 2, size.y / 2));
 | |
|         dc.DrawLine(wxPoint(size.x / 2, (size.y - line_length) / 2), wxPoint(size.x / 2, (size.y + line_length) / 2));
 | |
| 
 | |
|         dc.SetFont(Label::Body_16);
 | |
|         auto sizet = dc.GetTextExtent(m_add_file);
 | |
|         auto pos = wxPoint(0, 0);
 | |
|         pos.x = (size.x - sizet.x) / 2;
 | |
|         pos.y = (size.y - 40); // to modify
 | |
|         dc.SetTextForeground(AUFILE_GREY500);
 | |
|         dc.DrawText(m_add_file, pos);
 | |
|     }
 | |
|     else {
 | |
|         dc.SetPen(AUFILE_GREY200);
 | |
|         dc.SetBrush(AUFILE_GREY200);
 | |
|         dc.DrawRoundedRectangle(0, 0, size.x, size.y, AUFILE_ROUNDING);
 | |
|         dc.DrawBitmap(m_file_bitmap.bmp(), (size.x - m_file_bitmap.GetBmpWidth()) / 2, (size.y - m_file_bitmap.GetBmpHeight()) / 2);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void AuFile::OnEraseBackground(wxEraseEvent &evt) {}
 | |
| 
 | |
| void AuFile::PaintForeground(wxDC &dc)
 | |
| {
 | |
|     wxSize size = m_type == MODEL_PICTURE ? AUFILE_PICTURES_SIZE : AUFILE_SIZE;
 | |
| 
 | |
|     if (m_hover) {
 | |
|         if (m_type == AddFileButton) {
 | |
|             auto pen_width = FromDIP(2);
 | |
|             dc.SetPen(wxPen(AUFILE_BRAND, pen_width));
 | |
|             dc.SetBrush(AUFILE_BRAND_TRANSPARENT);
 | |
|             dc.DrawRoundedRectangle(pen_width / 2, pen_width / 2, size.x - pen_width / 2, size.y - pen_width / 2, AUFILE_ROUNDING);
 | |
| 
 | |
|             auto line_length = FromDIP(50);
 | |
|             dc.DrawLine(wxPoint((size.x - line_length) / 2, size.y / 2), wxPoint((size.x + line_length) / 2, size.y / 2));
 | |
|             dc.DrawLine(wxPoint(size.x / 2, (size.y - line_length) / 2), wxPoint(size.x / 2, (size.y + line_length) / 2));
 | |
| 
 | |
|             auto sizet = dc.GetTextExtent(m_add_file);
 | |
|             auto pos = wxPoint(0, 0);
 | |
|             pos.x = (size.x - sizet.x) / 2;
 | |
|             pos.y = (size.y - 40); // to modify
 | |
|             dc.SetTextForeground(AUFILE_BRAND);
 | |
|             dc.DrawText(m_add_file, pos);
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         if (m_type == MODEL_PICTURE) {
 | |
|             dc.DrawBitmap(m_file_edit_mask.bmp(), 0, size.y - m_file_edit_mask.GetBmpSize().y); 
 | |
|         }
 | |
| 
 | |
| 
 | |
|         dc.SetFont(Label::Body_12);
 | |
|         dc.SetTextForeground(*wxWHITE);
 | |
|         if (m_type == MODEL_PICTURE) {
 | |
|             // left text
 | |
|             auto sizet = dc.GetTextExtent(cover_text_left);
 | |
|             auto pos   = wxPoint(0, 0);
 | |
|             pos.x      = (size.x / 2 - sizet.x) / 2;
 | |
|             pos.y      = (size.y - (m_file_edit_mask.GetBmpSize().y + sizet.y) / 2);
 | |
|             dc.DrawText(cover_text_left, pos);
 | |
| 
 | |
|             // right text
 | |
|             sizet = dc.GetTextExtent(cover_text_right);
 | |
|             pos   = wxPoint(0, 0);
 | |
|             pos.x = size.x / 2 + (size.x / 2 - sizet.x) / 2;
 | |
|             pos.y = (size.y - (m_file_edit_mask.GetBmpSize().y + sizet.y) / 2);
 | |
|             dc.DrawText(cover_text_right, pos);
 | |
| 
 | |
|             // Split
 | |
|             dc.SetPen(*wxWHITE);
 | |
|             dc.SetBrush(*wxWHITE);
 | |
|             pos   = wxPoint(0, 0);
 | |
|             pos.x = size.x / 2 - 1;
 | |
|             pos.y = size.y - FromDIP(24) - (m_file_edit_mask.GetBmpSize().y - FromDIP(24)) / 2;
 | |
|             dc.DrawRectangle(pos.x, pos.y, 2, FromDIP(24));
 | |
|         } else {
 | |
|             // right text
 | |
|            /* auto sizet = dc.GetTextExtent(cover_text_right);
 | |
|             auto pos   = wxPoint(0, 0);
 | |
|             pos.x      = (size.x - sizet.x) / 2;
 | |
|             pos.y      = (size.y - (m_file_edit_mask.GetBmpSize().y + sizet.y) / 2);
 | |
|             dc.DrawText(cover_text_right, pos);*/
 | |
|         }       
 | |
|     }
 | |
| 
 | |
|     if (m_cover) {
 | |
|         dc.SetTextForeground(*wxWHITE);
 | |
|         dc.DrawBitmap(m_file_cover.bmp(), size.x - m_file_cover.GetBmpSize().x, 0);
 | |
|         dc.SetFont(Label::Body_12);
 | |
|         auto sizet = dc.GetTextExtent(cover_text_cover);
 | |
|         auto pos   = wxPoint(0, 0);
 | |
|         pos.x      = size.x - sizet.x - FromDIP(3);
 | |
|         pos.y      = FromDIP(3);
 | |
|         dc.DrawText(cover_text_cover, pos);
 | |
|     }
 | |
| 
 | |
|     if (m_hover) { dc.DrawBitmap(m_file_delete.bmp(), size.x - m_file_delete.GetBmpSize().x - FromDIP(10), FromDIP(10)); }
 | |
| }
 | |
| 
 | |
| void AuFile::on_mouse_enter(wxMouseEvent &evt)
 | |
| {
 | |
|     m_hover = true;
 | |
|     Refresh();
 | |
| }
 | |
| 
 | |
| void AuFile::on_mouse_leave(wxMouseEvent &evt)
 | |
| {
 | |
|     m_hover = false;
 | |
|     Refresh();
 | |
| }
 | |
| 
 | |
| void AuFile::on_input_enter(wxCommandEvent &evt)
 | |
| {
 | |
|     auto     new_file_name = m_input_name->GetTextCtrl()->GetValue();
 | |
|     auto     m_valid_type  = Valid;
 | |
|     wxString info_line;
 | |
| 
 | |
|     const char *unusable_symbols = "<>[]:/\\|?*\"";
 | |
| 
 | |
|     const std::string unusable_suffix = PresetCollection::get_suffix_modified(); //"(modified)";
 | |
|     for (size_t i = 0; i < std::strlen(unusable_symbols); i++) {
 | |
|         if (new_file_name.find_first_of(unusable_symbols[i]) != std::string::npos) {
 | |
|             info_line    = _L("Name is invalid;") + "\n" + _L("illegal characters:") + " " + unusable_symbols;
 | |
|             m_valid_type = NoValid;
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (m_valid_type == Valid && new_file_name.find(unusable_suffix) != std::string::npos) {
 | |
|         info_line    = _L("Name is invalid;") + "\n" + _L("illegal suffix:") + "\n\t" + from_u8(PresetCollection::get_suffix_modified());
 | |
|         m_valid_type = NoValid;
 | |
|     }
 | |
| 
 | |
|     auto     existing  = false;
 | |
|     auto     dir       = m_file_path.branch_path();
 | |
|     auto     new_fullname = new_file_name + m_file_path.extension().string();
 | |
| 
 | |
|     
 | |
|     wxString new_fullname_path = dir.wstring() + "/" + new_fullname;
 | |
|     fs::path new_dir_path(new_fullname_path.c_str());
 | |
|     
 | |
| 
 | |
|     if (fs::exists(new_dir_path)) existing = true;
 | |
| 
 | |
|     if (m_valid_type == Valid && existing) {
 | |
|         info_line    = from_u8((boost::format(_u8L("The name \"%1%\" already exists.")) % new_file_name).str());
 | |
|         m_valid_type = NoValid;
 | |
|     }
 | |
| 
 | |
|     if (m_valid_type == Valid && new_file_name.empty()) {
 | |
|         info_line    = _L("The name is not allowed to be empty.");
 | |
|         m_valid_type = NoValid;
 | |
|     }
 | |
| 
 | |
|     if (m_valid_type == Valid && new_file_name.find_first_of(' ') == 0) {
 | |
|         info_line    = _L("The name is not allowed to start with space character.");
 | |
|         m_valid_type = NoValid;
 | |
|     }
 | |
| 
 | |
|     if (m_valid_type == Valid && new_file_name.find_last_of(' ') == new_file_name.length() - 1) {
 | |
|         info_line    = _L("The name is not allowed to end with space character.");
 | |
|         m_valid_type = NoValid;
 | |
|     }
 | |
| 
 | |
|     if (m_valid_type == Valid) {
 | |
|         fs::path oldPath = m_file_path;
 | |
|         fs::path newPath(new_dir_path);
 | |
|         fs::rename(oldPath, newPath);
 | |
|     } else {
 | |
|         /*MessageDialog msg_wingow(nullptr, info_line, _L(""),
 | |
|                                  wxICON_WARNING | wxOK);
 | |
|         if (msg_wingow.ShowModal() == wxID_CANCEL) {
 | |
|             m_input_name->GetTextCtrl()->SetValue(wxEmptyString);
 | |
|             return;
 | |
|         }*/
 | |
| 
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     // post event
 | |
|     auto event = wxCommandEvent(EVT_AUXILIARY_UPDATE_RENAME);
 | |
|     event.SetString(wxString::Format("%s|%s|%s", s_default_folders[m_type], m_file_path.wstring(), new_dir_path.wstring()));
 | |
|     event.SetEventObject(m_parent);
 | |
|     wxPostEvent(m_parent, event);
 | |
| 
 | |
|     // update layout
 | |
|     m_file_path = new_dir_path.string();
 | |
|     m_file_name = new_fullname;
 | |
|     m_text_name->SetLabel(new_fullname);
 | |
|     exit_rename_mode();
 | |
|     // evt.Skip();
 | |
| }
 | |
| 
 | |
| void AuFile::on_dclick(wxMouseEvent &evt) 
 | |
| {
 | |
|     if (m_type == AddFileButton)
 | |
|         return;
 | |
|     else
 | |
|         wxLaunchDefaultApplication(m_file_path.wstring(), 0);
 | |
| }
 | |
| 
 | |
| void AuFile::on_mouse_left_up(wxMouseEvent &evt)
 | |
| {
 | |
|     if (m_type == AddFileButton) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     wxSize size = m_type == MODEL_PICTURE ? AUFILE_PICTURES_SIZE : AUFILE_SIZE;
 | |
| 
 | |
|     auto pos = evt.GetPosition();
 | |
|     // set cover
 | |
|     auto mask_size    = wxSize(GetSize().x, m_file_edit_mask.GetBmpSize().y);
 | |
|     auto cover_left   = 0;
 | |
|     auto cover_top    = size.y - mask_size.y;
 | |
|     auto cover_right  = mask_size.x / 2;
 | |
|     auto cover_bottom = size.y;
 | |
| 
 | |
|     if (pos.x > cover_left && pos.x < cover_right && pos.y > cover_top && pos.y < cover_bottom) { 
 | |
|         if(m_type == MODEL_PICTURE)
 | |
|             on_set_cover(); 
 | |
|        /* else
 | |
|              on_set_rename();*/
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     // rename
 | |
|     auto rename_left   = mask_size.x / 2;
 | |
|     auto rename_top    = size.y - mask_size.y;
 | |
|     auto rename_right  = mask_size.x;
 | |
|     auto rename_bottom = size.y;
 | |
|     if (pos.x > rename_left && pos.x < rename_right && pos.y > rename_top && pos.y < rename_bottom) { on_set_rename(); return; }
 | |
| 
 | |
|     // close
 | |
|     auto close_left   = size.x - m_file_delete.GetBmpSize().x - FromDIP(10);
 | |
|     auto close_top    = FromDIP(10);
 | |
|     auto close_right  = size.x - FromDIP(10);
 | |
|     auto close_bottom = m_file_delete.GetBmpSize().y + FromDIP(10);
 | |
|     if (pos.x > close_left && pos.x < close_right && pos.y > close_top && pos.y < close_bottom) { on_set_delete(); return; }
 | |
| 
 | |
|     exit_rename_mode();
 | |
| }
 | |
| 
 | |
| void AuFile::on_set_cover()
 | |
| {
 | |
|     if (wxGetApp().plater()->model().model_info == nullptr) { wxGetApp().plater()->model().model_info = std::make_shared<ModelInfo>(); }
 | |
| 
 | |
|     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_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.c_str());
 | |
| 
 | |
|     if (!fs::exists(dir_path)) {
 | |
|         fs::create_directory(dir_path); 
 | |
|     }
 | |
| 
 | |
|     bool result = true;
 | |
|     wxImage thumbnail_img;
 | |
| 
 | |
|     result = generate_image(m_file_path.string(), thumbnail_img, _3MF_COVER_SIZE);
 | |
|     if (result) {
 | |
|         auto cover_img_path = dir_path.string() + "/thumbnail_3mf.png";
 | |
|         thumbnail_img.SaveFile(encode_path(cover_img_path.c_str()));
 | |
|     }
 | |
| 
 | |
|     result = generate_image(m_file_path.string(), thumbnail_img, PRINTER_THUMBNAIL_SMALL_SIZE);
 | |
|     if (result) {
 | |
|         auto small_img_path = dir_path.string() + "/thumbnail_small.png";
 | |
|         thumbnail_img.SaveFile(encode_path(small_img_path.c_str()));
 | |
|     }
 | |
| 
 | |
|     result = generate_image(m_file_path.string(), thumbnail_img, PRINTER_THUMBNAIL_MIDDLE_SIZE);
 | |
|     if (result) {
 | |
|         auto middle_img_path = dir_path.string() + "/thumbnail_middle.png";
 | |
|         thumbnail_img.SaveFile(encode_path(middle_img_path.c_str()));
 | |
|     }
 | |
| 
 | |
|     auto evt = wxCommandEvent(EVT_AUXILIARY_UPDATE_COVER);
 | |
|     evt.SetString(s_default_folders[m_type]);
 | |
|     evt.SetEventObject(m_parent);
 | |
|     wxPostEvent(m_parent, evt);
 | |
| }
 | |
| 
 | |
| void AuFile::on_set_delete()
 | |
| {
 | |
|     fs::path bfs_path = m_file_path;
 | |
|     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_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.c_str());
 | |
| 
 | |
|         auto cover_img_path = dir_path.string() + "/thumbnail_3mf.png";
 | |
|         auto small_img_path = dir_path.string() + "/thumbnail_small.png";
 | |
|         auto middle_img_path = dir_path.string() + "/thumbnail_middle.png";
 | |
| 
 | |
|         if (fs::exists(fs::path(cover_img_path))) { fs::remove(fs::path(cover_img_path));}
 | |
|         if (fs::exists(fs::path(small_img_path))) { fs::remove(fs::path(small_img_path)); }
 | |
|         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 (is_fine) {
 | |
|         auto evt = wxCommandEvent(EVT_AUXILIARY_UPDATE_DELETE);
 | |
|         evt.SetString(wxString::Format("%s|%s", s_default_folders[m_type], m_file_path.wstring()));
 | |
|         evt.SetEventObject(m_parent);
 | |
|         wxPostEvent(m_parent, evt);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void AuFile::on_set_rename() { enter_rename_mode(); }
 | |
| 
 | |
| void AuFile::on_set_open() {}
 | |
| 
 | |
| void AuFile::set_cover(bool cover)
 | |
| {
 | |
|     m_cover = cover;
 | |
|     Refresh();
 | |
| }
 | |
| 
 | |
| AuFile::~AuFile() {}
 | |
| 
 | |
| void AuFile::msw_rescale() 
 | |
| { 
 | |
|     m_file_cover     = ScalableBitmap(this, "auxiliary_cover", 40);
 | |
|     m_file_edit_mask = ScalableBitmap(this, "auxiliary_edit_mask", FromDIP(30));
 | |
|     m_file_delete    = ScalableBitmap(this, "auxiliary_delete", 20);
 | |
| 
 | |
|     if (m_type == MODEL_PICTURE) {
 | |
|         if (m_file_path.empty()) { return;}
 | |
|         auto image = new wxImage(encode_path(m_file_path.string().c_str()));
 | |
|         // constrain
 | |
|         auto  size       = wxSize(0, 0);
 | |
|         float proportion = float(image->GetSize().x) / float(image->GetSize().y);
 | |
|         if (proportion >= 1) {
 | |
|             size.x = FromDIP(300);
 | |
|             size.y = FromDIP(300) / proportion;
 | |
|         } else {
 | |
|             size.y = FromDIP(300);
 | |
|             size.x = FromDIP(300) * proportion;
 | |
|         }
 | |
| 
 | |
|         image->Rescale(size.x, size.y);
 | |
|         m_file_bitmap.bmp() = wxBitmap(*image);
 | |
|     } else {
 | |
|         m_bitmap_excel = ScalableBitmap(this, "placeholder_excel", 168);
 | |
|         m_bitmap_pdf   = ScalableBitmap(this, "placeholder_pdf", 168);
 | |
|         m_bitmap_txt   = ScalableBitmap(this, "placeholder_txt", 168);
 | |
| 
 | |
|         if (m_type == OTHERS) { m_file_bitmap = m_bitmap_txt; }
 | |
|         if (m_type == BILL_OF_MATERIALS) { m_file_bitmap = m_bitmap_excel; }
 | |
|         if (m_type == ASSEMBLY_GUIDE) { m_file_bitmap = m_bitmap_pdf; }
 | |
|     }
 | |
|     Refresh();
 | |
| }
 | |
| 
 | |
| AuFolderPanel::AuFolderPanel(wxWindow *parent, AuxiliaryFolderType type, wxWindowID id, const wxPoint &pos, const wxSize &size, long style)
 | |
|     : wxPanel(parent, id, pos, size, style)
 | |
| {
 | |
|     m_type = type;
 | |
|     SetBackgroundColour(AUFILE_GREY300);
 | |
|     wxBoxSizer *sizer_main = new wxBoxSizer(wxVERTICAL);
 | |
| 
 | |
|     m_scrolledWindow = new wxScrolledWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL | wxVSCROLL);
 | |
|     m_scrolledWindow->SetScrollRate(5, 5);
 | |
|     wxBoxSizer *sizer_body = new wxBoxSizer(wxVERTICAL);
 | |
|     wxBoxSizer *sizer_top  = new wxBoxSizer(wxHORIZONTAL);
 | |
| 
 | |
|     StateColor btn_bg_white(std::pair<wxColour, int>(AMS_CONTROL_DISABLE_COLOUR, StateColor::Disabled), std::pair<wxColour, int>(AMS_CONTROL_DISABLE_COLOUR, StateColor::Pressed),
 | |
|                             std::pair<wxColour, int>(AMS_CONTROL_DEF_BLOCK_BK_COLOUR, StateColor::Hovered),
 | |
|                             std::pair<wxColour, int>(AMS_CONTROL_WHITE_COLOUR, StateColor::Normal));
 | |
| 
 | |
|     StateColor btn_bd_white(std::pair<wxColour, int>(AMS_CONTROL_WHITE_COLOUR, StateColor::Disabled), std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Enabled));
 | |
|     //m_button_add = new AuFile(m_scrolledWindow, fs::path(), "", AddFileButton, -1);
 | |
|     /*m_button_add->SetBackgroundColor(btn_bg_white);
 | |
|     m_button_add->SetBorderColor(btn_bd_white);
 | |
|     m_button_add->SetMinSize(wxSize(-1, FromDIP(24)));
 | |
|     m_button_add->SetCornerRadius(FromDIP(12));
 | |
|     m_button_add->SetFont(Label::Body_14);*/
 | |
| 
 | |
|     m_big_button_add = new AuFile(m_scrolledWindow, fs::path(), "", AddFileButton, -1);
 | |
| 
 | |
|     /*m_button_del = new Button(m_scrolledWindow, _L("Delete"), "auxiliary_delete_file", 12, 12);
 | |
|     m_button_del->SetBackgroundColor(btn_bg_white);
 | |
|     m_button_del->SetBorderColor(btn_bd_white);
 | |
|     m_button_del->SetMinSize(wxSize(FromDIP(80), FromDIP(24)));
 | |
|     m_button_del->SetCornerRadius(12);
 | |
|     m_button_del->SetFont(Label::Body_14);*/
 | |
|     // m_button_del->Bind(wxEVT_LEFT_UP, &AuxiliaryPanel::on_delete, this);
 | |
| 
 | |
|     sizer_top->Add(0, 0, 0, wxLEFT, FromDIP(10));
 | |
|     m_gsizer_content = new wxWrapSizer(wxHORIZONTAL, wxWRAPSIZER_DEFAULT_FLAGS);
 | |
|     //if (m_type == MODEL_PICTURE) {
 | |
|     //    //sizer_top->Add(m_button_add, 0, wxALL, 0);
 | |
|     //    //m_big_button_add->Hide();
 | |
|     //}
 | |
|     //else {
 | |
|         m_gsizer_content->Add(m_big_button_add, 0, wxALL, FromDIP(8));
 | |
|         //m_button_add->Hide();
 | |
|     //}
 | |
|     // sizer_top->Add(m_button_del, 0, wxALL, 0);
 | |
|     sizer_body->Add(sizer_top, 0, wxEXPAND | wxTOP, FromDIP(35));
 | |
|     sizer_body->AddSpacer(FromDIP(14));
 | |
|     sizer_body->Add(m_gsizer_content, 0, 0, 0);
 | |
|     m_scrolledWindow->SetSizer(sizer_body);
 | |
|     m_scrolledWindow->Layout();
 | |
|     sizer_main->Add(m_scrolledWindow, 1, wxEXPAND | wxLEFT, FromDIP(40));
 | |
| 
 | |
|     this->SetSizer(sizer_main);
 | |
|     this->Layout();
 | |
| 
 | |
|     m_big_button_add->Bind(wxEVT_LEFT_DOWN, [this](auto& e)
 | |
|         {
 | |
|             auto evt = wxCommandEvent(EVT_AUXILIARY_IMPORT);
 | |
|             evt.SetString(s_default_folders[m_type]);
 | |
|             evt.SetEventObject(m_parent);
 | |
|             wxPostEvent(m_parent, evt);
 | |
|         });
 | |
|     //m_button_add->Bind(wxEVT_LEFT_UP, &AuFolderPanel::on_add, this);
 | |
| }
 | |
| 
 | |
| void AuFolderPanel::clear()
 | |
| {
 | |
|     for (auto i = 0; i < m_aufiles_list.GetCount(); i++) {
 | |
|         AuFiles *aufile = m_aufiles_list[i];
 | |
|         if (aufile->file) { aufile->file->Destroy(); }
 | |
|     }
 | |
|     m_aufiles_list.clear();
 | |
|     Layout();
 | |
|     Refresh();
 | |
| }
 | |
| 
 | |
| void AuFolderPanel::update(std::vector<fs::path> paths)
 | |
| {
 | |
|     clear();
 | |
|     for (auto i = 0; i < paths.size(); i++) {
 | |
|         std::string temp_name   = fs::path(paths[i].c_str()).filename().string();
 | |
|         auto name             = encode_path(temp_name.c_str());
 | |
| 
 | |
|         auto        aufile = new AuFile(m_scrolledWindow, paths[i], name, m_type, wxID_ANY);
 | |
|         m_gsizer_content->Add(aufile, 0, wxALL, FromDIP(8));
 | |
|         auto af  = new AuFiles;
 | |
|         af->path = paths[i].string();
 | |
|         af->file = aufile;
 | |
|         m_aufiles_list.push_back(af);
 | |
|     }
 | |
|     m_gsizer_content->Layout();
 | |
|     Layout();
 | |
| }
 | |
| 
 | |
| void AuFolderPanel::msw_rescale() 
 | |
| {
 | |
|     //m_button_add->SetMinSize(wxSize(-1, FromDIP(24)));
 | |
|     for (auto i = 0; i < m_aufiles_list.GetCount(); i++) {
 | |
|         AuFiles *aufile = m_aufiles_list[i];
 | |
|         aufile->file->msw_rescale();
 | |
|     }
 | |
| }
 | |
| 
 | |
| void AuFolderPanel::on_add(wxMouseEvent& event)
 | |
| {
 | |
|     auto evt = wxCommandEvent(EVT_AUXILIARY_IMPORT);
 | |
|     evt.SetString(s_default_folders[m_type]);
 | |
|     evt.SetEventObject(m_parent);
 | |
|     wxPostEvent(m_parent, evt);
 | |
| }
 | |
| 
 | |
| void AuFolderPanel::on_delete(wxCommandEvent &event) { clear(); }
 | |
| 
 | |
| AuFolderPanel::~AuFolderPanel()
 | |
| {
 | |
| }
 | |
| 
 | |
| void AuFolderPanel::update_cover()
 | |
| {
 | |
|     if (wxGetApp().plater()->model().model_info != nullptr) {
 | |
|         for (auto i = 0; i < m_aufiles_list.GetCount(); i++) {
 | |
|             AuFiles *aufile = m_aufiles_list[i];
 | |
|             if (wxGetApp().plater()->model().model_info->cover_file == aufile->file->m_file_name) {
 | |
|                 aufile->file->set_cover(true);
 | |
|             } else {
 | |
|                 aufile->file->set_cover(false);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| AuxiliaryPanel::AuxiliaryPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size, long style) : wxPanel(parent, id, pos, size, style)
 | |
| {
 | |
|     init_tabpanel();
 | |
|     // init_auxiliary();
 | |
| 
 | |
|     m_main_sizer = new wxBoxSizer(wxHORIZONTAL);
 | |
|     m_main_sizer->Add(m_tabpanel, 1, wxEXPAND | wxLEFT, 0);
 | |
|     SetSizerAndFit(m_main_sizer);
 | |
|     Bind(wxEVT_SIZE, &AuxiliaryPanel::on_size, this);
 | |
|     Bind(EVT_AUXILIARY_IMPORT, &AuxiliaryPanel::on_import_file, this);
 | |
| 
 | |
|     // cover -event
 | |
|     Bind(EVT_AUXILIARY_UPDATE_COVER, [this](wxCommandEvent &e) { update_all_cover(); });
 | |
| 
 | |
|     // delete event
 | |
|     Bind(EVT_AUXILIARY_UPDATE_DELETE, [this](wxCommandEvent &e) {
 | |
|         auto info_str = e.GetString();
 | |
| 
 | |
|         wxArrayString     parems;
 | |
|         wxStringTokenizer tokenizer(info_str, "|");
 | |
|         while (tokenizer.HasMoreTokens()) {
 | |
|             wxString token = tokenizer.GetNextToken();
 | |
|             parems.Add(token);
 | |
|         }
 | |
| 
 | |
| 
 | |
|         auto model = parems[0];
 | |
|         auto name  = parems[1];
 | |
| 
 | |
|         auto iter = m_paths_list.find(model.ToStdString());
 | |
|         if (iter != m_paths_list.end()) {
 | |
|             auto list = iter->second;
 | |
|             for (auto i = 0; i < list.size(); i++) {
 | |
|                 if (list[i].wstring() == name) {
 | |
|                     list.erase(std::begin(list) + i);
 | |
|                     break;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             m_paths_list[model.ToStdString()] = list;
 | |
|             update_all_panel();
 | |
|             update_all_cover();
 | |
|         }
 | |
|     });
 | |
| 
 | |
|     // rename event
 | |
|     Bind(EVT_AUXILIARY_UPDATE_RENAME, [this](wxCommandEvent &e) {
 | |
|         auto info_str = e.GetString();
 | |
| 
 | |
|         wxArrayString     parems;
 | |
|         wxStringTokenizer tokenizer(info_str, "|");
 | |
|         while (tokenizer.HasMoreTokens()) {
 | |
|             wxString token = tokenizer.GetNextToken();
 | |
|             parems.Add(token);
 | |
|         }
 | |
| 
 | |
|         auto model    = parems[0];
 | |
|         auto old_name = parems[1];
 | |
|         auto new_name = parems[2];
 | |
| 
 | |
|         auto iter = m_paths_list.find(model.ToStdString());
 | |
|         if (iter != m_paths_list.end()) {
 | |
|             auto list = iter->second;
 | |
|             for (auto i = 0; i < list.size(); i++) {
 | |
|                 if (list[i].wstring() == old_name) {
 | |
|                     list[i] = fs::path(new_name.c_str());
 | |
|                     break;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             m_paths_list[model.ToStdString()] = list;
 | |
|         }
 | |
|     });
 | |
| }
 | |
| 
 | |
| void AuxiliaryPanel::Split(const std::string &src, const std::string &separator, std::vector<std::string> &dest)
 | |
| {
 | |
|     std::string            str = src;
 | |
|     std::string            substring;
 | |
|     std::string::size_type start = 0, index;
 | |
|     dest.clear();
 | |
|     index = str.find_first_of(separator, start);
 | |
|     do {
 | |
|         if (index != string::npos) {
 | |
|             substring = str.substr(start, index - start);
 | |
|             dest.push_back(substring);
 | |
|             start = index + separator.size();
 | |
|             index = str.find(separator, start);
 | |
|             if (start == string::npos) break;
 | |
|         }
 | |
|     } while (index != string::npos);
 | |
| 
 | |
|     // the last part
 | |
|     substring = str.substr(start);
 | |
|     dest.push_back(substring);
 | |
| }
 | |
| 
 | |
| AuxiliaryPanel::~AuxiliaryPanel() {}
 | |
| 
 | |
| void AuxiliaryPanel::init_bitmap()
 | |
| {
 | |
|     /*m_signal_strong_img = create_scaled_bitmap("monitor_signal_strong", nullptr, 24);
 | |
|     m_signal_middle_img = create_scaled_bitmap("monitor_signal_middle", nullptr, 24);
 | |
|     m_signal_weak_img   = create_scaled_bitmap("monitor_signal_weak", nullptr, 24);
 | |
|     m_signal_no_img     = create_scaled_bitmap("monitor_signal_no", nullptr, 24);
 | |
|     m_printer_img       = create_scaled_bitmap("monitor_printer", nullptr, 26);
 | |
|     m_arrow_img         = create_scaled_bitmap("monitor_arrow", nullptr, 14);*/
 | |
| }
 | |
| 
 | |
| void AuxiliaryPanel::init_tabpanel()
 | |
| {
 | |
|     auto        m_side_tools     = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(220), FromDIP(18)));
 | |
|     wxBoxSizer *sizer_side_tools = new wxBoxSizer(wxVERTICAL);
 | |
|     sizer_side_tools->Add(m_side_tools, 1, wxEXPAND, 0);
 | |
|     m_tabpanel = new Tabbook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, sizer_side_tools, wxNB_LEFT | wxTAB_TRAVERSAL | wxNB_NOPAGETHEME);
 | |
|     m_tabpanel->SetBackgroundColour(*wxWHITE);
 | |
|     m_tabpanel->Bind(wxEVT_BOOKCTRL_PAGE_CHANGED, [this](wxBookCtrlEvent &e) { ; });
 | |
| 
 | |
|     m_designer_panel = new DesignerPanel(m_tabpanel, AuxiliaryFolderType::DESIGNER);
 | |
|     m_pictures_panel          = new AuFolderPanel(m_tabpanel, AuxiliaryFolderType::MODEL_PICTURE);
 | |
|     m_bill_of_materials_panel = new AuFolderPanel(m_tabpanel, AuxiliaryFolderType::BILL_OF_MATERIALS);
 | |
|     m_assembly_panel          = new AuFolderPanel(m_tabpanel, AuxiliaryFolderType::ASSEMBLY_GUIDE);
 | |
|     m_others_panel            = new AuFolderPanel(m_tabpanel, AuxiliaryFolderType::OTHERS);
 | |
| 
 | |
|     m_tabpanel->AddPage(m_designer_panel, _L("Basic Info"), "", true);
 | |
|     m_tabpanel->AddPage(m_pictures_panel, _L("Pictures"), "", false);
 | |
|     m_tabpanel->AddPage(m_bill_of_materials_panel, _L("Bill of Materials"), "", false);
 | |
|     m_tabpanel->AddPage(m_assembly_panel, _L("Assembly Guide"), "", false);
 | |
|     m_tabpanel->AddPage(m_others_panel, _L("Others"), "", false);
 | |
| }
 | |
| 
 | |
| wxWindow *AuxiliaryPanel::create_side_tools()
 | |
| {
 | |
|     wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
 | |
|     auto        panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(0, FromDIP(50)));
 | |
|     panel->SetBackgroundColour(wxColour(135, 206, 250));
 | |
|     panel->SetSizer(sizer);
 | |
|     sizer->Layout();
 | |
|     panel->Fit();
 | |
|     return panel;
 | |
| }
 | |
| 
 | |
| void AuxiliaryPanel::msw_rescale() { 
 | |
|     m_pictures_panel->msw_rescale();
 | |
|     m_bill_of_materials_panel->msw_rescale();
 | |
|     m_assembly_panel->msw_rescale();
 | |
|     m_others_panel->msw_rescale();
 | |
|     m_designer_panel->msw_rescale();
 | |
| }
 | |
| 
 | |
| void AuxiliaryPanel::on_size(wxSizeEvent &event)
 | |
| {
 | |
|     if (!wxGetApp().mainframe) return;
 | |
|     Layout();
 | |
|     Refresh();
 | |
| }
 | |
| 
 | |
| bool AuxiliaryPanel::Show(bool show) { return wxPanel::Show(show); }
 | |
| 
 | |
| // core logic
 | |
| 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);
 | |
| }
 | |
| 
 | |
| void AuxiliaryPanel::on_import_file(wxCommandEvent &event)
 | |
| {
 | |
|     auto file_model = event.GetString();
 | |
| 
 | |
|     wxString     src_path;
 | |
|     wxString     dst_path;
 | |
| 
 | |
|      wxString wildcard = wxFileSelectorDefaultWildcardStr;
 | |
| 
 | |
|     if (file_model == s_default_folders[MODEL_PICTURE]) {
 | |
|         //wildcard = wxT("JPEG files (*.jpeg)|*.jpeg|BMP files (*.bmp)|*.bmp|GIF files (*.gif)|*.gif|PNG files (*.png)|*.png|JPG files (*.jpg)|*.jpg");
 | |
|         wildcard = wxT("files (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp");
 | |
|     } 
 | |
| 
 | |
|     if (file_model == s_default_folders[OTHERS]) {  wildcard = wxT("TXT files (*.txt)|*.txt"); }
 | |
|     if (file_model == s_default_folders[BILL_OF_MATERIALS]){ wildcard = wxT("EXCEL files (*.xls)|*.xls|EXCEL files (*.xlsx)|*.xlsx|PDF files (*.pdf)|*.pdf"); }
 | |
|     if (file_model == s_default_folders[ASSEMBLY_GUIDE]) { wildcard = wxT("PDF files (*.pdf)|*.pdf"); }
 | |
| 
 | |
|     wxFileDialog dialog(this, _L("Choose files"), wxEmptyString, wxEmptyString, wildcard, wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);
 | |
|     if (dialog.ShowModal() == wxID_OK) {
 | |
|         wxArrayString file_paths;
 | |
|         dialog.GetPaths(file_paths);
 | |
| 
 | |
|         for (wxString file_path : file_paths) {
 | |
|             // Copy imported file to project temp directory
 | |
|             fs::path src_bfs_path(file_path.ToStdWstring());
 | |
|             wxString dir_path = m_root_dir;
 | |
|             dir_path += "/" + file_model;
 | |
|             
 | |
| 
 | |
| 
 | |
|             auto is_exist = false;
 | |
|             auto iter = m_paths_list.find(file_model.ToStdString());
 | |
|             if (iter != m_paths_list.end()) {
 | |
|                 std::vector<fs::path> list = iter->second;
 | |
|                 for (auto i = 0; i < list.size(); i++) {
 | |
|                     if (src_bfs_path.filename() == list[i].filename()) { 
 | |
|                         is_exist = true;
 | |
|                         break;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             
 | |
|             if (!is_exist) {
 | |
|                 dir_path += "/" + src_bfs_path.filename().generic_wstring();
 | |
|             } else {
 | |
|                 time_t t1 = time(0);
 | |
|                 char   ch1[64];
 | |
|                 strftime(ch1, sizeof(ch1), "%T", localtime(&t1));
 | |
|                 std::string time_text = ch1;
 | |
| 
 | |
|                 wxString name = src_bfs_path.filename().generic_wstring();
 | |
|                 auto before_name = replaceSpace(name.ToStdString(), src_bfs_path.extension().string(), "");
 | |
|                 time_text = replaceSpace(time_text, ":", "_");
 | |
|                 dir_path += "/" + before_name + "_" + time_text + src_bfs_path.extension().wstring();
 | |
|             }
 | |
|            
 | |
| 
 | |
|             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;
 | |
|             Slic3r::put_other_changes();
 | |
| 
 | |
|             // add in file list
 | |
|             iter = m_paths_list.find(file_model.ToStdString());
 | |
|             auto file_fs_path = fs::path(dir_path.c_str());
 | |
|             if (iter != m_paths_list.end()) {
 | |
|                 m_paths_list[file_model.ToStdString()].push_back(file_fs_path);
 | |
|             } else {
 | |
|                 m_paths_list[file_model.ToStdString()] = std::vector<fs::path>{file_fs_path};
 | |
|             }
 | |
|         }
 | |
|         update_all_panel();
 | |
|         update_all_cover();
 | |
|     }
 | |
| }
 | |
| 
 | |
| void AuxiliaryPanel::create_folder(wxString name)
 | |
| {
 | |
|     wxString folder_name = name;
 | |
| 
 | |
|     // Create folder in file system
 | |
|     fs::path bfs_path((m_root_dir + "/" + folder_name).ToStdWstring());
 | |
|     if (fs::exists(bfs_path)) {
 | |
|         try {
 | |
|             bool is_done = fs::remove_all(bfs_path);
 | |
|         } catch (...) {
 | |
|             BOOST_LOG_TRIVIAL(error) << "Failed  removing the auxiliary directory " << m_root_dir.c_str();
 | |
|         }
 | |
|     }
 | |
|     fs::create_directory(bfs_path);
 | |
| }
 | |
| 
 | |
| std::string AuxiliaryPanel::replaceSpace(std::string s, std::string ts, std::string ns)
 | |
| {
 | |
|     int    index   = -1;
 | |
|     while ((index = s.find(ts.c_str())) >= 0) { s = s.replace(index, ts.length(), ns.c_str()); }
 | |
|     return s;
 | |
| }
 | |
| 
 | |
| void AuxiliaryPanel::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;
 | |
|     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());
 | |
|         }
 | |
|         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.c_str());
 | |
| 
 | |
| 
 | |
|                     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();
 | |
| }
 | |
| 
 | |
| void AuxiliaryPanel::update_all_panel()
 | |
| {
 | |
|     std::map<std::string, std::vector<fs::path>>::iterator mit;
 | |
| 
 | |
|     Freeze();
 | |
|     m_pictures_panel->clear();
 | |
|     m_bill_of_materials_panel->clear();
 | |
|     m_assembly_panel->clear();
 | |
|     m_others_panel->clear();
 | |
| 
 | |
|     for (mit = m_paths_list.begin(); mit != m_paths_list.end(); mit++) {
 | |
|         if (mit->first == "Model Pictures") { m_pictures_panel->update(mit->second); }
 | |
|         if (mit->first == "Bill of Materials") { m_bill_of_materials_panel->update(mit->second); }
 | |
|         if (mit->first == "Assembly Guide") { m_assembly_panel->update(mit->second); }
 | |
|         if (mit->first == "Others") { m_others_panel->update(mit->second); }
 | |
|     }
 | |
|     Thaw();
 | |
| }
 | |
| 
 | |
| void AuxiliaryPanel::update_all_cover()
 | |
| {
 | |
|     std::map<std::string, std::vector<fs::path>>::iterator mit;
 | |
|     for (mit = m_paths_list.begin(); mit != m_paths_list.end(); mit++) {
 | |
|         if (mit->first == "Model Pictures") { m_pictures_panel->update_cover(); }
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
|  DesignerPanel::DesignerPanel(wxWindow *          parent,
 | |
|                              AuxiliaryFolderType type,
 | |
|                              wxWindowID          id /*= wxID_ANY*/,
 | |
|                              const wxPoint &     pos /*= wxDefaultPosition*/,
 | |
|                              const wxSize &      size /*= wxDefaultSize*/,
 | |
|                              long                style /*= wxTAB_TRAVERSAL*/)
 | |
|      : wxPanel(parent, id, pos, size, style)
 | |
| {
 | |
|      SetBackgroundColour(AUFILE_GREY300);
 | |
|      wxBoxSizer *m_sizer_body = new wxBoxSizer(wxVERTICAL);
 | |
|      wxBoxSizer *m_sizer_designer = new wxBoxSizer(wxHORIZONTAL);
 | |
| 
 | |
|      auto m_text_designer = new wxStaticText(this, wxID_ANY, _L("Author"), wxDefaultPosition, wxSize(120, -1), 0);
 | |
|      m_text_designer->Wrap(-1);
 | |
|      m_sizer_designer->Add(m_text_designer, 0, wxALIGN_CENTER, 0);
 | |
| 
 | |
|      m_input_designer =  new ::TextInput(this, wxEmptyString, wxEmptyString, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(450), FromDIP(30)), wxTE_PROCESS_ENTER);
 | |
|      m_input_designer->GetTextCtrl()->SetFont(::Label::Body_14);
 | |
|      m_input_designer->GetTextCtrl()->SetSize(wxSize(FromDIP(450), FromDIP(22)));
 | |
|      m_sizer_designer->Add(m_input_designer, 0, wxALIGN_CENTER, 0);
 | |
| 
 | |
|      wxBoxSizer *m_sizer_model_name = new wxBoxSizer(wxHORIZONTAL);
 | |
| 
 | |
|      auto m_text_model_name = new wxStaticText(this, wxID_ANY, _L("Model Name"), wxDefaultPosition, wxSize(120, -1), 0);
 | |
|      m_text_model_name->Wrap(-1);
 | |
|      m_sizer_model_name->Add(m_text_model_name, 0, wxALIGN_CENTER, 0);
 | |
| 
 | |
|      m_imput_model_name =  new ::TextInput(this, wxEmptyString, wxEmptyString, wxEmptyString, wxDefaultPosition,wxSize(FromDIP(450),FromDIP(30)), wxTE_PROCESS_ENTER);
 | |
|      m_imput_model_name->GetTextCtrl()->SetFont(::Label::Body_14);
 | |
|      m_imput_model_name->GetTextCtrl()->SetSize(wxSize(FromDIP(450), FromDIP(22)));
 | |
|      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);
 | |
|      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_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();
 | |
| 
 | |
|      SetSizer(m_sizer_body);
 | |
|      Layout();
 | |
|      Fit();
 | |
| 
 | |
|      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);
 | |
| }
 | |
| 
 | |
|  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];
 | |
|          }
 | |
|      }
 | |
|  }
 | |
| 
 | |
| 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);
 | |
| }
 | |
| 
 | |
| void DesignerPanel::on_input_enter_designer(wxCommandEvent &evt) 
 | |
| { 
 | |
|     auto text  = evt.GetString();
 | |
|     wxGetApp().plater()->model().SetDesigner(std::string(text.ToUTF8().data()), "");
 | |
| }
 | |
| 
 | |
| 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());
 | |
|     }
 | |
| }
 | |
| 
 | |
| void DesignerPanel::update_info() 
 | |
| {
 | |
|     if (wxGetApp().plater()->model().design_info != nullptr) {
 | |
|         wxString text = wxString::FromUTF8(wxGetApp().plater()->model().design_info->Designer);
 | |
|         m_input_designer->GetTextCtrl()->SetValue(text);
 | |
|     } else {
 | |
|         m_input_designer->GetTextCtrl()->SetValue(wxEmptyString);
 | |
|     }
 | |
| 
 | |
|     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);
 | |
|     } else {
 | |
|          m_imput_model_name->GetTextCtrl()->SetValue(wxEmptyString);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void DesignerPanel::msw_rescale()
 | |
| {
 | |
|     m_input_designer->GetTextCtrl()->SetSize(wxSize(FromDIP(450), FromDIP(22)));
 | |
|     m_imput_model_name->GetTextCtrl()->SetSize(wxSize(FromDIP(450), FromDIP(22)));
 | |
| }
 | |
| 
 | |
| }} // namespace Slic3r::GUI
 | 
