mirror of
https://git.mirrors.martin98.com/https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-13 21:11:48 +08:00

1. first formal version of macos 2. add the bambu networking plugin install logic 3. auto compute the wipe volume when filament change 4. add the logic of wiping into support 5. refine the GUI layout and icons, improve the gui apperance in lots of small places 6. serveral improve to support 7. support AMS auto-mapping 8. disable lots of unstable features: such as params table, media file download, HMS 9. fix serveral kinds of bugs 10. update the document of building 11. ...
1374 lines
54 KiB
C++
1374 lines
54 KiB
C++
#include "PresetComboBoxes.hpp"
|
|
|
|
#include <cstddef>
|
|
#include <vector>
|
|
#include <string>
|
|
#include <boost/algorithm/string.hpp>
|
|
|
|
#include <wx/sizer.h>
|
|
#include <wx/stattext.h>
|
|
#include <wx/textctrl.h>
|
|
#include <wx/button.h>
|
|
#include <wx/statbox.h>
|
|
#include <wx/colordlg.h>
|
|
#include <wx/wupdlock.h>
|
|
#include <wx/menu.h>
|
|
#include <wx/odcombo.h>
|
|
#include <wx/listbook.h>
|
|
|
|
#ifdef _WIN32
|
|
#include <wx/msw/dcclient.h>
|
|
#include <wx/msw/private.h>
|
|
#endif
|
|
|
|
#include "libslic3r/libslic3r.h"
|
|
#include "libslic3r/PrintConfig.hpp"
|
|
#include "libslic3r/PresetBundle.hpp"
|
|
|
|
#include "GUI.hpp"
|
|
#include "GUI_App.hpp"
|
|
#include "Plater.hpp"
|
|
#include "MainFrame.hpp"
|
|
#include "format.hpp"
|
|
#include "Tab.hpp"
|
|
#include "ConfigWizard.hpp"
|
|
#include "../Utils/ASCIIFolding.hpp"
|
|
#include "../Utils/FixModelByWin10.hpp"
|
|
#include "../Utils/UndoRedo.hpp"
|
|
#include "BitmapCache.hpp"
|
|
#include "SavePresetDialog.hpp"
|
|
#include "MsgDialog.hpp"
|
|
#include "ParamsDialog.hpp"
|
|
|
|
// A workaround for a set of issues related to text fitting into gtk widgets:
|
|
#if defined(__WXGTK20__) || defined(__WXGTK3__)
|
|
#include <glib-2.0/glib-object.h>
|
|
#include <pango-1.0/pango/pango-layout.h>
|
|
#include <gtk/gtk.h>
|
|
#endif
|
|
|
|
using Slic3r::GUI::format_wxstr;
|
|
|
|
namespace Slic3r {
|
|
namespace GUI {
|
|
|
|
#define BORDER_W 10
|
|
|
|
// ---------------------------------
|
|
// *** PresetComboBox ***
|
|
// ---------------------------------
|
|
|
|
/* For PresetComboBox we use bitmaps that are created from images that are already scaled appropriately for Retina
|
|
* (Contrary to the intuition, the `scale` argument for Bitmap's constructor doesn't mean
|
|
* "please scale this to such and such" but rather
|
|
* "the wxImage is already sized for backing scale such and such". )
|
|
* Unfortunately, the constructor changes the size of wxBitmap too.
|
|
* Thus We need to use unscaled size value for bitmaps that we use
|
|
* to avoid scaled size of control items.
|
|
* For this purpose control drawing methods and
|
|
* control size calculation methods (virtual) are overridden.
|
|
**/
|
|
|
|
PresetComboBox::PresetComboBox(wxWindow* parent, Preset::Type preset_type, const wxSize& size, PresetBundle* preset_bundle/* = nullptr*/) :
|
|
::ComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, size, 0, nullptr, wxCB_READONLY),
|
|
m_type(preset_type),
|
|
m_last_selected(wxNOT_FOUND),
|
|
m_em_unit(em_unit(this)),
|
|
m_preset_bundle(preset_bundle ? preset_bundle : wxGetApp().preset_bundle)
|
|
{
|
|
#ifdef __WXMSW__
|
|
if (preset_type == Preset::TYPE_FILAMENT)
|
|
SetFont(Label::Body_13);
|
|
#endif // __WXMSW__
|
|
|
|
switch (m_type)
|
|
{
|
|
case Preset::TYPE_PRINT: {
|
|
m_collection = &m_preset_bundle->prints;
|
|
m_main_bitmap_name = "cog";
|
|
break;
|
|
}
|
|
case Preset::TYPE_FILAMENT: {
|
|
m_collection = &m_preset_bundle->filaments;
|
|
m_main_bitmap_name = "spool";
|
|
break;
|
|
}
|
|
case Preset::TYPE_SLA_PRINT: {
|
|
m_collection = &m_preset_bundle->sla_prints;
|
|
m_main_bitmap_name = "cog";
|
|
break;
|
|
}
|
|
case Preset::TYPE_SLA_MATERIAL: {
|
|
m_collection = &m_preset_bundle->sla_materials;
|
|
m_main_bitmap_name = "blank_16";
|
|
break;
|
|
}
|
|
case Preset::TYPE_PRINTER: {
|
|
m_collection = &m_preset_bundle->printers;
|
|
m_main_bitmap_name = "printer";
|
|
break;
|
|
}
|
|
default: break;
|
|
}
|
|
|
|
m_bitmapCompatible = ScalableBitmap(this, "flag_green");
|
|
m_bitmapIncompatible = ScalableBitmap(this, "flag_red");
|
|
|
|
// parameters for an icon's drawing
|
|
fill_width_height();
|
|
|
|
Bind(wxEVT_MOUSEWHEEL, [this](wxMouseEvent& e) {
|
|
if (m_suppress_change)
|
|
e.StopPropagation();
|
|
else
|
|
e.Skip();
|
|
});
|
|
Bind(wxEVT_COMBOBOX_DROPDOWN, [this](wxCommandEvent&) { m_suppress_change = false; });
|
|
Bind(wxEVT_COMBOBOX_CLOSEUP, [this](wxCommandEvent&) { m_suppress_change = true; });
|
|
|
|
Bind(wxEVT_COMBOBOX, &PresetComboBox::OnSelect, this);
|
|
}
|
|
|
|
void PresetComboBox::OnSelect(wxCommandEvent& evt)
|
|
{
|
|
// Under OSX: in case of use of a same names written in different case (like "ENDER" and "Ender")
|
|
// m_presets_choice->GetSelection() will return first item, because search in PopupListCtrl is case-insensitive.
|
|
// So, use GetSelection() from event parameter
|
|
auto selected_item = evt.GetSelection();
|
|
|
|
auto marker = reinterpret_cast<Marker>(this->GetClientData(selected_item));
|
|
if (marker >= LABEL_ITEM_DISABLED && marker < LABEL_ITEM_MAX)
|
|
this->SetSelection(m_last_selected);
|
|
else if (on_selection_changed && (m_last_selected != selected_item || m_collection->current_is_dirty())) {
|
|
m_last_selected = selected_item;
|
|
on_selection_changed(selected_item);
|
|
evt.StopPropagation();
|
|
}
|
|
evt.Skip();
|
|
}
|
|
|
|
PresetComboBox::~PresetComboBox()
|
|
{
|
|
}
|
|
|
|
BitmapCache& PresetComboBox::bitmap_cache()
|
|
{
|
|
static BitmapCache bmps;
|
|
return bmps;
|
|
}
|
|
|
|
void PresetComboBox::set_label_marker(int item, LabelItemType label_item_type)
|
|
{
|
|
this->SetClientData(item, (void*)label_item_type);
|
|
}
|
|
|
|
bool PresetComboBox::set_printer_technology(PrinterTechnology pt)
|
|
{
|
|
if (printer_technology != pt) {
|
|
printer_technology = pt;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void PresetComboBox::invalidate_selection()
|
|
{
|
|
m_last_selected = INT_MAX; // this value means that no one item is selected
|
|
}
|
|
|
|
void PresetComboBox::validate_selection(bool predicate/*=false*/)
|
|
{
|
|
if (predicate ||
|
|
// just in case: mark m_last_selected as a first added element
|
|
m_last_selected == INT_MAX)
|
|
m_last_selected = GetCount() - 1;
|
|
}
|
|
|
|
void PresetComboBox::update_selection()
|
|
{
|
|
/* If selected_preset_item is still equal to INT_MAX, it means that
|
|
* there is no presets added to the list.
|
|
* So, select last combobox item ("Add/Remove preset")
|
|
*/
|
|
validate_selection();
|
|
|
|
SetSelection(m_last_selected);
|
|
#ifdef __WXMSW__
|
|
// From the Windows 2004 the tooltip for preset combobox doesn't work after next call of SetTooltip()
|
|
// (There was an issue, when tooltip doesn't appears after changing of the preset selection)
|
|
// But this workaround seems to work: We should to kill tooltip and than set new tooltip value
|
|
SetToolTip(NULL);
|
|
#endif
|
|
SetToolTip(GetString(m_last_selected));
|
|
|
|
// A workaround for a set of issues related to text fitting into gtk widgets:
|
|
#if defined(__WXGTK20__) || defined(__WXGTK3__)
|
|
GList* cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(m_widget));
|
|
|
|
// 'cells' contains the GtkCellRendererPixBuf for the icon,
|
|
// 'cells->next' contains GtkCellRendererText for the text we need to ellipsize
|
|
if (!cells || !cells->next) return;
|
|
|
|
auto cell = static_cast<GtkCellRendererText *>(cells->next->data);
|
|
|
|
if (!cell) return;
|
|
|
|
g_object_set(G_OBJECT(cell), "ellipsize", PANGO_ELLIPSIZE_END, (char*)NULL);
|
|
|
|
// Only the list of cells must be freed, the renderer isn't ours to free
|
|
g_list_free(cells);
|
|
#endif
|
|
}
|
|
|
|
int PresetComboBox::update_ams_color()
|
|
{
|
|
if (m_filament_idx < 0) return -1;
|
|
int idx = selected_ams_filament();
|
|
if (idx < 0) return -1;
|
|
DynamicPrintConfig *cfg = &wxGetApp().preset_bundle->project_config;
|
|
auto colors = static_cast<ConfigOptionStrings*>(cfg->option("filament_colour")->clone());
|
|
colors->values[m_filament_idx] = wxGetApp().preset_bundle->filament_ams_list[idx]
|
|
.opt_string("filament_colour", 0u);
|
|
DynamicPrintConfig new_cfg;
|
|
new_cfg.set_key_value("filament_colour", colors);
|
|
cfg->apply(new_cfg);
|
|
wxGetApp().plater()->on_config_change(new_cfg);
|
|
//trigger the filament color changed
|
|
wxCommandEvent *evt = new wxCommandEvent(EVT_FILAMENT_COLOR_CHANGED);
|
|
wxQueueEvent(wxGetApp().plater(), evt);
|
|
return idx;
|
|
}
|
|
|
|
static std::string suffix(const Preset& preset)
|
|
{
|
|
return (preset.is_dirty ? Preset::suffix_modified() : "");
|
|
}
|
|
|
|
static std::string suffix(Preset* preset)
|
|
{
|
|
return (preset->is_dirty ? Preset::suffix_modified() : "");
|
|
}
|
|
|
|
wxColor PresetComboBox::different_color(wxColor const &clr)
|
|
{
|
|
if (clr.GetLuminance() < 0.51) return *wxWHITE;
|
|
return *wxBLACK;
|
|
}
|
|
|
|
wxString PresetComboBox::get_tooltip(const Preset &preset)
|
|
{
|
|
wxString tooltip = from_u8(preset.name);
|
|
// BBS: FIXME
|
|
#if 0
|
|
if (m_type == Preset::TYPE_FILAMENT) {
|
|
int temperature[4] = { 0,0,0,0 };
|
|
if (preset.config.has("nozzle_temperature_initial_layer")) //get the nozzle_temperature_initial_layer
|
|
temperature[0] = preset.config.opt_int("nozzle_temperature_initial_layer", 0);
|
|
if (preset.config.has("nozzle_temperature")) //get the nozzle temperature
|
|
temperature[1] = preset.config.opt_int("nozzle_temperature", 0);
|
|
if (preset.config.has("bed_temperature_initial_layer")) //get the bed_temperature_initial_layer
|
|
temperature[2] = preset.config.opt_int("bed_temperature_initial_layer", 0);
|
|
if (preset.config.has("bed_temperature")) //get the bed_temperature
|
|
temperature[3] = preset.config.opt_int("bed_temperature", 0);
|
|
|
|
tooltip += wxString::Format("\nNozzle First Layer:%d, Other Layer:%d\n Bed First Layer:%d, Other Layers:%d",
|
|
temperature[0], temperature[1], temperature[2], temperature[3]);
|
|
}
|
|
#endif
|
|
return tooltip;
|
|
}
|
|
|
|
wxString PresetComboBox::get_preset_name(const Preset & preset)
|
|
{
|
|
return from_u8(preset.name/* + suffix(preset)*/);
|
|
}
|
|
|
|
void PresetComboBox::update(std::string select_preset_name)
|
|
{
|
|
Freeze();
|
|
Clear();
|
|
invalidate_selection();
|
|
|
|
const std::deque<Preset>& presets = m_collection->get_presets();
|
|
|
|
std::map<wxString, std::pair<wxBitmap*, bool>> nonsys_presets;
|
|
std::map<wxString, wxBitmap*> incomp_presets;
|
|
|
|
wxString selected = "";
|
|
if (!presets.front().is_visible)
|
|
set_label_marker(Append(separator(L("System presets")), wxNullBitmap));
|
|
|
|
for (size_t i = presets.front().is_visible ? 0 : m_collection->num_default_presets(); i < presets.size(); ++i)
|
|
{
|
|
const Preset& preset = presets[i];
|
|
if (!m_show_all && (!preset.is_visible || !preset.is_compatible))
|
|
continue;
|
|
|
|
// marker used for disable incompatible printer models for the selected physical printer
|
|
bool is_enabled = m_type == Preset::TYPE_PRINTER && printer_technology != ptAny ? preset.printer_technology() == printer_technology : true;
|
|
if (select_preset_name.empty() && is_enabled)
|
|
select_preset_name = preset.name;
|
|
|
|
std::string bitmap_key = "cb";
|
|
if (m_type == Preset::TYPE_PRINTER) {
|
|
bitmap_key += "_printer";
|
|
if (preset.printer_technology() == ptSLA)
|
|
bitmap_key += "_sla";
|
|
}
|
|
std::string main_icon_name = m_type == Preset::TYPE_PRINTER && preset.printer_technology() == ptSLA ? "printer" : m_main_bitmap_name;
|
|
|
|
wxBitmap* bmp = get_bmp(bitmap_key, main_icon_name, "unlock_normal", is_enabled, preset.is_compatible, preset.is_system || preset.is_default);
|
|
assert(bmp);
|
|
|
|
if (!is_enabled)
|
|
incomp_presets.emplace(get_preset_name(preset), bmp);
|
|
else if (preset.is_default || preset.is_system)
|
|
{
|
|
Append(get_preset_name(preset), *bmp);
|
|
validate_selection(preset.name == select_preset_name);
|
|
}
|
|
else
|
|
{
|
|
nonsys_presets.emplace(get_preset_name(preset), std::pair<wxBitmap*, bool>(bmp, is_enabled));
|
|
if (preset.name == select_preset_name || (select_preset_name.empty() && is_enabled))
|
|
selected = get_preset_name(preset);
|
|
}
|
|
if (i + 1 == m_collection->num_default_presets())
|
|
set_label_marker(Append(separator(L("System presets")), wxNullBitmap));
|
|
}
|
|
if (!nonsys_presets.empty())
|
|
{
|
|
set_label_marker(Append(separator(L("User presets")), wxNullBitmap));
|
|
for (std::map<wxString, std::pair<wxBitmap*, bool>>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) {
|
|
int item_id = Append(it->first, *it->second.first);
|
|
bool is_enabled = it->second.second;
|
|
if (!is_enabled)
|
|
set_label_marker(item_id, LABEL_ITEM_DISABLED);
|
|
validate_selection(it->first == selected);
|
|
}
|
|
}
|
|
if (!incomp_presets.empty())
|
|
{
|
|
set_label_marker(Append(separator(L("Incompatible presets")), wxNullBitmap));
|
|
for (std::map<wxString, wxBitmap*>::iterator it = incomp_presets.begin(); it != incomp_presets.end(); ++it) {
|
|
set_label_marker(Append(it->first, *it->second), LABEL_ITEM_DISABLED);
|
|
}
|
|
}
|
|
|
|
update_selection();
|
|
Thaw();
|
|
}
|
|
|
|
void PresetComboBox::show_all(bool show_all)
|
|
{
|
|
m_show_all = show_all;
|
|
update();
|
|
}
|
|
|
|
void PresetComboBox::update()
|
|
{
|
|
this->update(into_u8(this->GetString(this->GetSelection())));
|
|
}
|
|
|
|
void PresetComboBox::update_from_bundle()
|
|
{
|
|
this->update(m_collection->get_selected_preset().name);
|
|
}
|
|
|
|
void PresetComboBox::add_ams_filaments(std::string selected, bool alias_name)
|
|
{
|
|
if (!m_preset_bundle->filament_ams_list.empty()) {
|
|
set_label_marker(Append(separator(L("AMS filaments")), wxNullBitmap));
|
|
m_first_ams_filament = GetCount();
|
|
auto &filaments = m_collection->get_presets();
|
|
for (auto &f : m_preset_bundle->filament_ams_list) {
|
|
std::string setting_id = f.opt_string("filament_settings_id", 0u);
|
|
auto iter = std::find_if(filaments.begin(), filaments.end(),
|
|
[&setting_id](auto &f) { return f.is_compatible && f.is_system && f.filament_id == setting_id; });
|
|
if (iter == filaments.end())
|
|
continue;
|
|
const_cast<Preset&>(*iter).is_visible = true;
|
|
auto color = f.opt_string("filament_colour", 0u);
|
|
wxColour clr(color);
|
|
wxImage img(16, 16);
|
|
if (clr.Red() > 224 && clr.Blue() > 224 && clr.Green() > 224) {
|
|
img.SetRGB(wxRect({0, 0}, img.GetSize()), 128, 128, 128);
|
|
img.SetRGB(wxRect({1, 1}, img.GetSize() - wxSize{2, 2}), clr.Red(), clr.Green(), clr.Blue());
|
|
} else {
|
|
img.SetRGB(wxRect({0, 0}, img.GetSize()), clr.Red(), clr.Green(), clr.Blue());
|
|
}
|
|
int item_id = Append(get_preset_name(*iter), img);
|
|
//validate_selection(id->value == selected); // can not select
|
|
}
|
|
m_last_ams_filament = GetCount();
|
|
}
|
|
}
|
|
|
|
int PresetComboBox::selected_ams_filament() const
|
|
{
|
|
if (m_first_ams_filament && m_last_selected >= m_first_ams_filament && m_last_selected < m_last_ams_filament) {
|
|
return m_last_selected - m_first_ams_filament;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void PresetComboBox::msw_rescale()
|
|
{
|
|
m_em_unit = em_unit(this);
|
|
Rescale();
|
|
|
|
m_bitmapIncompatible.msw_rescale();
|
|
m_bitmapCompatible.msw_rescale();
|
|
|
|
// parameters for an icon's drawing
|
|
fill_width_height();
|
|
|
|
// update the control to redraw the icons
|
|
update();
|
|
}
|
|
|
|
void PresetComboBox::sys_color_changed()
|
|
{
|
|
wxGetApp().UpdateDarkUI(this);
|
|
msw_rescale();
|
|
}
|
|
|
|
void PresetComboBox::fill_width_height()
|
|
{
|
|
// To avoid asserts, each added bitmap to wxBitmapCombobox should be the same size, so
|
|
// set a bitmap's height to m_bitmapCompatible->GetHeight() and norm_icon_width to m_bitmapCompatible->GetWidth()
|
|
icon_height = m_bitmapCompatible.GetBmpHeight();
|
|
norm_icon_width = m_bitmapCompatible.GetBmpWidth();
|
|
|
|
/* It's supposed that standard size of an icon is 16px*16px for 100% scaled display.
|
|
* So set sizes for solid_colored icons used for filament preset
|
|
* and scale them in respect to em_unit value
|
|
*/
|
|
const float scale_f = (float)m_em_unit * 0.1f;
|
|
|
|
thin_icon_width = lroundf(8 * scale_f); // analogue to 8px;
|
|
wide_icon_width = norm_icon_width + thin_icon_width;
|
|
|
|
space_icon_width = lroundf(2 * scale_f);
|
|
thin_space_icon_width = lroundf(4 * scale_f);
|
|
wide_space_icon_width = lroundf(6 * scale_f);
|
|
}
|
|
|
|
wxString PresetComboBox::separator(const std::string& label)
|
|
{
|
|
return wxString::FromUTF8(separator_head()) + _(label) + wxString::FromUTF8(separator_tail());
|
|
}
|
|
|
|
wxBitmap* PresetComboBox::get_bmp( std::string bitmap_key, bool wide_icons, const std::string& main_icon_name,
|
|
bool is_compatible/* = true*/, bool is_system/* = false*/, bool is_single_bar/* = false*/,
|
|
const std::string& filament_rgb/* = ""*/, const std::string& extruder_rgb/* = ""*/, const std::string& material_rgb/* = ""*/)
|
|
{
|
|
// BBS: no icon
|
|
#if 1
|
|
static wxBitmap bmp;
|
|
return &bmp;
|
|
#else
|
|
// If the filament preset is not compatible and there is a "red flag" icon loaded, show it left
|
|
// to the filament color image.
|
|
if (wide_icons)
|
|
bitmap_key += is_compatible ? ",cmpt" : ",ncmpt";
|
|
|
|
bitmap_key += is_system ? ",syst" : ",nsyst";
|
|
bitmap_key += ",h" + std::to_string(icon_height);
|
|
bool dark_mode = wxGetApp().dark_mode();
|
|
if (dark_mode)
|
|
bitmap_key += ",dark";
|
|
bitmap_key += material_rgb;
|
|
|
|
wxBitmap* bmp = bitmap_cache().find(bitmap_key);
|
|
if (bmp == nullptr) {
|
|
// Create the bitmap with color bars.
|
|
std::vector<wxBitmap> bmps;
|
|
if (wide_icons)
|
|
// Paint a red flag for incompatible presets.
|
|
bmps.emplace_back(is_compatible ? bitmap_cache().mkclear(norm_icon_width, icon_height) : m_bitmapIncompatible.bmp());
|
|
|
|
if (m_type == Preset::TYPE_FILAMENT && !filament_rgb.empty())
|
|
{
|
|
// BBS
|
|
#if 0
|
|
unsigned char rgb[3];
|
|
// Paint the color bars.
|
|
bitmap_cache().parse_color(filament_rgb, rgb);
|
|
bmps.emplace_back(bitmap_cache().mksolid(is_single_bar ? wide_icon_width : norm_icon_width, icon_height, rgb, false, 1, dark_mode));
|
|
if (!is_single_bar) {
|
|
bitmap_cache().parse_color(extruder_rgb, rgb);
|
|
bmps.emplace_back(bitmap_cache().mksolid(thin_icon_width, icon_height, rgb, false, 1, dark_mode));
|
|
}
|
|
#endif
|
|
// Paint a lock at the system presets.
|
|
bmps.emplace_back(bitmap_cache().mkclear(space_icon_width, icon_height));
|
|
}
|
|
else
|
|
{
|
|
// BBS
|
|
#if 0
|
|
// Paint the color bars.
|
|
bmps.emplace_back(bitmap_cache().mkclear(thin_space_icon_width, icon_height));
|
|
if (m_type == Preset::TYPE_SLA_MATERIAL)
|
|
bmps.emplace_back(create_scaled_bitmap(main_icon_name, this, 16, false, material_rgb));
|
|
else
|
|
bmps.emplace_back(create_scaled_bitmap(main_icon_name));
|
|
#endif
|
|
// Paint a lock at the system presets.
|
|
bmps.emplace_back(bitmap_cache().mkclear(wide_space_icon_width, icon_height));
|
|
}
|
|
bmps.emplace_back(is_system ? create_scaled_bitmap("unlock_normal") : bitmap_cache().mkclear(norm_icon_width, icon_height));
|
|
bmp = bitmap_cache().insert(bitmap_key, bmps);
|
|
}
|
|
|
|
return bmp;
|
|
#endif
|
|
}
|
|
|
|
wxBitmap* PresetComboBox::get_bmp( std::string bitmap_key, const std::string& main_icon_name, const std::string& next_icon_name,
|
|
bool is_enabled/* = true*/, bool is_compatible/* = true*/, bool is_system/* = false*/)
|
|
{
|
|
// BBS: no icon
|
|
#if 1
|
|
static wxBitmap bmp;
|
|
return &bmp;
|
|
#else
|
|
bitmap_key += !is_enabled ? "_disabled" : "";
|
|
bitmap_key += is_compatible ? ",cmpt" : ",ncmpt";
|
|
bitmap_key += is_system ? ",syst" : ",nsyst";
|
|
bitmap_key += ",h" + std::to_string(icon_height);
|
|
if (wxGetApp().dark_mode())
|
|
bitmap_key += ",dark";
|
|
|
|
wxBitmap* bmp = bitmap_cache().find(bitmap_key);
|
|
if (bmp == nullptr) {
|
|
// Create the bitmap with color bars.
|
|
std::vector<wxBitmap> bmps;
|
|
bmps.emplace_back(m_type == Preset::TYPE_PRINTER ? create_scaled_bitmap(main_icon_name, this, 16, !is_enabled) :
|
|
is_compatible ? m_bitmapCompatible.bmp() : m_bitmapIncompatible.bmp());
|
|
// Paint a lock at the system presets.
|
|
bmps.emplace_back(is_system ? create_scaled_bitmap(next_icon_name, this, 16, !is_enabled) : bitmap_cache().mkclear(norm_icon_width, icon_height));
|
|
bmp = bitmap_cache().insert(bitmap_key, bmps);
|
|
}
|
|
|
|
return bmp;
|
|
#endif
|
|
}
|
|
|
|
bool PresetComboBox::is_selected_physical_printer()
|
|
{
|
|
auto selected_item = this->GetSelection();
|
|
auto marker = reinterpret_cast<Marker>(this->GetClientData(selected_item));
|
|
return marker == LABEL_ITEM_PHYSICAL_PRINTER;
|
|
}
|
|
|
|
bool PresetComboBox::selection_is_changed_according_to_physical_printers()
|
|
{
|
|
if (m_type != Preset::TYPE_PRINTER || !is_selected_physical_printer())
|
|
return false;
|
|
|
|
PhysicalPrinterCollection& physical_printers = m_preset_bundle->physical_printers;
|
|
|
|
std::string selected_string = this->GetString(this->GetSelection()).ToUTF8().data();
|
|
|
|
std::string old_printer_full_name, old_printer_preset;
|
|
if (physical_printers.has_selection()) {
|
|
old_printer_full_name = physical_printers.get_selected_full_printer_name();
|
|
old_printer_preset = physical_printers.get_selected_printer_preset_name();
|
|
}
|
|
else
|
|
old_printer_preset = m_collection->get_edited_preset().name;
|
|
// Select related printer preset on the Printer Settings Tab
|
|
physical_printers.select_printer(selected_string);
|
|
std::string preset_name = physical_printers.get_selected_printer_preset_name();
|
|
|
|
// if new preset wasn't selected, there is no need to call update preset selection
|
|
if (old_printer_preset == preset_name) {
|
|
// we need just to update according Plater<->Tab PresetComboBox
|
|
if (dynamic_cast<PlaterPresetComboBox*>(this)!=nullptr) {
|
|
wxGetApp().get_tab(m_type)->update_preset_choice();
|
|
// Synchronize config.ini with the current selections.
|
|
m_preset_bundle->export_selections(*wxGetApp().app_config);
|
|
}
|
|
else if (dynamic_cast<TabPresetComboBox*>(this)!=nullptr)
|
|
wxGetApp().sidebar().update_presets(m_type);
|
|
|
|
this->update();
|
|
return true;
|
|
}
|
|
|
|
Tab* tab = wxGetApp().get_tab(Preset::TYPE_PRINTER);
|
|
if (tab)
|
|
tab->select_preset(preset_name, false, old_printer_full_name);
|
|
return true;
|
|
}
|
|
|
|
// ---------------------------------
|
|
// *** PlaterPresetComboBox ***
|
|
// ---------------------------------
|
|
|
|
PlaterPresetComboBox::PlaterPresetComboBox(wxWindow *parent, Preset::Type preset_type) :
|
|
PresetComboBox(parent, preset_type, wxSize(15 * wxGetApp().em_unit(), 3 * wxGetApp().em_unit()))
|
|
{
|
|
GetDropDown().SetUseContentWidth(true);
|
|
|
|
if (m_type == Preset::TYPE_FILAMENT)
|
|
{
|
|
// BBS: not show color picker
|
|
#if 0
|
|
Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &event) {
|
|
const Preset* selected_preset = m_collection->find_preset(m_preset_bundle->filament_presets[m_filament_idx]);
|
|
// Wide icons are shown if the currently selected preset is not compatible with the current printer,
|
|
// and red flag is drown in front of the selected preset.
|
|
bool wide_icons = selected_preset && !selected_preset->is_compatible;
|
|
float scale = m_em_unit*0.1f;
|
|
|
|
int shifl_Left = wide_icons ? int(scale * 16 + 0.5) : 0;
|
|
#if defined(wxBITMAPCOMBOBOX_OWNERDRAWN_BASED)
|
|
shifl_Left += int(scale * 4 + 0.5f); // IMAGE_SPACING_RIGHT = 4 for wxBitmapComboBox -> Space left of image
|
|
#endif
|
|
int icon_right_pos = shifl_Left + int(scale * (24+4) + 0.5);
|
|
int mouse_pos = event.GetLogicalPosition(wxClientDC(this)).x;
|
|
if (mouse_pos < shifl_Left || mouse_pos > icon_right_pos ) {
|
|
// Let the combo box process the mouse click.
|
|
event.Skip();
|
|
return;
|
|
}
|
|
|
|
// BBS
|
|
// Swallow the mouse click and open the color picker.
|
|
//change_extruder_color();
|
|
});
|
|
#endif
|
|
}
|
|
|
|
// BBS
|
|
if (m_type == Preset::TYPE_FILAMENT) {
|
|
int em = wxGetApp().em_unit();
|
|
clr_picker = new wxButton(parent, wxID_ANY, "", wxDefaultPosition, wxSize(FromDIP(20), FromDIP(20)), wxBU_EXACTFIT | wxBORDER_NONE);
|
|
clr_picker->SetToolTip(_L("Click to pick filament color"));
|
|
clr_picker->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e) {
|
|
m_clrData.SetColour(clr_picker->GetBackgroundColour());
|
|
m_clrData.SetChooseFull(true);
|
|
m_clrData.SetChooseAlpha(false);
|
|
|
|
wxColourDialog dialog(this, &m_clrData);
|
|
dialog.SetTitle("Please choose the filament colour");
|
|
if ( dialog.ShowModal() == wxID_OK )
|
|
{
|
|
m_clrData = dialog.GetColourData();
|
|
|
|
// get current color
|
|
DynamicPrintConfig* cfg = &wxGetApp().preset_bundle->project_config;
|
|
auto colors = static_cast<ConfigOptionStrings*>(cfg->option("filament_colour")->clone());
|
|
wxColour clr(colors->values[m_filament_idx]);
|
|
if (!clr.IsOk())
|
|
clr = wxColour(0, 0, 0); // Don't set alfa to transparence
|
|
|
|
colors->values[m_filament_idx] = m_clrData.GetColour().GetAsString(wxC2S_HTML_SYNTAX).ToStdString();
|
|
DynamicPrintConfig cfg_new = *cfg;
|
|
cfg_new.set_key_value("filament_colour", colors);
|
|
|
|
//wxGetApp().get_tab(Preset::TYPE_PRINTER)->load_config(cfg_new);
|
|
cfg->apply(cfg_new);
|
|
wxGetApp().plater()->update_project_dirty_from_presets();
|
|
update();
|
|
wxGetApp().plater()->on_config_change(cfg_new);
|
|
|
|
wxCommandEvent *evt = new wxCommandEvent(EVT_FILAMENT_COLOR_CHANGED);
|
|
wxQueueEvent(wxGetApp().plater(), evt);
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
edit_btn = new ScalableButton(parent, wxID_ANY, "cog");
|
|
edit_btn->SetToolTip(_L("Click to edit preset"));
|
|
|
|
edit_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent)
|
|
{
|
|
// In a case of a physical printer, for its editing open PhysicalPrinterDialog
|
|
if (m_type == Preset::TYPE_PRINTER
|
|
#ifdef __linux__
|
|
// To edit extruder color from the sidebar
|
|
|| m_type == Preset::TYPE_FILAMENT
|
|
#endif //__linux__
|
|
)
|
|
show_edit_menu();
|
|
else
|
|
switch_to_tab();
|
|
});
|
|
}
|
|
}
|
|
|
|
PlaterPresetComboBox::~PlaterPresetComboBox()
|
|
{
|
|
if (edit_btn)
|
|
edit_btn->Destroy();
|
|
|
|
// BBS.
|
|
if (clr_picker)
|
|
clr_picker->Destroy();
|
|
}
|
|
|
|
static void run_wizard(ConfigWizard::StartPage sp)
|
|
{
|
|
wxGetApp().run_wizard(ConfigWizard::RR_USER, sp);
|
|
}
|
|
|
|
void PlaterPresetComboBox::OnSelect(wxCommandEvent &evt)
|
|
{
|
|
auto selected_item = evt.GetSelection();
|
|
|
|
auto marker = reinterpret_cast<Marker>(this->GetClientData(selected_item));
|
|
if (marker >= LABEL_ITEM_MARKER && marker < LABEL_ITEM_MAX) {
|
|
this->SetSelection(m_last_selected);
|
|
evt.StopPropagation();
|
|
if (marker == LABEL_ITEM_MARKER)
|
|
return;
|
|
if (marker == LABEL_ITEM_WIZARD_PRINTERS)
|
|
show_add_menu();
|
|
else {
|
|
ConfigWizard::StartPage sp = ConfigWizard::SP_WELCOME;
|
|
switch (marker) {
|
|
case LABEL_ITEM_WIZARD_FILAMENTS: sp = ConfigWizard::SP_FILAMENTS; break;
|
|
case LABEL_ITEM_WIZARD_MATERIALS: sp = ConfigWizard::SP_MATERIALS; break;
|
|
default: break;
|
|
}
|
|
wxTheApp->CallAfter([sp]() { run_wizard(sp); });
|
|
}
|
|
return;
|
|
} else if (marker == LABEL_ITEM_PHYSICAL_PRINTER || m_last_selected != selected_item || m_collection->current_is_dirty()) {
|
|
m_last_selected = selected_item;
|
|
if (m_type == Preset::TYPE_FILAMENT)
|
|
update_ams_color();
|
|
}
|
|
|
|
evt.Skip();
|
|
}
|
|
|
|
void PlaterPresetComboBox::switch_to_tab()
|
|
{
|
|
Tab* tab = wxGetApp().get_tab(m_type);
|
|
if (!tab)
|
|
return;
|
|
|
|
//BBS Select NoteBook Tab params
|
|
if (tab->GetParent() == wxGetApp().params_panel())
|
|
wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor);
|
|
else
|
|
wxGetApp().params_dialog()->Popup();
|
|
tab->restore_last_select_item();
|
|
|
|
const Preset* selected_filament_preset = nullptr;
|
|
if (m_type == Preset::TYPE_FILAMENT)
|
|
{
|
|
const std::string& selected_preset = GetString(GetSelection()).ToUTF8().data();
|
|
if (!boost::algorithm::ends_with(selected_preset, Preset::suffix_modified()))
|
|
{
|
|
const std::string& preset_name = wxGetApp().preset_bundle->filaments.get_preset_name_by_alias(selected_preset);
|
|
wxGetApp().get_tab(m_type)->select_preset(preset_name);
|
|
wxGetApp().get_tab(m_type)->get_combo_box()->set_filament_idx(m_filament_idx);
|
|
}
|
|
}
|
|
|
|
/*
|
|
if (int page_id = wxGetApp().tab_panel()->FindPage(tab); page_id != wxNOT_FOUND)
|
|
{
|
|
wxGetApp().tab_panel()->SetSelection(page_id);
|
|
// Switch to Settings NotePad
|
|
wxGetApp().mainframe->select_tab();
|
|
|
|
//In a case of a multi-material printing, for editing another Filament Preset
|
|
//it's needed to select this preset for the "Filament settings" Tab
|
|
if (m_type == Preset::TYPE_FILAMENT && wxGetApp().extruders_edited_cnt() > 1)
|
|
{
|
|
const std::string& selected_preset = GetString(GetSelection()).ToUTF8().data();
|
|
// Call select_preset() only if there is new preset and not just modified
|
|
if (!boost::algorithm::ends_with(selected_preset, Preset::suffix_modified()))
|
|
{
|
|
const std::string& preset_name = wxGetApp().preset_bundle->filaments.get_preset_name_by_alias(selected_preset);
|
|
wxGetApp().get_tab(m_type)->select_preset(preset_name);
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
void PlaterPresetComboBox::change_extruder_color()
|
|
{
|
|
// get current color
|
|
DynamicPrintConfig* cfg = &wxGetApp().preset_bundle->project_config;
|
|
auto colors = static_cast<ConfigOptionStrings*>(cfg->option("filament_colour")->clone());
|
|
wxColour clr(colors->values[m_filament_idx]);
|
|
if (!clr.IsOk())
|
|
clr = wxColour(0, 0, 0); // Don't set alfa to transparence
|
|
|
|
auto data = new wxColourData();
|
|
data->SetChooseFull(1);
|
|
data->SetColour(clr);
|
|
|
|
wxColourDialog dialog(this, data);
|
|
dialog.CenterOnParent();
|
|
if (dialog.ShowModal() == wxID_OK)
|
|
{
|
|
colors->values[m_filament_idx] = dialog.GetColourData().GetColour().GetAsString(wxC2S_HTML_SYNTAX).ToStdString();
|
|
|
|
DynamicPrintConfig cfg_new = *cfg;
|
|
cfg_new.set_key_value("filament_colour", colors);
|
|
|
|
wxGetApp().get_tab(Preset::TYPE_PRINTER)->load_config(cfg_new);
|
|
this->update();
|
|
wxGetApp().plater()->on_config_change(cfg_new);
|
|
}
|
|
}
|
|
|
|
void PlaterPresetComboBox::show_add_menu()
|
|
{
|
|
wxMenu* menu = new wxMenu();
|
|
|
|
append_menu_item(menu, wxID_ANY, _L("Add/Remove presets"), "",
|
|
[](wxCommandEvent&) {
|
|
wxTheApp->CallAfter([]() { run_wizard(ConfigWizard::SP_PRINTERS); });
|
|
}, "menu_edit_preset", menu, []() { return true; }, wxGetApp().plater());
|
|
|
|
wxGetApp().plater()->PopupMenu(menu);
|
|
}
|
|
|
|
void PlaterPresetComboBox::show_edit_menu()
|
|
{
|
|
wxMenu* menu = new wxMenu();
|
|
|
|
append_menu_item(menu, wxID_ANY, _L("Edit preset"), "",
|
|
[this](wxCommandEvent&) { this->switch_to_tab(); }, "cog", menu, []() { return true; }, wxGetApp().plater());
|
|
|
|
#ifdef __linux__
|
|
// To edit extruder color from the sidebar
|
|
if (m_type == Preset::TYPE_FILAMENT) {
|
|
append_menu_item(menu, wxID_ANY, _devL("Change extruder color"), "",
|
|
[this](wxCommandEvent&) { this->change_extruder_color(); }, "blank_14", menu, []() { return true; }, wxGetApp().plater());
|
|
wxGetApp().plater()->PopupMenu(menu);
|
|
return;
|
|
}
|
|
#endif //__linux__
|
|
|
|
append_menu_item(menu, wxID_ANY, _L("Add/Remove presets"), "",
|
|
[](wxCommandEvent&) {
|
|
wxTheApp->CallAfter([]() { run_wizard(ConfigWizard::SP_PRINTERS); });
|
|
}, "menu_edit_preset", menu, []() { return true; }, wxGetApp().plater());
|
|
|
|
wxGetApp().plater()->PopupMenu(menu);
|
|
}
|
|
|
|
wxString PlaterPresetComboBox::get_preset_name(const Preset& preset)
|
|
{
|
|
std::string name = preset.alias.empty() ? preset.name : preset.alias;
|
|
return from_u8(name + suffix(preset));
|
|
}
|
|
|
|
// Only the compatible presets are shown.
|
|
// If an incompatible preset is selected, it is shown as well.
|
|
void PlaterPresetComboBox::update()
|
|
{
|
|
if (m_type == Preset::TYPE_FILAMENT &&
|
|
(m_preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA ||
|
|
m_preset_bundle->filament_presets.size() <= (size_t)m_filament_idx) )
|
|
return;
|
|
|
|
// Otherwise fill in the list from scratch.
|
|
this->Freeze();
|
|
this->Clear();
|
|
invalidate_selection();
|
|
|
|
const Preset* selected_filament_preset = nullptr;
|
|
std::string filament_color;
|
|
if (m_type == Preset::TYPE_FILAMENT)
|
|
{
|
|
//unsigned char rgb[3];
|
|
filament_color = m_preset_bundle->project_config.opt_string("filament_colour", (unsigned int) m_filament_idx);
|
|
//if (!bitmap_cache().parse_color(filament_color, rgb))
|
|
// // Extruder color is not defined.
|
|
// filament_color.clear();
|
|
// BBS
|
|
wxColor clr(filament_color);
|
|
clr_picker->SetBackgroundColour(clr);
|
|
auto style = clr_picker->GetWindowStyle() & ~(wxBORDER_NONE | wxBORDER_SIMPLE);
|
|
auto diff_clr = different_color(clr);
|
|
clr_picker->SetWindowStyle(clr.Red() > 224 && clr.Blue() > 224 && clr.Green() > 224 ? (style | wxBORDER_SIMPLE) : (style | wxBORDER_NONE));
|
|
clr_picker->SetForegroundColour(diff_clr);
|
|
selected_filament_preset = m_collection->find_preset(m_preset_bundle->filament_presets[m_filament_idx]);
|
|
if (!selected_filament_preset) {
|
|
//can not find this filament, should be caused by project embedded presets, will be updated later
|
|
return;
|
|
}
|
|
//assert(selected_filament_preset);
|
|
}
|
|
|
|
bool has_selection = m_collection->get_selected_idx() != size_t(-1);
|
|
const Preset* selected_preset = m_type == Preset::TYPE_FILAMENT ? selected_filament_preset : has_selection ? &m_collection->get_selected_preset() : nullptr;
|
|
// Show wide icons if the currently selected preset is not compatible with the current printer,
|
|
// and draw a red flag in front of the selected preset.
|
|
bool wide_icons = selected_preset && !selected_preset->is_compatible;
|
|
|
|
std::map<wxString, wxBitmap*> nonsys_presets;
|
|
//BBS: add project embedded presets logic
|
|
std::map<wxString, wxBitmap*> project_embedded_presets;
|
|
std::map<wxString, wxBitmap*> system_presets;
|
|
|
|
//BBS: move system to the end
|
|
wxString selected_system_preset;
|
|
wxString selected_user_preset;
|
|
wxString tooltip;
|
|
const std::deque<Preset>& presets = m_collection->get_presets();
|
|
|
|
//BBS: move system to the end
|
|
/*if (!presets.front().is_visible)
|
|
this->set_label_marker(this->Append(separator(L("System presets")), wxNullBitmap));*/
|
|
|
|
for (size_t i = presets.front().is_visible ? 0 : m_collection->num_default_presets(); i < presets.size(); ++i)
|
|
{
|
|
const Preset& preset = presets[i];
|
|
bool is_selected = m_type == Preset::TYPE_FILAMENT ?
|
|
m_preset_bundle->filament_presets[m_filament_idx] == preset.name :
|
|
// The case, when some physical printer is selected
|
|
m_type == Preset::TYPE_PRINTER && m_preset_bundle->physical_printers.has_selection() ? false :
|
|
i == m_collection->get_selected_idx();
|
|
|
|
if (!preset.is_visible || (!preset.is_compatible && !is_selected))
|
|
continue;
|
|
|
|
std::string bitmap_key, filament_rgb, extruder_rgb, material_rgb;
|
|
std::string bitmap_type_name = bitmap_key = m_type == Preset::TYPE_PRINTER && preset.printer_technology() == ptSLA ? "sla_printer" : m_main_bitmap_name;
|
|
|
|
bool single_bar = false;
|
|
if (m_type == Preset::TYPE_FILAMENT)
|
|
{
|
|
#if 0
|
|
// Assign an extruder color to the selected item if the extruder color is defined.
|
|
filament_rgb = is_selected ? selected_filament_preset->config.opt_string("filament_colour", 0) :
|
|
preset.config.opt_string("filament_colour", 0);
|
|
extruder_rgb = (is_selected && !filament_color.empty()) ? filament_color : filament_rgb;
|
|
single_bar = filament_rgb == extruder_rgb;
|
|
|
|
bitmap_key += single_bar ? filament_rgb : filament_rgb + extruder_rgb;
|
|
#endif
|
|
}
|
|
else if (m_type == Preset::TYPE_SLA_MATERIAL) {
|
|
material_rgb = is_selected ? m_preset_bundle->sla_materials.get_edited_preset().config.opt_string("material_colour") : preset.config.opt_string("material_colour");
|
|
if (material_rgb.empty())
|
|
material_rgb = print_config_def.get("material_colour")->get_default_value<ConfigOptionString>()->value;
|
|
}
|
|
|
|
wxBitmap* bmp = get_bmp(bitmap_key, wide_icons, bitmap_type_name,
|
|
preset.is_compatible, preset.is_system || preset.is_default,
|
|
single_bar, filament_rgb, extruder_rgb, material_rgb);
|
|
assert(bmp);
|
|
|
|
const std::string name = preset.alias.empty() ? preset.name : preset.alias;
|
|
if (preset.is_default || preset.is_system) {
|
|
//BBS: move system to the end
|
|
system_presets.emplace(wxString::FromUTF8((name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()), bmp);
|
|
if (is_selected) {
|
|
tooltip = get_tooltip(preset);
|
|
selected_system_preset = wxString::FromUTF8((name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str());
|
|
}
|
|
//Append(get_preset_name(preset), *bmp);
|
|
//validate_selection(is_selected);
|
|
//if (is_selected)
|
|
//BBS set tooltip
|
|
// tooltip = get_tooltip(preset);
|
|
}
|
|
//BBS: add project embedded preset logic
|
|
else if (preset.is_project_embedded)
|
|
{
|
|
project_embedded_presets.emplace(wxString::FromUTF8((name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()), bmp);
|
|
if (is_selected) {
|
|
selected_user_preset = wxString::FromUTF8((name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str());
|
|
tooltip = wxString::FromUTF8(preset.name.c_str());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
nonsys_presets.emplace(get_preset_name(preset), bmp);
|
|
if (is_selected) {
|
|
selected_user_preset = get_preset_name(preset);
|
|
//BBS set tooltip
|
|
tooltip = get_tooltip(preset);
|
|
}
|
|
}
|
|
//BBS: move system to the end
|
|
//if (i + 1 == m_collection->num_default_presets())
|
|
// set_label_marker(Append(separator(L("System presets")), wxNullBitmap));
|
|
}
|
|
|
|
if (m_type == Preset::TYPE_FILAMENT)
|
|
add_ams_filaments(into_u8(selected_user_preset), true);
|
|
|
|
//BBS: add project embedded preset logic
|
|
if (!project_embedded_presets.empty())
|
|
{
|
|
set_label_marker(Append(separator(L("Project-inside presets")), wxNullBitmap));
|
|
for (std::map<wxString, wxBitmap*>::iterator it = project_embedded_presets.begin(); it != project_embedded_presets.end(); ++it) {
|
|
Append(it->first, *it->second);
|
|
validate_selection(it->first == selected_user_preset);
|
|
}
|
|
}
|
|
if (!nonsys_presets.empty())
|
|
{
|
|
set_label_marker(Append(separator(L("User presets")), wxNullBitmap));
|
|
for (std::map<wxString, wxBitmap*>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) {
|
|
Append(it->first, *it->second);
|
|
validate_selection(it->first == selected_user_preset);
|
|
}
|
|
}
|
|
//BBS: move system to the end
|
|
if (!system_presets.empty())
|
|
{
|
|
set_label_marker(Append(separator(L("System presets")), wxNullBitmap));
|
|
for (std::map<wxString, wxBitmap*>::iterator it = system_presets.begin(); it != system_presets.end(); ++it) {
|
|
Append(it->first, *it->second);
|
|
validate_selection(it->first == selected_system_preset);
|
|
}
|
|
}
|
|
|
|
//BBS: remove unused pysical printer logic
|
|
/*if (m_type == Preset::TYPE_PRINTER)
|
|
{
|
|
// add Physical printers, if any exists
|
|
if (!m_preset_bundle->physical_printers.empty()) {
|
|
set_label_marker(Append(separator(L("Physical printers")), wxNullBitmap));
|
|
const PhysicalPrinterCollection& ph_printers = m_preset_bundle->physical_printers;
|
|
|
|
for (PhysicalPrinterCollection::ConstIterator it = ph_printers.begin(); it != ph_printers.end(); ++it) {
|
|
for (const std::string& preset_name : it->get_preset_names()) {
|
|
Preset* preset = m_collection->find_preset(preset_name);
|
|
if (!preset || !preset->is_visible)
|
|
continue;
|
|
std::string main_icon_name, bitmap_key = main_icon_name = preset->printer_technology() == ptSLA ? "sla_printer" : m_main_bitmap_name;
|
|
wxBitmap* bmp = get_bmp(main_icon_name, wide_icons, main_icon_name);
|
|
assert(bmp);
|
|
|
|
set_label_marker(Append(from_u8(it->get_full_name(preset_name) + suffix(preset)), *bmp), LABEL_ITEM_PHYSICAL_PRINTER);
|
|
validate_selection(ph_printers.is_selected(it, preset_name));
|
|
}
|
|
}
|
|
}
|
|
}*/
|
|
|
|
//if (m_type == Preset::TYPE_PRINTER || m_type == Preset::TYPE_FILAMENT || m_type == Preset::TYPE_SLA_MATERIAL) {
|
|
// wxBitmap* bmp = get_bmp("edit_preset_list", wide_icons, "edit_uni");
|
|
// assert(bmp);
|
|
|
|
// if (m_type == Preset::TYPE_FILAMENT)
|
|
// set_label_marker(Append(separator(L("Add/Remove filaments")), *bmp), LABEL_ITEM_WIZARD_FILAMENTS);
|
|
// else if (m_type == Preset::TYPE_SLA_MATERIAL)
|
|
// set_label_marker(Append(separator(L("Add/Remove materials")), *bmp), LABEL_ITEM_WIZARD_MATERIALS);
|
|
// else
|
|
// set_label_marker(Append(separator(L("Add/Remove printers")), *bmp), LABEL_ITEM_WIZARD_PRINTERS);
|
|
//}
|
|
|
|
update_selection();
|
|
Thaw();
|
|
|
|
if (!tooltip.IsEmpty()) {
|
|
#ifdef __WXMSW__
|
|
// From the Windows 2004 the tooltip for preset combobox doesn't work after next call of SetTooltip()
|
|
// (There was an issue, when tooltip doesn't appears after changing of the preset selection)
|
|
// But this workaround seems to work: We should to kill tooltip and than set new tooltip value
|
|
// See, https://groups.google.com/g/wx-users/c/mOEe3fgHrzk
|
|
SetToolTip(NULL);
|
|
#endif
|
|
SetToolTip(tooltip);
|
|
}
|
|
|
|
#ifdef __WXMSW__
|
|
// Use this part of code just on Windows to avoid of some layout issues on Linux
|
|
// Update control min size after rescale (changed Display DPI under MSW)
|
|
if (GetMinWidth() != 10 * m_em_unit)
|
|
SetMinSize(wxSize(10 * m_em_unit, GetSize().GetHeight()));
|
|
#endif //__WXMSW__
|
|
}
|
|
|
|
void PlaterPresetComboBox::msw_rescale()
|
|
{
|
|
PresetComboBox::msw_rescale();
|
|
SetMinSize({-1, 3 * m_em_unit});
|
|
|
|
if (clr_picker)
|
|
clr_picker->SetSize(20 * m_em_unit / 10, 20 * m_em_unit / 10);
|
|
// BBS
|
|
if (edit_btn != nullptr)
|
|
edit_btn->msw_rescale();
|
|
}
|
|
|
|
|
|
// ---------------------------------
|
|
// *** TabPresetComboBox ***
|
|
// ---------------------------------
|
|
|
|
TabPresetComboBox::TabPresetComboBox(wxWindow* parent, Preset::Type preset_type) :
|
|
// BBS: new layout
|
|
PresetComboBox(parent, preset_type, wxSize(20 * wxGetApp().em_unit(), -1))
|
|
{
|
|
}
|
|
|
|
void TabPresetComboBox::OnSelect(wxCommandEvent &evt)
|
|
{
|
|
// Under OSX: in case of use of a same names written in different case (like "ENDER" and "Ender")
|
|
// m_presets_choice->GetSelection() will return first item, because search in PopupListCtrl is case-insensitive.
|
|
// So, use GetSelection() from event parameter
|
|
auto selected_item = evt.GetSelection();
|
|
|
|
auto marker = reinterpret_cast<Marker>(this->GetClientData(selected_item));
|
|
if (marker >= LABEL_ITEM_DISABLED && marker < LABEL_ITEM_MAX) {
|
|
this->SetSelection(m_last_selected);
|
|
// BBS: Add/Remove filaments
|
|
ConfigWizard::StartPage sp = ConfigWizard::SP_WELCOME;
|
|
switch (marker) {
|
|
case LABEL_ITEM_WIZARD_PRINTERS: sp = ConfigWizard::SP_PRINTERS; break;
|
|
case LABEL_ITEM_WIZARD_FILAMENTS: sp = ConfigWizard::SP_FILAMENTS; break;
|
|
case LABEL_ITEM_WIZARD_MATERIALS: sp = ConfigWizard::SP_MATERIALS; break;
|
|
default: break;
|
|
}
|
|
if (sp != ConfigWizard::SP_WELCOME) {
|
|
wxTheApp->CallAfter([this, sp]() {
|
|
run_wizard(sp);
|
|
});
|
|
}
|
|
}
|
|
else if (on_selection_changed && (m_last_selected != selected_item || m_collection->current_is_dirty())) {
|
|
m_last_selected = selected_item;
|
|
// BBS: ams
|
|
update_ams_color();
|
|
on_selection_changed(selected_item);
|
|
}
|
|
|
|
evt.StopPropagation();
|
|
#ifdef __WXMSW__
|
|
// From the Win 2004 preset combobox lose a focus after change the preset selection
|
|
// and that is why the up/down arrow doesn't work properly
|
|
// So, set the focus to the combobox explicitly
|
|
this->SetFocus();
|
|
#endif
|
|
}
|
|
|
|
wxString TabPresetComboBox::get_preset_name(const Preset& preset)
|
|
{
|
|
return from_u8(preset.name + suffix(preset));
|
|
}
|
|
|
|
// Update the choice UI from the list of presets.
|
|
// If show_incompatible, all presets are shown, otherwise only the compatible presets are shown.
|
|
// If an incompatible preset is selected, it is shown as well.
|
|
void TabPresetComboBox::update()
|
|
{
|
|
Freeze();
|
|
Clear();
|
|
invalidate_selection();
|
|
|
|
const std::deque<Preset>& presets = m_collection->get_presets();
|
|
|
|
std::map<wxString, std::pair<wxBitmap*, bool>> nonsys_presets;
|
|
//BBS: add project embedded presets logic
|
|
std::map<wxString, std::pair<wxBitmap*, bool>> project_embedded_presets;
|
|
//BBS: move system to the end
|
|
std::map<wxString, std::pair<wxBitmap*, bool>> system_presets;
|
|
|
|
wxString selected = "";
|
|
//BBS: move system to the end
|
|
/*if (!presets.front().is_visible)
|
|
set_label_marker(Append(separator(L("System presets")), wxNullBitmap));*/
|
|
size_t idx_selected = m_collection->get_selected_idx();
|
|
|
|
if (m_type == Preset::TYPE_PRINTER && m_preset_bundle->physical_printers.has_selection()) {
|
|
std::string sel_preset_name = m_preset_bundle->physical_printers.get_selected_printer_preset_name();
|
|
Preset* preset = m_collection->find_preset(sel_preset_name);
|
|
if (!preset)
|
|
m_preset_bundle->physical_printers.unselect_printer();
|
|
}
|
|
|
|
for (size_t i = presets.front().is_visible ? 0 : m_collection->num_default_presets(); i < presets.size(); ++i)
|
|
{
|
|
const Preset& preset = presets[i];
|
|
if (!preset.is_visible || (!show_incompatible && !preset.is_compatible && i != idx_selected))
|
|
continue;
|
|
|
|
// marker used for disable incompatible printer models for the selected physical printer
|
|
bool is_enabled = true;
|
|
|
|
std::string bitmap_key = "tab";
|
|
if (m_type == Preset::TYPE_PRINTER) {
|
|
bitmap_key += "_printer";
|
|
if (preset.printer_technology() == ptSLA)
|
|
bitmap_key += "_sla";
|
|
}
|
|
std::string main_icon_name = m_type == Preset::TYPE_PRINTER && preset.printer_technology() == ptSLA ? "sla_printer" : m_main_bitmap_name;
|
|
|
|
wxBitmap* bmp = get_bmp(bitmap_key, main_icon_name, "unlock_normal", is_enabled, preset.is_compatible, preset.is_system || preset.is_default);
|
|
assert(bmp);
|
|
|
|
if (preset.is_default || preset.is_system) {
|
|
//BBS: move system to the end
|
|
system_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()), std::pair<wxBitmap*, bool>(bmp, is_enabled));
|
|
if (i == idx_selected)
|
|
selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str());
|
|
//int item_id = Append(get_preset_name(preset), *bmp);
|
|
//if (!is_enabled)
|
|
// set_label_marker(item_id, LABEL_ITEM_DISABLED);
|
|
//validate_selection(i == idx_selected);
|
|
}
|
|
//BBS: add project embedded preset logic
|
|
else if (preset.is_project_embedded)
|
|
{
|
|
//std::pair<wxBitmap*, bool> pair(bmp, is_enabled);
|
|
project_embedded_presets.emplace(wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()), std::pair<wxBitmap*, bool>(bmp, is_enabled));
|
|
if (i == idx_selected)
|
|
selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str());
|
|
}
|
|
else
|
|
{
|
|
std::pair<wxBitmap*, bool> pair(bmp, is_enabled);
|
|
nonsys_presets.emplace(get_preset_name(preset), std::pair<wxBitmap*, bool>(bmp, is_enabled));
|
|
if (i == idx_selected)
|
|
selected = get_preset_name(preset);
|
|
}
|
|
//BBS: move system to the end
|
|
//if (i + 1 == m_collection->num_default_presets())
|
|
// set_label_marker(Append(separator(L("System presets")), wxNullBitmap));
|
|
}
|
|
|
|
if (m_type == Preset::TYPE_FILAMENT)
|
|
add_ams_filaments(into_u8(selected));
|
|
|
|
//BBS: add project embedded preset logic
|
|
if (!project_embedded_presets.empty())
|
|
{
|
|
set_label_marker(Append(separator(L("Project-inside presets")), wxNullBitmap));
|
|
for (std::map<wxString, std::pair<wxBitmap*, bool>>::iterator it = project_embedded_presets.begin(); it != project_embedded_presets.end(); ++it) {
|
|
int item_id = Append(it->first, *it->second.first);
|
|
bool is_enabled = it->second.second;
|
|
if (!is_enabled)
|
|
set_label_marker(item_id, LABEL_ITEM_DISABLED);
|
|
validate_selection(it->first == selected);
|
|
}
|
|
}
|
|
if (!nonsys_presets.empty())
|
|
{
|
|
set_label_marker(Append(separator(L("User presets")), wxNullBitmap));
|
|
for (std::map<wxString, std::pair<wxBitmap*, bool>>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) {
|
|
int item_id = Append(it->first, *it->second.first);
|
|
bool is_enabled = it->second.second;
|
|
if (!is_enabled)
|
|
set_label_marker(item_id, LABEL_ITEM_DISABLED);
|
|
validate_selection(it->first == selected);
|
|
}
|
|
}
|
|
//BBS: move system to the end
|
|
if (!system_presets.empty())
|
|
{
|
|
set_label_marker(Append(separator(L("System presets")), wxNullBitmap));
|
|
for (std::map<wxString, std::pair<wxBitmap*, bool>>::iterator it = system_presets.begin(); it != system_presets.end(); ++it) {
|
|
int item_id = Append(it->first, *it->second.first);
|
|
bool is_enabled = it->second.second;
|
|
if (!is_enabled)
|
|
set_label_marker(item_id, LABEL_ITEM_DISABLED);
|
|
validate_selection(it->first == selected);
|
|
}
|
|
}
|
|
|
|
if (m_type == Preset::TYPE_PRINTER)
|
|
{
|
|
//BBS: remove unused pysical printer logic
|
|
/*// add Physical printers, if any exists
|
|
if (!m_preset_bundle->physical_printers.empty()) {
|
|
set_label_marker(Append(separator(L("Physical printers")), wxNullBitmap));
|
|
const PhysicalPrinterCollection& ph_printers = m_preset_bundle->physical_printers;
|
|
|
|
for (PhysicalPrinterCollection::ConstIterator it = ph_printers.begin(); it != ph_printers.end(); ++it) {
|
|
for (const std::string& preset_name : it->get_preset_names()) {
|
|
Preset* preset = m_collection->find_preset(preset_name);
|
|
if (!preset || !preset->is_visible)
|
|
continue;
|
|
std::string main_icon_name = preset->printer_technology() == ptSLA ? "sla_printer" : m_main_bitmap_name;
|
|
|
|
wxBitmap* bmp = get_bmp(main_icon_name, main_icon_name, "", true, true, false);
|
|
assert(bmp);
|
|
|
|
set_label_marker(Append(from_u8(it->get_full_name(preset_name) + suffix(preset)), *bmp), LABEL_ITEM_PHYSICAL_PRINTER);
|
|
validate_selection(ph_printers.is_selected(it, preset_name));
|
|
}
|
|
}
|
|
}*/
|
|
|
|
// add "Add/Remove printers" item
|
|
//std::string icon_name = "edit_uni";
|
|
//wxBitmap* bmp = get_bmp("edit_preset_list, tab,", icon_name, "");
|
|
//assert(bmp);
|
|
|
|
//set_label_marker(Append(separator(L("Add/Remove printers")), *bmp), LABEL_ITEM_WIZARD_PRINTERS);
|
|
}
|
|
|
|
// BBS Add/Remove filaments select
|
|
//wxBitmap* bmp = get_bmp("edit_preset_list", false, "edit_uni");
|
|
//assert(bmp);
|
|
//if (m_type == Preset::TYPE_FILAMENT)
|
|
// set_label_marker(Append(separator(L("Add/Remove filaments")), *bmp), LABEL_ITEM_WIZARD_FILAMENTS);
|
|
//else if (m_type == Preset::TYPE_SLA_MATERIAL)
|
|
// set_label_marker(Append(separator(L("Add/Remove materials")), *bmp), LABEL_ITEM_WIZARD_MATERIALS);
|
|
|
|
update_selection();
|
|
Thaw();
|
|
}
|
|
|
|
void TabPresetComboBox::msw_rescale()
|
|
{
|
|
PresetComboBox::msw_rescale();
|
|
// BBS: new layout
|
|
wxSize sz = wxSize(20 * m_em_unit, GetSize().GetHeight());
|
|
SetMinSize(sz);
|
|
SetSize(sz);
|
|
}
|
|
|
|
void TabPresetComboBox::update_dirty()
|
|
{
|
|
// 1) Update the dirty flag of the current preset.
|
|
m_collection->update_dirty();
|
|
|
|
// 2) Update the labels.
|
|
wxWindowUpdateLocker noUpdates(this);
|
|
for (unsigned int ui_id = 0; ui_id < GetCount(); ++ui_id) {
|
|
auto marker = reinterpret_cast<Marker>(this->GetClientData(ui_id));
|
|
if (marker >= LABEL_ITEM_MARKER)
|
|
continue;
|
|
|
|
std::string old_label = GetString(ui_id).utf8_str().data();
|
|
std::string preset_name = Preset::remove_suffix_modified(old_label);
|
|
std::string ph_printer_name;
|
|
|
|
if (marker == LABEL_ITEM_PHYSICAL_PRINTER) {
|
|
ph_printer_name = PhysicalPrinter::get_short_name(preset_name);
|
|
preset_name = PhysicalPrinter::get_preset_name(preset_name);
|
|
}
|
|
|
|
Preset* preset = m_collection->find_preset(preset_name, false);
|
|
if (preset) {
|
|
std::string new_label = preset->name + suffix(preset);
|
|
|
|
if (marker == LABEL_ITEM_PHYSICAL_PRINTER)
|
|
new_label = ph_printer_name + PhysicalPrinter::separator() + new_label;
|
|
|
|
if (old_label != new_label) {
|
|
SetString(ui_id, from_u8(new_label));
|
|
if (ui_id == GetSelection()) SetToolTip(wxString::FromUTF8(new_label.c_str())); // BBS
|
|
}
|
|
}
|
|
}
|
|
#ifdef __APPLE__
|
|
// wxWidgets on OSX do not upload the text of the combo box line automatically.
|
|
// Force it to update by re-selecting.
|
|
SetSelection(GetSelection());
|
|
#endif /* __APPLE __ */
|
|
}
|
|
|
|
}} // namespace Slic3r::GUI
|